<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Blog Symfony2 - Lexik Montpellier</title>
	
	<link>http://www.lexik.fr/blog/symfony</link>
	<description>Blog sur le développement Web PHP avec Symfony 2</description>
	<lastBuildDate>Thu, 02 Feb 2012 14:00:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/BlogSymfony-LexikMontpellier" /><feedburner:info uri="blogsymfony-lexikmontpellier" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><creativeCommons:license>http://creativecommons.org/licenses/by/2.0/</creativeCommons:license><feedburner:emailServiceId>BlogSymfony-LexikMontpellier</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Lexik recrute 2 développeurs PHP5 / Symfony2</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/7lyyL7QzhQQ/lexik-recrute-2-developpeurs-php5-symfony2-2009</link>
		<comments>http://www.lexik.fr/blog/symfony/recrutement/lexik-recrute-2-developpeurs-php5-symfony2-2009#comments</comments>
		<pubDate>Thu, 02 Feb 2012 14:00:26 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Lexik Life]]></category>
		<category><![CDATA[recrutement]]></category>
		<category><![CDATA[developpeur]]></category>
		<category><![CDATA[emploi]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Symfony2]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=2009</guid>
		<description><![CDATA[Description de la société : Lexik c&#8217;est qui ? Une société basée à Montpellier depuis 5 ans, avec 10 personnes et une ambiance sympa. On fait quoi chez Lexik ? Nous sommes spécialisés dans le développement d&#8217;applications web en Symfony2. &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/recrutement/lexik-recrute-2-developpeurs-php5-symfony2-2009">...</a></p>]]></description>
			<content:encoded><![CDATA[<h2>Description de la société :</h2>
<p><strong>Lexik c&#8217;est qui ?</strong><br />
Une société basée à Montpellier depuis 5 ans, avec 10 personnes et une ambiance sympa.</p>
<p><strong>On fait quoi chez Lexik ?</strong><br />
Nous sommes spécialisés dans le développement d&#8217;applications web en Symfony2. Nos projets reposent sur les méthodes agiles et un développement de qualité via la mise en place de tests unitaires et fonctionnels.<br />
<span id="more-2009"></span></p>
<p><strong>Quels types de clients ?</strong><br />
Des start-ups qui recherchent un appui technique sur la mise en place de leur projet, des PME et collectivités locales ayant un besoin d&#8217;accompagnement en conseil et réalisation.</p>
<p><strong>Lexik, c&#8217;est quoi d&#8217;autre ?</strong><br />
Des scrum meetings quotidiens, des points techniques presque tous les mardi, des idées communes pour des projets internes, du développement en équipe et comme dirait Laurent, le vendredi c&#8217;est sushis !</p>
<p><strong>Et si on résumait tout ça techniquement :</strong></p>
<ul>
<li>spécialistes du framework Symfony2 ;</li>
<li>contributions à des bundles Open Source sur <a href="https://github.com/lexik">Github</a> ;</li>
<li>un <a href="http://www.lexik.fr/blog/symfony/">blog technique</a> ;</li>
<li>développement frontend avec jQuery, Twitter Bootstrap, websockets, etc. ;</li>
<li>méthodes agiles avec Scrum ;</li>
<li>intégration continue avec Jenkins et tests fonctionnels avec Behat.</li>
</ul>
<h2>Description du poste :</h2>
<p>Vous êtes motivé et passionné par votre métier, vous suivez avec attention l&#8217;évolution des frameworks et des derniers langages à la mode. Vous avez déjà travaillé en équipe et vous aimez ça.</p>
<p>Vous bénéficiez d&#8217;une bonne expérience à titre privé ou professionnel dans les technologies suivantes :</p>
<ul>
<li>PHP 5.3, OOP ;</li>
<li>HTML5 / CSS3 ;</li>
<li>SQL (MySQL, SQLite, PostgreSQL, …).</li>
</ul>
<p>Une expérience ou un intérêt dans les domaines suivants seront un atout :</p>
<ul>
<li>Framework symfony 1.4 / Symfony2 avec l&#8217;ORM Doctrine ou Propel2 ;</li>
<li>Gestionnaire de version (Git / SVN) ;</li>
<li>Javascript, jQuery, node.js ;</li>
<li>Tests unitaires et fonctionnels, intégration continue, Behat ;</li>
<li>Méthodologie de développement agile (Scrum).</li>
</ul>
<h2>Détails :</h2>
<p><strong>Envoyez-nous votre CV et lettre de motivation par email à l&#8217;adresse : <a href="mailto:recrutement@lexik.fr">recrutement@lexik.fr</a></strong></p>
<ul>
<li>Type de contrat : CDI</li>
<li>Lieu : Pérols</li>
<li>Début du contrat : ASAP</li>
<li>Télétravail : non</li>
<li>Rémunération : selon profil</li>
</ul>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/7lyyL7QzhQQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/recrutement/lexik-recrute-2-developpeurs-php5-symfony2-2009/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/recrutement/lexik-recrute-2-developpeurs-php5-symfony2-2009</feedburner:origLink></item>
		<item>
		<title>Intégration de Magento et Symfony2</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/ZpQCiqgsQT4/integration-de-magento-et-symfony2-1935</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony2/integration-de-magento-et-symfony2-1935#comments</comments>
		<pubDate>Fri, 09 Dec 2011 09:40:42 +0000</pubDate>
		<dc:creator>Nicolas</dc:creator>
				<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[magento]]></category>
		<category><![CDATA[web service]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1935</guid>
		<description><![CDATA[Ayant à réaliser une boutique plutôt complexe, mais n’étant pas spécialistes du développement Magento, nous avons voulu tester l&#8217;association de Symfony2 en front end et Magento en back end. L&#8217;intégration de ces deux systèmes est intéressante à plus d&#8217;un titre. &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony2/integration-de-magento-et-symfony2-1935">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Ayant à réaliser une boutique plutôt complexe, mais n’étant pas spécialistes du développement Magento, nous avons voulu tester l&#8217;association de <strong>Symfony2 en front end</strong> et <strong>Magento en back end</strong>.</p>
<p>L&#8217;intégration de ces deux systèmes est intéressante à plus d&#8217;un titre. Vous souhaitez afficher une liste de produits stockés dans une boutique Magento ? Récupérer des commandes pour les traiter dans un ERP réalisé avec Symfony2 ? Ou pourquoi pas développer une boutique entière en vous concentrant uniquement sur la logique ?</p>
<p>Nous allons voir ici comment utiliser l&#8217;API de Magento depuis Symfony2 : à distance en utilisant le web service, ou en local en faisant directement appel au noyau Magento.<span id="more-1935"></span></p>
<h2>Le web service SOAP / XML-RPC</h2>
<p>A distance, le seul moyen d&#8217;échanger des données entre la boutique et un autre site est de passer par le web service. Son activation et ses possibilités sont très bien décrites dans <a title="Magento API" href="http://www.magentocommerce.com/support/magento_core_api">la documentation officielle</a> et sur <a title="Communauté Magento Francophone" href="http://www.wikigento.com/phpzendmagento/magento-le-web-service/">Wikigento</a>.</p>
<p>L&#8217;utilisation de base dans un controller ressemblerait au morceau de code suivant. Évidemment, dans l&#8217;idéal il faudrait créer un service pour ne pas avoir à se répéter d&#8217;une action à l&#8217;autre, et mettre en place un système de cache.</p>
<p><script type="text/javascript" src="https://gist.github.com/1423333.js?file=DefaultController.php"></script><br />
<script type="text/javascript" src="https://gist.github.com/1423333.js?file=index.html.twig"></script></p>
<h2>Le noyau Magento &laquo;&nbsp;Mage&nbsp;&raquo;</h2>
<p>Si Magento et Symfony2 sont sur le même serveur, le plus efficace reste encore l&#8217;utilisation directe du noyau. L&#8217;équipe <a title="Liip" href="http://blog.liip.ch/archive/2011/09/21/integrating-magento-into-symfony2.html">Liip</a> a réalisé un bundle permettant d&#8217;instancier le coeur de Magento et donc d&#8217;utiliser ses méthodes internes. Le <a href="https://github.com/liip/LiipMagentoBundle">LiipMagentoBundle</a> permet (à l&#8217;heure actuelle) :</p>
<ul>
<li>la connexion des utilisateurs Magento dans Symfony2</li>
<li>le partage des sessions utilisateurs</li>
<li>l&#8217;accès au contenu et même aux blocks Magento</li>
</ul>
<p>Une fois le bundle en place, l&#8217;application Symfony2 aura accès à toutes les données et méthodes du noyau Magento : création/édition/suppression de clients, produits et commandes, gestion du panier et des factures par Magento, l&#8217;accès au différents modes de livraison et de paiement&#8230;</p>
<h3>Exemple 1 : Affichage d&#8217;un block Magento</h3>
<p>Voir la documentation du <a href="https://github.com/liip/LiipMagentoBundle">LiipMagentoBundle.</a></p>
<h3>Exemple 2 : Récupération de données Magento</h3>
<p><script type="text/javascript" src="https://gist.github.com/1423237.js?file=DefaultController.php"></script><br />
<script type="text/javascript" src="https://gist.github.com/1423237.js?file=index.html.twig"></script></p>
<h2>Conclusion</h2>
<p>Au final, l&#8217;intégration des deux systèmes est relativement aisée. Si le web service est indispensable pour faire communiquer des sites distants, l’intérêt de son utilisation en local est plus limité : relativement lent, il ne donne pas accès à toutes les fonctions que l&#8217;on peut attendre (pour le moment).</p>
<p>L&#8217;utilisation du noyau Magento à travers le <a href="https://github.com/liip/LiipMagentoBundle">LiipMagentoBundle</a> pallie à ces limitations : vitesse d’exécution, partage de sessions, accès à toutes les méthodes existantes&#8230; Il ne reste plus qu&#8217;à s&#8217;occuper de la logique et de la présentation.</p>
<p>L&#8217;association Magento/Symfony2 semble très intéressante pour la mise en place d&#8217;une boutique rapide, si vous avez des retours d’expérience n&#8217;hésitez pas à nous en faire part. Nous ne manquerons pas d&#8217;en discuter si nous réalisons un site de cette façon.</p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/ZpQCiqgsQT4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony2/integration-de-magento-et-symfony2-1935/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/symfony2/integration-de-magento-et-symfony2-1935</feedburner:origLink></item>
		<item>
		<title>Un bundle de mise en maintenance pour vos sites avec Symfony2</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/fePs-5-qpD4/un-bundle-de-mise-en-maintenance-pour-vos-sites-avec-symfony2-1807</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony2/un-bundle-de-mise-en-maintenance-pour-vos-sites-avec-symfony2-1807#comments</comments>
		<pubDate>Wed, 09 Nov 2011 15:48:17 +0000</pubDate>
		<dc:creator>Gilles</dc:creator>
				<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[bundle]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1807</guid>
		<description><![CDATA[Présentation Voici le LexikMaintenanceBundle qui a pour but d&#8217;activer et désactiver la mise en maintenance de votre site. Quand un site à besoin pour X raisons d&#8217;être mis en maintenance, par exemple lors d&#8217;une mise à jour, vous allez pouvoir &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony2/un-bundle-de-mise-en-maintenance-pour-vos-sites-avec-symfony2-1807">...</a></p>]]></description>
			<content:encoded><![CDATA[<h3>Présentation</h3>
<p>Voici le <a href="https://github.com/lexik/LexikMaintenanceBundle" title="LexikMaintenanceBundle" target="_blank">LexikMaintenanceBundle</a> qui a pour but d&#8217;activer et désactiver la mise en maintenance de votre site. Quand un site à besoin pour X raisons d&#8217;être mis en maintenance, par exemple lors d&#8217;une mise à jour, vous allez pouvoir faire apparaître une page d&#8217;erreur où seront redirigés les visiteurs avec la possibilité d&#8217;en autoriser certains.<br />
<span id="more-1807"></span></p>
<h2>Pourquoi utiliser un bundle pour gérer la maintenance ?</h2>
<p>Il existe de nombreuses manières de mettre un site Internet en maintenance, comme par exemple en éditant le .htaccess ou le virtual host. Symfony 1 proposait une mise en maintenance en ligne de commande et cette fonctionnalité n&#8217;a pas été reprise dans sa version 2, l&#8217;idée de ce bundle est de proposer une fonctionnalité similaire tout en laissant plus de souplesse, via l&#8217;utilisation de drivers et d&#8217;un service.</p>
<p>Nous avons choisi de créer ce bundle car nous voulions laisser aux utilisateurs plusieurs alternatives de mise en maintenance, ainsi que son activation depuis la console ou depuis le backend par exemple.</p>
<h2>Fonctionnement</h2>
<h3>Un listener</h3>
<p>Le bundle utilise un listener qui écoute l’événement onKernelRequest avec une priorité evelée pour être ainsi le premier à être appelé. Le listener va tout d&#8217;abord vérifier s&#8217;il y a des adresses IP autorisées à consulter le site en maintenance. Si oui, l&#8217;utilisateur peut continuer. Dans le cas contraire on va demander au driver utilisé dans la configuration de vérifier si la maintenance a été activé et de décider si on lève une exception qui retournera un status 503. Sinon on laisse passer l&#8217;utilisateur.</p>
<h3>Des drivers</h3>
<p>Un driver est une méthode choisie pour activer/désactiver la maintenance. Le bundle propose trois drivers différents.</p>
<ul>
<li>Le premier est le FileDriver dont l&#8217;utilisation consiste à créer un fichier quelque part et à vérifier si celui-ci existe.</li>
<li>Le second est le MemCacheDriver qui utilise MemCache et qui va regarder si une donnée a été stockée dans le serveur de cache.</li>
<li>Le troisième est le DatabaseDriver qui va créer une table dans une base de données et vérifier les informations présentes à l&#8217;intérieur.</li>
</ul>
<blockquote><p>Il y a d&#8217;autres implémentation de drivers possibles, libre à chacun de créer le sien.</p>
</blockquote>
<h4>Options</h4>
<h5>TTL</h5>
<p>Chaque driver a la possibilité d&#8217;avoir un temps limite pour la durée de la maintenance -par défaut il n&#8217;y en a pas-. Cette option est le ttl -time to life- qui peut être modifié soit dans votre configuration soit dynamiquement via la console par exemple. (A l&#8217;exception du FileDriver).</p>
<h5>IP autorisées</h5>
<p>Vous avez la possibilité, comme écrit plus haut, d&#8217;ajouter dans un tableau des adresses IP qui seront autorisées à consulter le site.</p>
<h2>Installation et configuration</h2>
<p>L’installation se fait comme pour tous les autres bundle Symfony2 à l’aide des fichiers deps et deps.lock.</p>
<p>Fichier deps:</p>
<p><script src="https://gist.github.com/1350964.js?file=1-deps"></script></p>
<p>Enregistrer le namespace:</p>
<p><script src="https://gist.github.com/1350964.js?file=2-autoload.php"></script></p>
<p>Activer le bundle:</p>
<p><script src="https://gist.github.com/1350964.js?file=3-kernel.php"></script></p>
<p>Pour la configuration, les options de bases requises sont la classe du driver et les options qui iront avec.</p>
<p><script src="https://gist.github.com/1350964.js?file=4-config.yml"></script></p>
<p>Remarques pour la configuration:</p>
<ul>
<li>Pour utiliser la connexion Doctrine, vous n&#8217;êtes pas obligé de passer des options, vous pouvez écrire simplement le nom de la classe du driver.</li>
<li>Pour utiliser une table existante sur une autre base de données (option dsn), vous devez avoir un champ <strong>ttl</strong> dans votre table.</li>
<li>Pour le FileDriver, vous ne pouvez pas changer la durée en mode console, seulement pour DatabaseDriver et MemCacheDriver</li>
</ul>
<h2>Utilisation</h2>
<p>Ce service met à disposition les méthodes `lock()` et `unlock()` permettant d&#8217;activer et désactiver le mode maintenance de votre site. L&#8217;intérêt majeur de ce service est qu&#8217;il vous permet de l&#8217;utiliser dans le contexte de votre choix, libre à vous d&#8217;implémenter une interface de backend permettant d&#8217;activer la maintenance. <a href="https://github.com/lexik/LexikMaintenanceBundle" title="LexikMaintenanceBundle" target="_blank">LexikMaintenanceBundle</a> propose en standard les commandes console suivantes:</p>
<p><span style="text-decoration: underline;">lexik:maintenance:lock</span> qui aura pour effet d&#8217;appeler la méthode lock().</p>
<p><span style="text-decoration: underline;">lexik:maintenance:unlock</span> aura l&#8217;effet inverse.</p>
<h3>Pour la vue</h3>
<p>Element important de la maintenance, une page d&#8217;erreur à afficher. Lorsque le listener lève une exception avec le status 503, Symfony2 va afficher par défaut la vue error.html.twig située dans le bundle TwigBundle. Vous pouvez alors définir une vue appelée <strong>error503.html.twig</strong> dans app/Resources/TwigBundle/views/Exception/ qui sera appelée à la place.</p>
<blockquote><p>Astuce: Cela fonctionne aussi pour les erreurs 404, 403 etc&#8230;</p>
</blockquote>
<blockquote><p>Information: Nous ne proposons pas de vue par défaut, c&#8217;est à vous d&#8217;en créer une.</p>
</blockquote>
<p>Pour plus le reste, voici le lien vers les <a href="https://github.com/lexik/LexikMaintenanceBundle" title="LexikMaintenanceBundle" target="_blank">sources</a> Github.</p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/fePs-5-qpD4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony2/un-bundle-de-mise-en-maintenance-pour-vos-sites-avec-symfony2-1807/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/symfony2/un-bundle-de-mise-en-maintenance-pour-vos-sites-avec-symfony2-1807</feedburner:origLink></item>
		<item>
		<title>LexikTranslationBundle, pour éditer vos traductions avec Symfony2</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/-hL95x-1EFE/lexiktranslationbundle-pour-editer-vos-traductions-avec-symfony2-1753</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony2/lexiktranslationbundle-pour-editer-vos-traductions-avec-symfony2-1753#comments</comments>
		<pubDate>Fri, 28 Oct 2011 08:23:09 +0000</pubDate>
		<dc:creator>cedric</dc:creator>
				<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[bundle]]></category>
		<category><![CDATA[I18N]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1753</guid>
		<description><![CDATA[Bonjour à tous, voici le premier bundle Symfony2 made in Lexik, j&#8217;ai nommé LexikTranslationBundle. Le but de ce bundle est simple, pouvoir gérer le contenu des fichiers de traduction (xliff, yml, php) via la base de données afin de faciliter &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony2/lexiktranslationbundle-pour-editer-vos-traductions-avec-symfony2-1753">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Bonjour à tous, voici le premier bundle Symfony2 made in Lexik, j&#8217;ai nommé <a title="github LexikTranslationBundle" href="https://github.com/lexik/LexikTranslationBundle">LexikTranslationBundle</a>. Le but de ce bundle est simple, pouvoir gérer le contenu des fichiers de traduction (xliff, yml, php) via la base de données afin de faciliter l&#8217;édition les traductions sans avoir à mettre le nez dans le code source du projet.<span id="more-1753"></span></p>
<h2>Pourquoi utiliser la base de données ?</h2>
<p>En effet, pourquoi utiliser la base de données au lieu d&#8217;éditer directement les fichiers de traduction ? Lorsque votre site sera en production des modifications pourront être faites grâce à l&#8217;interface d&#8217;édition, cependant les développeurs seront potentiellement amenés à ajouter de nouvelles traductions dans les fichiers. Donc si on édite directement les fichiers de traduction un problème risque de se présenter: lors des mises en ligne, comment ajouter les nouvelles traductions sans perdre les modifications faites depuis l&#8217;interface d&#8217;édition ? (sans compter le fait que Apache devra avoir les droits en écriture sur les fichiers).<br />
C&#8217;est pour cela que nous avons choisi de charger les traductions en base de données. De cette façon l&#8217;administrateur du site peut modifier les traductions à son gré et les développeurs peuvent à tout moment ajouter de nouvelles entées dans les fichiers. </p>
<h2>Fonctionnement</h2>
<p>Le bundle redéfinit le service de traduction de Symfony (translator) et fournit un loader pour charger les traductions depuis la base de données.<br />
Les traductions présentes en base de données sont chargées en dernier, elles prennent donc le dessus sur les traductions des fichiers xliff, yml ou php. Le bundle fournit aussi une interface d&#8217;édition et d&#8217;ajout de traductions avec une intégration de <a title="jqGrid" href="http://www.trirand.com/blog/" target="_blank">jqGrid 4.2.0</a>.<br />
L&#8217;ajout de traduction dans la base de données se fait soit par l&#8217;interface, soit en ligne de commande avec une tâche qui va importer vos fichiers de traduction dans la base de données.</p>
<h2>Utilisation</h2>
<p>Lors de votre développement créez vos fichiers de traductions au moins pour une langue (la langue par défaut du site par exemple). Ensuite lancez la tâche d&#8217;import pour ajouter les nouvelles traductions en base de données. Une fois importées les traductions sont éditables dans l&#8217;interface, vous pouvez donc modifier les traductions pour toutes les langues gérées par le bundle.<br />
Une traduction n&#8217;est éditable que si elle est présente dans la base de données, donc si vous ajoutez de nouvelles entées dans vos fichiers de traduction il faudra relancer la tache d&#8217;import.</p>
<p><em>Note: lors de la modification d&#8217;une traduction via l&#8217;interface il sera nécessaire de cliquer sur le bouton &laquo;&nbsp;invalidate cache&nbsp;&raquo; afin de prendre en compte le changement de la traduction (surtout en environnement de production).</em></p>
<h2>Installation et configuration</h2>
<p>L&#8217;installation se fait comme pour tous les autres bundle Symfony2 à l&#8217;aide des fichiers <code>deps</code> et <code>deps.lock</code>.<br />
Au niveau de la configuration il vous faudra au minimum définir la langue par défaut (fallback_locale) et les langues que le bundle doit gérer (managed_locales), comme ci-dessous :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1753code2'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p17532"><td class="code" id="p1753code2"><pre class="yml" style="font-family:monospace;"># app/config/config.yml
lexik_translation:
    fallback_locale:  fr
    managed_locales:  [fr, en]</pre></td></tr></table></div>

<p>Il est aussi possible de configurer certaines classes utilisées par le bundle dans le cas où vous souhaitez redéfinir des éléments (entité et/ou service).</p>
<p>Pour plus de détail sur cette partie je vous invite à lire <a title="Doc LexikTranslationBundle" href="https://github.com/lexik/LexikTranslationBundle/blob/master/Resources/doc/index.md">la doc sur le dépot Github</a>.</p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/-hL95x-1EFE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony2/lexiktranslationbundle-pour-editer-vos-traductions-avec-symfony2-1753/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/symfony2/lexiktranslationbundle-pour-editer-vos-traductions-avec-symfony2-1753</feedburner:origLink></item>
		<item>
		<title>Symfony2: création d’un service</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/iCfUvBcP_44/symfony2-creation-dun-service-1690</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony2/symfony2-creation-dun-service-1690#comments</comments>
		<pubDate>Tue, 06 Sep 2011 12:20:50 +0000</pubDate>
		<dc:creator>Bérenger</dc:creator>
				<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[callback]]></category>
		<category><![CDATA[création]]></category>
		<category><![CDATA[events]]></category>
		<category><![CDATA[lifecycle]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1690</guid>
		<description><![CDATA[Bonjour, Nous allons voir dans cet article la mise en place d&#8217;un callback sur une entité dans symfony2. Contexte Nous allons ici prendre l&#8217;exemple d&#8217;un site de commande. Chaque commande a un statut et nous souhaitons enregistrer dans la base &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony2/symfony2-creation-dun-service-1690">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Bonjour,</p>
<p>Nous allons voir dans cet article la mise en place d&#8217;un callback sur une entité dans symfony2.</p>
<h2>Contexte</h2>
<p>Nous allons ici prendre l&#8217;exemple d&#8217;un site de commande. Chaque commande a un statut et nous souhaitons enregistrer dans la base de données chaque changement de statut afin de conserver un historique.</p>
<p>Pour cela, Symfony2 et Doctrine fournissent un ensemble d&#8217;actions pouvant être appelées à chaque étapes du cycle de vie d&#8217;une entité (&laquo;&nbsp;lifecycle&nbsp;&raquo;).<br />
<span id="more-1690"></span><br />
Vous trouverez à cette adresse l&#8217;ensemble des événements disponibles: <a href="http://www.doctrine-project.org/docs/orm/2.0/en/reference/events.html#lifecycle-events" target="_blank">Lifecycle Events</a></p>
<p>Dans notre cas, nous avons choisi d&#8217;effectuer la sauvegarde du statut après chaque mise à jour de notre entité Order (qui gère les commandes du site). Pour cela nous allons utiliser l’événement postUpdate qui sera appelé après chaque update de l&#8217;entité.</p>
<p>Voici, les deux objets concernés par ce service:</p>
<p>L&#8217;objet commande</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1690code8'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p16908"><td class="code" id="p1690code8"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Projet\OrderBundle\Entity\Order
 *
 * @ORM\Entity(repositoryClass=&quot;Projet\OrderBundle\Repository\OrderRepository&quot;)
 * @ORM\Table(name=&quot;Projet_order_order&quot;)
 * @ORM\HasLifecycleCallbacks
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Order
<span style="color: #009900;">&#123;</span>
     <span style="color: #009933; font-style: italic;">/**
     * @var integer $id
     *
     * @ORM\Column(name=&quot;id&quot;, type=&quot;integer&quot;)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy=&quot;AUTO&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$id</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @var Yatoo\UserBundle\Entity\User $user
     *
     * @ORM\ManyToOne(targetEntity=&quot;Yatoo\UserBundle\Entity\User&quot;, inversedBy=&quot;orders&quot;)
     * @ORM\JoinColumn(name=&quot;user_id&quot;, referencedColumnName=&quot;id&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$user</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @var string $comment
     *
     * @ORM\Column(name=&quot;title&quot;, type=&quot;string&quot;, length=255)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$title</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @var decimal $price
     *
     * @ORM\Column(name=&quot;price&quot;, type=&quot;decimal&quot;, length=&quot;7&quot;, scale=&quot;2&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$price</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @var integer $quantity
     *
     * @ORM\Column(name=&quot;quantity&quot;, type=&quot;integer&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$quantity</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @var Yatoo\CardBundle\Entity\Pricing $pricing
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$pricing</span><span style="color: #339933;">;</span>
&nbsp;
     <span style="color: #009933; font-style: italic;">/**
     * @var smallint $status
     *
     * @ORM\Column(name=&quot;status&quot;, type=&quot;smallint&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$status</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @var text $comment
     *
     * @ORM\Column(name=&quot;comment&quot;, type=&quot;text&quot;, nullable=&quot;true&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$comment</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @ORM\OneToMany(targetEntity=&quot;HistoricalStatus&quot;, mappedBy=&quot;order&quot;, cascade={&quot;all&quot;})
     * @ORM\JoinColumn(name=&quot;order_id&quot;, referencedColumnName=&quot;id&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$historicalStatus</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @Gedmo\Timestampable(on=&quot;create&quot;)
     * @ORM\Column(name=&quot;created_at&quot;, type=&quot;datetime&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$createdAt</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$statusOld</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #339933;">...</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p> Et HistoricalStatus qui servira à stocker l&#8217;historique des changements de statut des commandes.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1690code9'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p16909"><td class="code" id="p1690code9"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Projet\OrderBundle\Entity\HistoricalStatus
 *
 * @ORM\Entity(repositoryClass=&quot;Projet\OrderBundle\Repository\HistoricalStatusRepository&quot;)
 * @ORM\Table(name=&quot;Projet_order_historical_status&quot;)
 * @ORM\HasLifecycleCallbacks
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> HistoricalStatus
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
     * @var integer $id
     *
     * @ORM\Column(name=&quot;id&quot;, type=&quot;integer&quot;)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy=&quot;AUTO&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$id</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @var object $order
     *
     * @ORM\ManyToOne(targetEntity=&quot;Order&quot;, inversedBy=&quot;files&quot;)
     * @ORM\JoinColumn(name=&quot;order_id&quot;, referencedColumnName=&quot;id&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$order</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @var smallint $status
     *
     * @ORM\Column(name=&quot;status&quot;, type=&quot;smallint&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$status</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @var text $comment
     *
     * @ORM\Column(name=&quot;comment&quot;, type=&quot;text&quot;, nullable=&quot;true&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$comment</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @Gedmo\Timestampable(on=&quot;create&quot;)
     * @ORM\Column(name=&quot;created_at&quot;, type=&quot;datetime&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$createdAt</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #339933;">...</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h2>Mise en place</h2>
<p>Dans un premier temps, il faut créer le dossier Listener dans votre bundle.Dans notre exemple ce dossier se trouvera à l&#8217;adresse : repSite/src/Projet/OrderBundle/Listener puis créer le fichier OrderListener.php.</p>
<p>Voici pour exemple le code de notre service:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1690code10'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p169010"><td class="code" id="p1690code10"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">namespace</span> Projet\OrderBundle\Listener<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">use</span> Projet\OrderBundle\Entity\HistoricalStatus<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Projet\OrderBundle\Entity\Order<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">use</span> Doctrine\ORM\Event\LifecycleEventArgs<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> OrderListener
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> postUpdate<span style="color: #009900;">&#40;</span>LifecycleEventArgs <span style="color: #000088;">$args</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #000088;">$entity</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$args</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getEntity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$entityManager</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$args</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getEntityManager</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$entity</span> instanceof Order<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
            <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$entity</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOldStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #000088;">$entity</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getStatus<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$historicalStatus</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> HistoricalStatus<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$historicalStatus</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setOrder</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$entity</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$historicalStatus</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setComment</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$entity</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getComment<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$historicalStatus</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setStatus</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$entity</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getStatus<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$entityManager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">persist</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$historicalStatus</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$entityManager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">flush</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
      <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Pour expliquer rapidement ce que fait ce bout de code :</p>
<p>Si le statut de la commande a changé, on crée un nouveau statut historique et on l&#8217;enregistre.</p>
<p>La fonction $entity->getOldStatus() permet de récupérer l&#8217;ancien statut de la commande avant sa mise à jour. La valeur est initialisée à la création de l&#8217;objet dans le constructeur.</p>
<h2>Configuration</h2>
<p>Une fois votre listener écrit, il faut le configurer pour qu&#8217;il soit appelé. Pour cela, éditer simplement le fichier : Projet\OrderBundle\Ressources\config\services.xml et ajoutez y ces lignes:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1690code11'); return false;">View Code</a> XML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p169011"><td class="code" id="p1690code11"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;service</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;order.postUpdate&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;Projet\OrderBundle\Listener\OrderListener&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;tag</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;doctrine.event_listener&quot;</span> <span style="color: #000066;">event</span>=<span style="color: #ff0000;">&quot;postUpdate&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/service<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Vous pouvez aussi le déclarer en yml :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1690code12'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p169012"><td class="code" id="p1690code12"><pre class="yml" style="font-family:monospace;">services:
    order.postUpdate :
        class: Projet\OrderBundle\Listener\OrderListener
        tags:
            - { name: doctrine.event_listener, event: postUpdate }</pre></td></tr></table></div>

<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/iCfUvBcP_44" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony2/symfony2-creation-dun-service-1690/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/symfony2/symfony2-creation-dun-service-1690</feedburner:origLink></item>
		<item>
		<title>Apéro Web Montpellier – Jeudi 8 Septembre 2011</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/eskiVsGW1IE/apero-web-montpellier-jeudi-8-septembre-2011-1683</link>
		<comments>http://www.lexik.fr/blog/symfony/lexik-life/apero-web-montpellier-jeudi-8-septembre-2011-1683#comments</comments>
		<pubDate>Thu, 01 Sep 2011 12:03:02 +0000</pubDate>
		<dc:creator>Samuel Breton</dc:creator>
				<category><![CDATA[Lexik Life]]></category>
		<category><![CDATA[apero]]></category>
		<category><![CDATA[montpellier]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1683</guid>
		<description><![CDATA[Toi l&#8217;ami qui travaille dans le Web, rejoins nous à l&#8217;apéro Web de Montpellier : Date : Jeudi 8 Septembre Lieu : au Fitzpatrick&#8217;s Irish pub (Map) Heure : à partir de 18H30. Vous pensez venir, passez sur le Doodle! &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/lexik-life/apero-web-montpellier-jeudi-8-septembre-2011-1683">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Toi l&#8217;ami qui travaille dans le Web, rejoins nous à l&#8217;apéro Web de Montpellier :</p>
<p>Date : Jeudi 8 Septembre<br />
Lieu : au Fitzpatrick&#8217;s Irish pub (<a href="http://maps.google.fr/maps/place?hl=fr&amp;prmd=ivns&amp;prmdo=1&amp;bav=on.2,or.r_gc.r_pw.&amp;biw=1280&amp;bih=963&amp;um=1&amp;ie=UTF-8&amp;q=fitzpatrick+montpellier&amp;fb=1&amp;gl=fr&amp;hq=fitzpatrick&amp;hnear=0x12b6af0725dd9db1:0xad8756742894e802,Montpellier&amp;cid=9273875162430621950">Map</a>)<br />
Heure : à partir de 18H30.</p>
<p>Vous pensez venir, passez <a href="http://www.doodle.com/3xannd5r9vgwkxqr">sur le Doodle</a>!</p>
<p>Les apéros web ont pour objectif de donner un cadre d&#8217;échange aux acteurs du web. Que vous soyez développeurs, webdesigner, chef de projet agile ou non, au marketing, ou resp. d&#8217;entreprise les apéros web vous permettront de discuter hors contexte entreprise / travail de votre métier et pouvoir échanger librement sur vos problématiques.</p>
<p><a href="http://www.lexik.fr/blog/symfony/wp-content/uploads/2011/09/aperoLexik.jpg"><img class="size-full wp-image-1747 alignnone" title="aperoLexik" src="http://www.lexik.fr/blog/symfony/wp-content/uploads/2011/09/aperoLexik.jpg" alt="" width="600" height="337" /></a></p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/eskiVsGW1IE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/lexik-life/apero-web-montpellier-jeudi-8-septembre-2011-1683/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/lexik-life/apero-web-montpellier-jeudi-8-septembre-2011-1683</feedburner:origLink></item>
		<item>
		<title>Installation de SuPHP sur Ubuntu</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/NPtj6f7htng/installation-de-suphp-sur-ubuntu-1665</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/installation-de-suphp-sur-ubuntu-1665#comments</comments>
		<pubDate>Fri, 26 Aug 2011 08:00:40 +0000</pubDate>
		<dc:creator>laurent</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1665</guid>
		<description><![CDATA[Un problème récurrent pour beaucoup de développeurs utilisant Symfony est l&#8217;éternel conflit avec l&#8217;utilisateur &#171;&#160;www-data&#160;&#187; lors des accès, par exemple, aux fichiers du cache et aux logs. Sur Symfony 2 ce problème devient encore plus visible avec l&#8217;utilisation massive du &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony/installation-de-suphp-sur-ubuntu-1665">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Un problème récurrent pour beaucoup de développeurs utilisant Symfony est l&#8217;éternel conflit avec l&#8217;utilisateur &laquo;&nbsp;www-data&nbsp;&raquo; lors des accès, par exemple, aux fichiers du cache et aux logs. Sur Symfony 2 ce problème devient encore plus visible avec l&#8217;utilisation massive du répertoire cache même en environnement &laquo;&nbsp;dev&nbsp;&raquo;.</p>
<p>Le cas de conflit le plus flagrant est certainement le <code>app/console cache:clear</code> qui renvoie une erreur car le cache a été généré par www-data lors du chargement du site par apache. Le bon gros <code>sudo rm -rf app/cache/*</code> n&#8217;est pas une solution acceptable, tout juste une rustine.<span id="more-1665"></span></p>
<p>Il existe différents moyens d&#8217;éviter ces conflits, que ce soit via scripts personnalisés, configurations avancées, ou packages additionnels. SuPHP est un module pour Apache très facile à mettre en place pour un environnement de &laquo;&nbsp;dev&nbsp;&raquo;, et il va répondre à notre problème d&#8217;une manière très simple: Apache ne va plus éxécuter les sites via &#8216;www-data&#8217;, mais via l&#8217;utilisateur propriétaire des fichiers éxécutés, c&#8217;est-à-dire le plus souvent le compte du développeur.</p>
<p>L&#8217;installation comprend deux packages dispos sur synaptic ou directement depuis la console:</p>
<pre>sudo apt-get install suphp-common libapache2-mod-suphp</pre>
<p>Pour une station de dev, une configuration fonctionnelle et simple est très bien décrite sur <a href="http://doc.ubuntu-fr.org/suphp#installation_de_suphp">http://doc.ubuntu-fr.org/suphp#installation_de_suphp</a>. Cette configuration empêche l&#8217;intervention de suphp dans les répertoires de /usr/share pour permettre entre autres à phpmyadmin (dans son emplacement par défaut) de continuer à fonctionner sans problèmes.</p>
<p>Il faudra éventuellement supprimer les fichiers de sessions en cours appartenent encore à www-data (dans /var/lib/php5 par défaut).</p>
<p>Si vos projets ne sont pas stockés dans les répertoires /var/www ou ~/public_html, il faut éditer la valeur de &laquo;&nbsp;docroot&nbsp;&raquo; dans /etc/suphp/suphp.conf pour y ajouter les répertoires supplémentaires. Par exemple, mes projets sont dans ~/www/ :</p>
<pre>docroot=/var/www:${HOME}/public_html</pre>
<p>devient alors:</p>
<pre>docroot=/var/www:${HOME}/public_html:${HOME}/www</pre>
<p>Pensez à nettoyer vos fichiers appartenant encore à www-data (cette fois avec des <code>sudo rm</code> par contre), comme les répertoires cache et logs, et redémarrez simplement Apache (<code>sudo service apache2 restart</code>). Après ça vous ne devriez plus voir de www-data dans vos projets, et vous pourrez oublier ce mauvais réflexe du <code>sudo rm -rf</code> à tout bout de champ !</p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/NPtj6f7htng" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/installation-de-suphp-sur-ubuntu-1665/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/symfony/installation-de-suphp-sur-ubuntu-1665</feedburner:origLink></item>
		<item>
		<title>Symfony2 launch party à Montpellier</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/ZTfRBo-nwpw/symfony2-launch-party-a-montpellier-1655</link>
		<comments>http://www.lexik.fr/blog/symfony/lexik-life/symfony2-launch-party-a-montpellier-1655#comments</comments>
		<pubDate>Wed, 27 Jul 2011 16:58:21 +0000</pubDate>
		<dc:creator>Samuel Breton</dc:creator>
				<category><![CDATA[Lexik Life]]></category>
		<category><![CDATA[Symfony2]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1655</guid>
		<description><![CDATA[Fêtons de lancement de Symfony2 au Shakespeare A partir de 19H00 The Shakespeare Pub 12 Rue de la Petite Loge, 34000 Montpellier 04 67 60 22 25 ‎ Agrandir le plan]]></description>
			<content:encoded><![CDATA[<p><strong>Fêtons de lancement de Symfony2 au Shakespeare</strong></p>
<p>A partir de 19H00<br />
The Shakespeare Pub<br />
12 Rue de la Petite Loge, 34000 Montpellier<br />
04 67 60 22 25 ‎<br />
<span id="more-1655"></span><br />
<iframe src="http://maps.google.fr/maps?f=q&amp;source=s_q&amp;hl=fr&amp;geocode=&amp;q=Le+Shakespeare,+Rue+de+la+Petite+Loge,+Montpellier&amp;aq=1&amp;sll=46.75984,1.738281&amp;sspn=12.360483,19.753418&amp;ie=UTF8&amp;hq=Le+Shakespeare,&amp;hnear=Rue+de+la+Petite+Loge,+34000+Montpellier,+H%C3%A9rault,+Languedoc-Roussillon&amp;ll=43.610598,3.878507&amp;spn=0.006295,0.006295&amp;output=embed" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="425" height="350"></iframe><br />
<small><a style="color: #0000ff; text-align: left;" href="http://maps.google.fr/maps?f=q&amp;source=embed&amp;hl=fr&amp;geocode=&amp;q=Le+Shakespeare,+Rue+de+la+Petite+Loge,+Montpellier&amp;aq=1&amp;sll=46.75984,1.738281&amp;sspn=12.360483,19.753418&amp;ie=UTF8&amp;hq=Le+Shakespeare,&amp;hnear=Rue+de+la+Petite+Loge,+34000+Montpellier,+H%C3%A9rault,+Languedoc-Roussillon&amp;ll=43.610598,3.878507&amp;spn=0.006295,0.006295">Agrandir le plan</a></small></p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/ZTfRBo-nwpw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/lexik-life/symfony2-launch-party-a-montpellier-1655/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/lexik-life/symfony2-launch-party-a-montpellier-1655</feedburner:origLink></item>
		<item>
		<title>Géolocalisation ou comment créer ses propres fonctions DQL avec Doctrine2</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/HA2xWeOstc8/geolocalisation-ou-comment-creer-ses-propres-fonctions-dql-avec-doctrine2-1624</link>
		<comments>http://www.lexik.fr/blog/symfony/doctrine2/geolocalisation-ou-comment-creer-ses-propres-fonctions-dql-avec-doctrine2-1624#comments</comments>
		<pubDate>Mon, 25 Jul 2011 12:34:48 +0000</pubDate>
		<dc:creator>yoye</dc:creator>
				<category><![CDATA[doctrine2]]></category>
		<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Doctrine2]]></category>
		<category><![CDATA[DQL]]></category>
		<category><![CDATA[geolocalisation]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1624</guid>
		<description><![CDATA[Pour calculer les distances entre deux points géographiques il faut se baser sur leurs latitudes et longitudes. Lorsque l&#8217;on souhaite appliquer ce calcul en SQL on se retrouve avec une requête extrêmement verbeuse. Heureusement si vous utilisez Doctrine2 vous allez &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/doctrine2/geolocalisation-ou-comment-creer-ses-propres-fonctions-dql-avec-doctrine2-1624">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Pour calculer les distances entre deux points géographiques il faut se baser sur leurs latitudes et longitudes. Lorsque l&#8217;on souhaite appliquer ce calcul en SQL on se retrouve avec une requête extrêmement verbeuse. Heureusement si vous utilisez Doctrine2 vous allez pouvoir créer votre propre fonction DQL qui vous permettra de faire ce calcul très simplement.<br />
<span id="more-1624"></span><br />
Dans un premier temps il va falloir ajouter les propriétés latitude et longitude à notre modèle, imaginons que nous souhaitons calculer la distance entre deux villes.</p>
<div id="gist-1094596" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">&lt;?php</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="k">namespace</span> <span class="nx">Acme\GeoBundle\Entity</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'><span class="k">use</span> <span class="nx">Doctrine\ORM\Mapping</span> <span class="k">as</span> <span class="nx">ORM</span><span class="p">;</span></div><div class='line' id='LC6'><span class="k">use</span> <span class="nx">Symfony\Component\Validator\Constraints</span> <span class="k">as</span> <span class="nx">Assert</span><span class="p">;</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'><span class="sd">/**</span></div><div class='line' id='LC9'><span class="sd"> * @ORM\Entity</span></div><div class='line' id='LC10'><span class="sd"> * @ORM\Table(name=&quot;city&quot;)</span></div><div class='line' id='LC11'><span class="sd"> */</span></div><div class='line' id='LC12'><span class="k">class</span> <span class="nc">City</span></div><div class='line' id='LC13'><span class="p">{</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">/**</span></div><div class='line' id='LC15'><span class="sd">     * @ORM\Id</span></div><div class='line' id='LC16'><span class="sd">     * @ORM\Column(type=&quot;integer&quot;)</span></div><div class='line' id='LC17'><span class="sd">     * @ORM\GeneratedValue(strategy=&quot;AUTO&quot;)</span></div><div class='line' id='LC18'><span class="sd">     */</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">protected</span> <span class="nv">$id</span><span class="p">;</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">/**</span></div><div class='line' id='LC22'><span class="sd">     * @ORM\Column(name=&quot;label&quot;)</span></div><div class='line' id='LC23'><span class="sd">     * @Assert\NotBlank()</span></div><div class='line' id='LC24'><span class="sd">     */</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">protected</span> <span class="nv">$label</span><span class="p">;</span></div><div class='line' id='LC26'><br/></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">/**</span></div><div class='line' id='LC28'><span class="sd">     * @ORM\Column(type=&quot;decimal&quot;, scale=&quot;8&quot;)</span></div><div class='line' id='LC29'><span class="sd">     * @Assert\NotBlank()</span></div><div class='line' id='LC30'><span class="sd">     */</span></div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">protected</span> <span class="nv">$latitude</span><span class="p">;</span></div><div class='line' id='LC32'><br/></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">/**</span></div><div class='line' id='LC34'><span class="sd">     * @ORM\Column(type=&quot;decimal&quot;, scale=&quot;8&quot;)</span></div><div class='line' id='LC35'><span class="sd">     * @Assert\NotBlank()</span></div><div class='line' id='LC36'><span class="sd">     */</span></div><div class='line' id='LC37'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">protected</span> <span class="nv">$longitude</span><span class="p">;</span></div><div class='line' id='LC38'><br/></div><div class='line' id='LC39'><span class="c1">// Getter and Setter</span></div><div class='line' id='LC40'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1094596/4cbc29012639ae19bef9c3915554378761f1e229/gistfile1.php" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1094596#file_gistfile1.php" style="float:right;margin-right:10px;color:#666">gistfile1.php</a>
            <a href="https://gist.github.com/1094596">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Une fois que nous avons nos colonnes nous pourrions écrire la requête suivante pour connaître la distance en kilométres qui sépare les villes de notre base de données de Montpellier:</p>
<div id="gist-1103983" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">SELECT</span> </div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="p">((</span><span class="n">ACOS</span><span class="p">(</span><span class="n">SIN</span><span class="p">(</span><span class="mi">43</span><span class="p">.</span><span class="mi">61</span> <span class="o">*</span> <span class="n">PI</span><span class="p">()</span> <span class="o">/</span> <span class="mi">180</span><span class="p">)</span> <span class="o">*</span> <span class="n">SIN</span><span class="p">(</span><span class="n">latitude</span> <span class="o">*</span> <span class="n">PI</span><span class="p">()</span> <span class="o">/</span> <span class="mi">180</span><span class="p">)</span> <span class="o">+</span> <span class="n">COS</span><span class="p">(</span><span class="mi">43</span><span class="p">.</span><span class="mi">61</span> <span class="o">*</span> <span class="n">PI</span><span class="p">()</span> <span class="o">/</span> <span class="mi">180</span><span class="p">)</span> <span class="o">*</span> <span class="n">COS</span><span class="p">(</span><span class="n">latitude</span> <span class="o">*</span> <span class="n">PI</span><span class="p">()</span> <span class="o">/</span>   <span class="mi">180</span><span class="p">)</span> <span class="o">*</span> <span class="n">COS</span><span class="p">((</span><span class="mi">3</span><span class="p">.</span><span class="mi">87</span> <span class="o">-</span> <span class="n">longitude</span><span class="p">)</span> <span class="o">*</span> <span class="n">PI</span><span class="p">()</span> <span class="o">/</span> <span class="mi">180</span><span class="p">))</span> <span class="o">*</span> <span class="mi">180</span> <span class="o">/</span> <span class="n">PI</span><span class="p">())</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">1</span><span class="p">.</span><span class="mi">1515</span> <span class="o">*</span> <span class="mi">1</span><span class="p">.</span><span class="mi">609344</span><span class="p">)</span> </div><div class='line' id='LC3'><span class="k">FROM</span> <span class="n">city</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1103983/a5d058271f217678a0bcc5c7f5213865c92649fb/gistfile1.sql" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1103983#file_gistfile1.sql" style="float:right;margin-right:10px;color:#666">gistfile1.sql</a>
            <a href="https://gist.github.com/1103983">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Heureusement le parser de Doctrine2 va me permettre de créer une fonction DQL qui sera ensuite retranscris en SQL.</p>
<div id="gist-1094671" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>&lt;?php</div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'>namespace Acme\GeoBundle\AST\Functions;</div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'>use Doctrine\ORM\Query\AST\Functions\FunctionNode;</div><div class='line' id='LC6'>use Doctrine\ORM\Query\Parser;</div><div class='line' id='LC7'>use Doctrine\ORM\Query\SqlWalker;</div><div class='line' id='LC8'>use Doctrine\ORM\Query\Lexer;</div><div class='line' id='LC9'><br/></div><div class='line' id='LC10'>class Geo extends FunctionNode</div><div class='line' id='LC11'>{</div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;/**</div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* @var \Doctrine\ORM\Query\AST\ComparisonExpression</div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;private $latitude;</div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;/**</div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* @var \Doctrine\ORM\Query\AST\ComparisonExpression</div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/    </div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;private $longitude;</div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;/**</div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* Parse DQL Function</div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* </div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* @param Parser $parser </div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;public function parse(Parser $parser)</div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;{</div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$parser-&gt;match(Lexer::T_IDENTIFIER);</div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$parser-&gt;match(Lexer::T_OPEN_PARENTHESIS);</div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;latitude = $parser-&gt;ComparisonExpression();</div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$parser-&gt;match(Lexer::T_COMMA);</div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;longitude = $parser-&gt;ComparisonExpression();</div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$parser-&gt;match(Lexer::T_CLOSE_PARENTHESIS);</div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;}</div><div class='line' id='LC35'><br/></div><div class='line' id='LC36'>&nbsp;&nbsp;&nbsp;&nbsp;/**</div><div class='line' id='LC37'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* Get SQL </div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* </div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* @param SqlWalker $sqlWalker</div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* @return string</div><div class='line' id='LC41'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</div><div class='line' id='LC42'>&nbsp;&nbsp;&nbsp;&nbsp;public function getSql(SqlWalker $sqlWalker)</div><div class='line' id='LC43'>&nbsp;&nbsp;&nbsp;&nbsp;{</div><div class='line' id='LC44'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return sprintf(&#39;((ACOS(SIN(%s * PI() / 180) * SIN(%s * PI() / 180) + COS(%s * PI() / 180) * COS(%s * PI() / 180) * COS((%s - %s) * PI() / 180)) * 180 / PI()) * 60 * %s)&#39;,</div><div class='line' id='LC45'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;latitude-&gt;rightExpression-&gt;dispatch($sqlWalker), </div><div class='line' id='LC46'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;latitude-&gt;leftExpression-&gt;dispatch($sqlWalker), </div><div class='line' id='LC47'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;latitude-&gt;rightExpression-&gt;dispatch($sqlWalker), </div><div class='line' id='LC48'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;latitude-&gt;leftExpression-&gt;dispatch($sqlWalker), </div><div class='line' id='LC49'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;longitude-&gt;rightExpression-&gt;dispatch($sqlWalker), </div><div class='line' id='LC50'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;longitude-&gt;leftExpression-&gt;dispatch($sqlWalker),</div><div class='line' id='LC51'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39;1.1515 * 1.609344&#39;);</div><div class='line' id='LC52'>&nbsp;&nbsp;&nbsp;&nbsp;}</div><div class='line' id='LC53'>}</div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1094671/7181efcb519d42bfc2a04aab9ec73726997f548b/DQL%20Geo%20function" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1094671#file_dql geo function" style="float:right;margin-right:10px;color:#666">DQL Geo function</a>
            <a href="https://gist.github.com/1094671">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Que se passe t&#8217;il dans cette fonction ? Dans un premier temps la méthode Geo::parse() va parcourir le DQL et en extraire les parties souhaitées.</p>
<ul>
<li>Le parser reconnaît ma fonction (ligne 28)</li>
<li>J&#8217;ouvre ma parenthèse (ligne 29)</li>
<li>Le parser récupère ma première expression : latitude = :latitude (ligne 30)</li>
<li>Je mets une virgule (ligne 31)</li>
<li>Le parser récupère ma seconde expression : longitude = :longitude (ligne 32)</li>
<li>Je ferme ma parenthèse</li>
</ul>
<p>Maintenant que ma fonction est capable de parser mon DQL il va falloir qu&#8217;elle me genère du SQL, tout se passe dans la méthode getSql. Lorsque j&#8217;ai parsé mon DQL j&#8217;ai stocké les expressions correspondants à la longitude et latitude en tant qu&#8217;expression de comparaison (Parser::ComparisonExpression). Je vais ensuite pouvoir récupérer la partie qui m&#8217;intéresse pour construire mon SQL.</p>
<div id="gist-1127049" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">&lt;?php</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">latitude</span><span class="o">-&gt;</span><span class="na">rightExpression</span><span class="o">-&gt;</span><span class="na">dispatch</span><span class="p">(</span><span class="nv">$sqlWalker</span><span class="p">)</span> <span class="c1">// Correspond à ma colonne latitude</span></div><div class='line' id='LC4'><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">latitude</span><span class="o">-&gt;</span><span class="na">leftExpression</span><span class="o">-&gt;</span><span class="na">dispatch</span><span class="p">(</span><span class="nv">$sqlWalker</span><span class="p">)</span> <span class="c1">// Correspond à la valeur de la latitude</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1127049/c8573eba9723db015a545d6802835c4dd901d41b/gistfile1.aw" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1127049#file_gistfile1.aw" style="float:right;margin-right:10px;color:#666">gistfile1.aw</a>
            <a href="https://gist.github.com/1127049">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Désormais il me suffira décrire pour connaître la distance entre toutes les villes de ma base et Montpellier :</p>
<div id="gist-1094706" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">&lt;?php</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="nv">$entityManager</span><span class="o">-&gt;</span><span class="na">createQueryBuilder</span><span class="p">()</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="o">-&gt;</span><span class="na">from</span><span class="p">(</span><span class="s1">&#39;AcmeGeoBundle:City&#39;</span><span class="p">,</span> <span class="s1">&#39;c&#39;</span><span class="p">)</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="o">-&gt;</span><span class="na">select</span><span class="p">(</span><span class="s1">&#39;GEO(c.latitude = :latitude, c.longitude = :longitude)&#39;</span><span class="p">)</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="o">-&gt;</span><span class="na">setParameter</span><span class="p">(</span><span class="s1">&#39;latitude&#39;</span><span class="p">,</span> <span class="s1">&#39;43.61&#39;</span><span class="p">)</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="o">-&gt;</span><span class="na">setParameter</span><span class="p">(</span><span class="s1">&#39;longitude&#39;</span><span class="p">,</span> <span class="s1">&#39;3.87&#39;</span><span class="p">)</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="o">-&gt;</span><span class="na">getQuery</span><span class="p">()</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="o">-&gt;</span><span class="na">execute</span><span class="p">();</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1094706/3f525f57865ad46124b69e58b5f83b3ab9386991/gistfile1.php" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1094706#file_gistfile1.php" style="float:right;margin-right:10px;color:#666">gistfile1.php</a>
            <a href="https://gist.github.com/1094706">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Pour terminer il va falloir enregistrer cette fonction sur votre EntityManager :</p>
<div id="gist-1103998" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="c1"># Doctrine Configuration</span></div><div class='line' id='LC2'><span class="l-Scalar-Plain">doctrine</span><span class="p-Indicator">:</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">dbal</span><span class="p-Indicator">:</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">driver</span><span class="p-Indicator">:</span>   <span class="err">%</span><span class="l-Scalar-Plain">database_driver%</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">host</span><span class="p-Indicator">:</span>     <span class="err">%</span><span class="l-Scalar-Plain">database_host%</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">dbname</span><span class="p-Indicator">:</span>   <span class="err">%</span><span class="l-Scalar-Plain">database_name%</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">user</span><span class="p-Indicator">:</span>     <span class="err">%</span><span class="l-Scalar-Plain">database_user%</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">password</span><span class="p-Indicator">:</span> <span class="err">%</span><span class="l-Scalar-Plain">database_password%</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">charset</span><span class="p-Indicator">:</span>  <span class="l-Scalar-Plain">UTF8</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">orm</span><span class="p-Indicator">:</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">auto_generate_proxy_classes</span><span class="p-Indicator">:</span> <span class="err">%</span><span class="l-Scalar-Plain">kernel.debug%</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">entity_managers</span><span class="p-Indicator">:</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">default</span><span class="p-Indicator">:</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">auto_mapping</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">dql</span><span class="p-Indicator">:</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">numeric_functions</span><span class="p-Indicator">:</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="l-Scalar-Plain">geo</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">Acme\GeoBundle\AST\Functions\Geo</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1103998/5a8165a8bc716cc5e52255066305a8574309ad86/gistfile1.yml" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1103998#file_gistfile1.yml" style="float:right;margin-right:10px;color:#666">gistfile1.yml</a>
            <a href="https://gist.github.com/1103998">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Doctrine2 permet donc d&#8217;étendre très facilement son système de fonction. Dans l&#8217;exemple donné ici il est évident que l&#8217;écriture d&#8217;une nouvelle fonction nous a simplifié l&#8217;écriture de nos futures requêtes DQL.</p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/HA2xWeOstc8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/doctrine2/geolocalisation-ou-comment-creer-ses-propres-fonctions-dql-avec-doctrine2-1624/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/doctrine2/geolocalisation-ou-comment-creer-ses-propres-fonctions-dql-avec-doctrine2-1624</feedburner:origLink></item>
		<item>
		<title>Enfin un design pour le blog Lexik</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/NVvoAEoLiGY/enfin-un-design-pour-le-blog-lexik-1586</link>
		<comments>http://www.lexik.fr/blog/symfony/lexik-life/enfin-un-design-pour-le-blog-lexik-1586#comments</comments>
		<pubDate>Mon, 18 Jul 2011 16:48:27 +0000</pubDate>
		<dc:creator>Samuel Breton</dc:creator>
				<category><![CDATA[Lexik Life]]></category>
		<category><![CDATA[lexik]]></category>
		<category><![CDATA[news]]></category>
		<category><![CDATA[webdesign]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1586</guid>
		<description><![CDATA[Après 2 ans et demi de bons et loyaux services, le thême trouvé rapidement sur internet s&#8217;en est allé et laisse place à une version plus personnelle de l&#8217;équipe de développement. Retrouvez nos développeurs Symfony cachés entre des div et &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/lexik-life/enfin-un-design-pour-le-blog-lexik-1586">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Après 2 ans et demi de bons et loyaux services, le thême trouvé rapidement sur internet s&#8217;en est allé et laisse place à une version plus personnelle de l&#8217;équipe de développement.</p>
<p>Retrouvez nos développeurs Symfony cachés entre des div et des h<code>n</code>.<span id="more-1586"></span></p>
<h2>Quoi de neuf chez Lexik ?</h2>
<ul>
<li>un nouveau logo ;</li>
<li>des projets Symfony2 ;</li>
<li>de nouveaux développeurs ;</li>
<li>un championnat de pétanque tout l&#8217;été ;</li>
<li>des applications mobiles pour le blog.</li>
</ul>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/NVvoAEoLiGY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/lexik-life/enfin-un-design-pour-le-blog-lexik-1586/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/lexik-life/enfin-un-design-pour-le-blog-lexik-1586</feedburner:origLink></item>
		<item>
		<title>Offre d’emploi développeur PHP / Symfony</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/Es59SDAIORo/offre-d-emploi-developpeur-php-symfony-1562</link>
		<comments>http://www.lexik.fr/blog/symfony/recrutement/offre-d-emploi-developpeur-php-symfony-1562#comments</comments>
		<pubDate>Wed, 20 Apr 2011 11:51:10 +0000</pubDate>
		<dc:creator>Samuel Breton</dc:creator>
				<category><![CDATA[Lexik Life]]></category>
		<category><![CDATA[recrutement]]></category>
		<category><![CDATA[developpeur]]></category>
		<category><![CDATA[emploi]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1562</guid>
		<description><![CDATA[Lexik est une agence Web spécialisée dans le développement d&#8217;application Web et de sites Internet sur-mesure en PHP avec le framework Symfony. Nous souhaitons renforcer nos équipes de développement par 2 développeurs pour nos projets clients et internes. Vous avez &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/recrutement/offre-d-emploi-developpeur-php-symfony-1562">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Lexik est une agence Web spécialisée dans le développement d&#8217;application Web et de sites Internet sur-mesure en PHP avec le framework Symfony. Nous souhaitons renforcer nos équipes de développement par <strong>2 développeurs</strong> pour nos projets clients et internes. Vous avez envie de vous intégrer dans une jeune société (âge moyen : entre 25 et 30 ans) avec <strong>une ambiance agréable et dynamique</strong>, de travailler en équipe sous la responsabilité d&#8217;un chef de projet.<br />
<span id="more-1562"></span></p>
<h2>Votre profil :</h2>
<p>De formation BTS / DUT ou école d&#8217;ingénieur, vous justifiez <strong>d&#8217;une expérience significative</strong> dans le milieu du développement Web.</p>
<p>Vous bénéficiez d&#8217;une bonne expérience à titre privé ou professionnel dans les technologies suivantes :</p>
<ul>
<li>XHTML / CSS ;</li>
<li>PHP 5, orienté objet ;</li>
<li>SQL (MySQL, SQLite, PostgreSQL, &#8230;).</li>
</ul>
<p>Une expérience ou un intérêt dans les domaines suivants seront un atout :</p>
<ul>
<li>Framework symfony 1.4 / Symfony2 avec l&#8217;ORM Doctrine ;</li>
<li>Gestionnaire de version (Git / SVN) ;</li>
<li>Javascript ;</li>
<li>Tests unitaires et fonctionnels / Intégration continue ;</li>
<li>Méthodologie de développement agile (SCRUM).</li>
</ul>
<h2>Détails :</h2>
<p><strong>Envoyez-nous votre CV et lettre de motivation par email à l&#8217;adresse : <a href="mailto:contact@lexik.fr">contact@lexik.fr</a></strong></p>
<ul>
<li>Type de contrat : CDI</li>
<li>Lieu : Pérols</li>
<li>Début du contrat : ASAP</li>
<li>Télétravail : non</li>
<li>Rémunération selon profil</li>
</ul>
<p><a href="http://www.lexik.fr/">http://www.lexik.fr/</a></p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/Es59SDAIORo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/recrutement/offre-d-emploi-developpeur-php-symfony-1562/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/recrutement/offre-d-emploi-developpeur-php-symfony-1562</feedburner:origLink></item>
		<item>
		<title>Envoi d’email avec Symfony et Mailjet</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/Yr3-gxvRWKI/envoi-de-mails-avec-symfony-et-mailjet-1526</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/envoi-de-mails-avec-symfony-et-mailjet-1526#comments</comments>
		<pubDate>Thu, 14 Apr 2011 08:17:03 +0000</pubDate>
		<dc:creator>cedric</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[mailjet]]></category>
		<category><![CDATA[SwiftMailer]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1526</guid>
		<description><![CDATA[Petit constat : La gestion des expéditions de mails dans les projets Web est souvent laborieuse. En effet, les serveurs ne sont pas toujours bien configurés pour ça. Il arrive que les emails partent en spam ou encore qu&#8217;ils soient &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony/envoi-de-mails-avec-symfony-et-mailjet-1526">...</a></p>]]></description>
			<content:encoded><![CDATA[<h4>Petit constat :</h4>
<p>La gestion des expéditions de mails dans les projets Web est souvent laborieuse. En effet, les serveurs ne sont pas toujours bien configurés pour ça. Il arrive que les emails partent en spam ou encore qu&#8217;ils soient bloqués avant même d&#8217;entrer dans la boite mails des utilisateurs&#8230; Bref, c&#8217;est jamais pratique et le suivi se fait très difficilement.<br />
<span id="more-1526"></span></p>
<h2>Quelques services d&#8217;envoi :</h2>
<p>La solution réside bien souvent dans le fait de déporter l&#8217;expédition sur une plateforme spécialisée. Il en existe des dizaines :<br />
Amazon a récemment sorti une plateforme <a href="http://aws.amazon.com/fr/ses/">Amazon SES</a> qui permet d&#8217;expédier ses emails via un simple appel à une API. Cette solution est très pratique mais a pour inconvénient de changer un peu le processus d&#8217;envoi d&#8217;email, il faudra donc faire quelques adaptations dans le code de votre application.<br />
Il existe également d&#8217;autres solutions :</p>
<ul>
<li>MailChimp : <a href="http://www.mailchimp.com/">http://www.mailchimp.com/</a></li>
<li>Campaign Monitor : <a href="http://www.campaignmonitor.com/">http://www.campaignmonitor.com/</a></li>
<li>AWeber : <a href="http://www.aweber.com/">http://www.aweber.com/</a></li>
</ul>
<p>pour en citer quelques uns&#8230;</p>
<p>Ces solutions sont idéales pour gérer des newsletters mais sont contraignantes pour les emails transactionnels. Eh oui, il faut souvent se rendre sur l&#8217;interface du site pour faire ses expéditions ou tout traiter via leur API.</p>
<h2>Une solution intéressante : Mailjet</h2>
<p>Les emails de vos projets Web sont souvent délivrés via un serveur SMTP, <a href="http://fr.mailjet.com/">Mailjet</a> est un service en ligne qui a eu la bonne idée de proposer d&#8217;exploiter un serveur <strong>SMTP authentifié et donc optimisé pour assurer la délivrabilité des emails</strong>. L&#8217;autre avantage indéniable de cette solution est qu&#8217;il suffit de <strong>changer les paramètres du SMTP</strong> de votre application et le tour est joué, vos emails sont délivrés par Mailjet. En prime Mailjet vous propose un système de statistiques sur les expéditions que vous pouvez consulter sur leur plateforme ou encore interroger à distance, via leur API.</p>
<p>Nous avons testé cette solution sur un projet pour envoyer des mails transactionnels tels que des mails d&#8217;inscriptions, de notifications ainsi qu&#8217;une newsletter hebdomadaire. <a href="http://fr.mailjet.com/">Mailjet</a> propose plusieurs offres dont une gratuite permettant d&#8217;envoyer jusqu&#8217;à 6000 mails par mois ce qui dans notre cas était suffisant.</p>
<p>Exemple de configuration du SMTP :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1526code14'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p152614"><td class="code" id="p1526code14"><pre class="yml" style="font-family:monospace;"># apps/&lt;app_name&gt;/config/factories.yml
prod:
  mailer:
    param:
      transport:
        class: Swift_SmtpTransport
        param:
          host:       in.mailjet.com
          port:       465
          encryption: ssl
          username:   &quot;your-username&quot;
          password:   &quot;your-pass&quot;</pre></td></tr></table></div>

<p>Une fois cette petite configuration faite vos mails seront délivrés par le SMTP de Mailjet qui s&#8217;occupe d&#8217;envoyer vos mails et qui fera aussi en sorte de limiter les risques de non livraison des mails.</p>
<p>PS : Non, non, non ce billet n&#8217;est pas sponsorisé! C&#8217;est juste que cette solution est vraiment pratique et souhaitions la partager.</p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/Yr3-gxvRWKI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/envoi-de-mails-avec-symfony-et-mailjet-1526/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/symfony/envoi-de-mails-avec-symfony-et-mailjet-1526</feedburner:origLink></item>
		<item>
		<title>Survol de la GoogleMaps Api v3</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/3Dbn8rqe0D8/survol-de-la-googlemaps-api-v3-1509</link>
		<comments>http://www.lexik.fr/blog/symfony/javascript/survol-de-la-googlemaps-api-v3-1509#comments</comments>
		<pubDate>Fri, 11 Mar 2011 10:30:04 +0000</pubDate>
		<dc:creator>laurent</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[geolocalisation]]></category>
		<category><![CDATA[google api]]></category>
		<category><![CDATA[googlemaps]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1509</guid>
		<description><![CDATA[Beaucoup d&#8217;entre vous ont certainement déjà eu l&#8217;occasion de jouer avec l&#8217;api javascript de GoogleMaps. Elle est performante, bien documentée, et plutôt instinctive à implémenter. De plus il éxiste énormément de ressources sur le web proposant des exemples d&#8217;utilisation. On &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/javascript/survol-de-la-googlemaps-api-v3-1509">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Beaucoup d&#8217;entre vous ont certainement déjà eu l&#8217;occasion de jouer avec l&#8217;api javascript de GoogleMaps. Elle est performante, bien documentée, et plutôt instinctive à implémenter. De plus il éxiste énormément de ressources sur le web proposant des exemples d&#8217;utilisation.<br />
On trouve cependant encore peu de ressources mentionnant la dernière mouture de l&#8217;api, la v3, qui simplifie et éclaircie encore plus son utilisation. Ce petit article va survoler quelques exemples d&#8217;utilisation de celle-ci.</p>
<p><span id="more-1509"></span></p>
<p><strong>La première grosse nouveauté de la v3, c&#8217;est la mort de la clé api !</strong> En effet, il n&#8217;est plus nécessaire de déclarer un domaine pour récupérer une clé, ou de se battre avec tout un trousseau pour jongler entre des environnements de dev, preprod, prod, test, etc&#8230; Maintenant on charge simplement l&#8217;api comme n&#8217;importe quelle librairie Javascript.<br />
Second changement notoire, plus aucun appel Ajax explicite vers l&#8217;api REST n&#8217;est nécessaire pour récupérer des données de géolocalisation. Un simple passage de paramètres à des objets Javascript nous rendra les informations voulues en un temps record.</p>
<p>Commençons donc par charger l&#8217;api et afficher une map:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1509code23'); return false;">View Code</a> JAVASCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p150923"><td class="code" id="p1509code23"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>div id<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;gmap-div&quot;</span> style<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;width: 500px; height: 400px;&quot;</span><span style="color: #339933;">&gt;&lt;/</span>div<span style="color: #339933;">&gt;</span>
&nbsp;
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span> src<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js&quot;</span><span style="color: #339933;">&gt;&lt;/</span>script<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span> src<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;http://maps.google.com/maps/api/js?sensor=false&quot;</span> <span style="color: #339933;">/&gt;</span>
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
$<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">//J'utilise dans l'exemple jQuery pour améliorer la lisibilité du code, le focus étant sur GoogleMaps</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">//tout d'abord on définit le centre de notre map par sa latitude et longitude, par exemple Montpellier: </span>
  <span style="color: #003366; font-weight: bold;">var</span> latLng <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #660066;">maps</span>.<span style="color: #660066;">LatLng</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">43.60</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">3.88</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #006600; font-style: italic;">//puis on créé la map</span>
  <span style="color: #003366; font-weight: bold;">var</span> gmap <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #660066;">maps</span>.<span style="color: #660066;">Map</span><span style="color: #009900;">&#40;</span>document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'gmap-div'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
    zoom<span style="color: #339933;">:</span> <span style="color: #CC0000;">10</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">//le zoom de départ</span>
    center<span style="color: #339933;">:</span> latLng<span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">//le centre de la map au chargement</span>
    mapTypeId<span style="color: #339933;">:</span> google.<span style="color: #660066;">maps</span>.<span style="color: #660066;">MapTypeId</span>.<span style="color: #660066;">ROADMAP</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">//le type de map, ROADMAP correspond à la version par défaut des versions précédentes</span>
    streetViewControl<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">//si on souhaite désactiver les contrôle StreetView</span>
    panControl<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span> <span style="color: #006600; font-style: italic;">//si on souhaite masquer les contrôles de déplacement</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>Créons maintenant quelques interactions. Pour commencer un formulaire va nous permettre de rechercher une ville pour ensuite placer un marqueur à son emplacement sur la map:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1509code24'); return false;">View Code</a> HTML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p150924"><td class="code" id="p1509code24"><pre class="html" style="font-family:monospace;">&lt;form id=&quot;search-form&quot; action=&quot;#&quot;&gt;
  &lt;input type=&quot;text&quot; id=&quot;search-query&quot; size=&quot;20&quot; /&gt;
  &lt;input type=&quot;submit&quot; value=&quot;chercher&quot; /&gt;
&lt;/form&gt;</pre></td></tr></table></div>

<p>Et le code javascript correspondant:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1509code25'); return false;">View Code</a> JAVASCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p150925"><td class="code" id="p1509code25"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">//on créé un geocoder qui s'occupera des requètes de géolocalisation</span>
<span style="color: #003366; font-weight: bold;">var</span> geocoder <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #660066;">maps</span>.<span style="color: #660066;">Geocoder</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#search-form'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">submit</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  e.<span style="color: #660066;">preventDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">//l'objet request que l'on passe au geocoder</span>
  <span style="color: #003366; font-weight: bold;">var</span> request <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
    address<span style="color: #339933;">:</span>    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#search-query'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    region<span style="color: #339933;">:</span>     <span style="color: #3366CC;">'fr'</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">//pour améliorer la qualité des résultats en précisant que l'on cherche principalement en France</span>
    language<span style="color: #339933;">:</span>   <span style="color: #3366CC;">'fr'</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
  <span style="color: #006600; font-style: italic;">//aucune requète ajax nécessaire !</span>
  geocoder.<span style="color: #660066;">geocode</span><span style="color: #009900;">&#40;</span>request<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>results<span style="color: #339933;">,</span> <span style="color: #000066;">status</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">status</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'OK'</span> <span style="color: #339933;">&amp;&amp;</span> results.<span style="color: #660066;">length</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #006600; font-style: italic;">//on récupère les coordonnées du premier résultat</span>
      <span style="color: #003366; font-weight: bold;">var</span> lat <span style="color: #339933;">=</span> results<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">geometry</span>.<span style="color: #660066;">location</span>.<span style="color: #660066;">lat</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #003366; font-weight: bold;">var</span> lng <span style="color: #339933;">=</span> results<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">geometry</span>.<span style="color: #660066;">location</span>.<span style="color: #660066;">lng</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #006600; font-style: italic;">//puis on recentre la map...</span>
      <span style="color: #003366; font-weight: bold;">var</span> newCenter <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #660066;">maps</span>.<span style="color: #660066;">LatLng</span><span style="color: #009900;">&#40;</span>lat<span style="color: #339933;">,</span> lng<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      gmap.<span style="color: #660066;">setCenter</span><span style="color: #009900;">&#40;</span>newCenter<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #006600; font-style: italic;">//...et on pose un marqueur dessus</span>
      <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #660066;">maps</span>.<span style="color: #660066;">Marker</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
	position<span style="color: #339933;">:</span>  newCenter<span style="color: #339933;">,</span>
        map<span style="color: #339933;">:</span>       gmap
      <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
      console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'aucun résultat'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Plutôt simple pour l&#8217;instant. Allons un peu plus loin et traçons une ligne qui va relier au fur et à mesure toutes les villes marquées. Il va falloir pour cela utiliser la librairie supplémentaire de GoogleMaps &laquo;&nbsp;Geometry&nbsp;&raquo;. N&#8217;étant pas une librairie chargée par défaut, il faut préciser son utilisation au chargement de GoogleMaps:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1509code26'); return false;">View Code</a> HTML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p150926"><td class="code" id="p1509code26"><pre class="html" style="font-family:monospace;">&lt;script type=&quot;text/javascript&quot; src=&quot;http://maps.google.com/maps/api/js?libraries=geometry&amp;sensor=false&quot;&gt;&lt;/script&gt;</pre></td></tr></table></div>

<p>Profitons-en pour afficher la longueur en kilomètre de notre itinéraire dans une div que l&#8217;on va tout de suite rajouter au document:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1509code27'); return false;">View Code</a> HTML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p150927"><td class="code" id="p1509code27"><pre class="html" style="font-family:monospace;">&lt;div id=&quot;total-length&quot;&gt;&lt;/div&gt;</pre></td></tr></table></div>

<p>Pour tracer une ligne reliant des points sur une GoogleMap, il faut utiliser la classe &laquo;&nbsp;Polyline&nbsp;&raquo;. Déclarons-la juste après la map en début de script:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1509code28'); return false;">View Code</a> JAVASCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p150928"><td class="code" id="p1509code28"><pre class="javascript" style="font-family:monospace;">  <span style="color: #009966; font-style: italic;">/* ... */</span>
  <span style="color: #003366; font-weight: bold;">var</span> polyline <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #660066;">maps</span>.<span style="color: #660066;">Polyline</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
    strokeColor<span style="color: #339933;">:</span>   <span style="color: #3366CC;">'#2222FF'</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">//on définit la couleur</span>
    strokeOpacity<span style="color: #339933;">:</span> <span style="color: #CC0000;">0.5</span><span style="color: #339933;">,</span>       <span style="color: #006600; font-style: italic;">//l'opacité</span>
    strokeWeight<span style="color: #339933;">:</span>  <span style="color: #CC0000;">3</span><span style="color: #339933;">,</span>         <span style="color: #006600; font-style: italic;">//l'épaisseur du trait,</span>
    map<span style="color: #339933;">:</span>           gmap       <span style="color: #006600; font-style: italic;">//la map à laquelle rattacher la polyline</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">//on peut extraire un objet renfermant tous les points d'une Polyline</span>
  <span style="color: #006600; font-style: italic;">//cet objet nous sera utile pour calculer la distance de l'itinéraire</span>
  <span style="color: #003366; font-weight: bold;">var</span> path <span style="color: #339933;">=</span> polyline.<span style="color: #660066;">getPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Il faut maintenant étoffer le code de création du marqueur:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1509code29'); return false;">View Code</a> JAVASCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p150929"><td class="code" id="p1509code29"><pre class="javascript" style="font-family:monospace;">  <span style="color: #009966; font-style: italic;">/* ... */</span>
  geocoder.<span style="color: #660066;">geocode</span><span style="color: #009900;">&#40;</span>request<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>results<span style="color: #339933;">,</span> <span style="color: #000066;">status</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">status</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'OK'</span> <span style="color: #339933;">&amp;&amp;</span> results.<span style="color: #660066;">length</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #003366; font-weight: bold;">var</span> lat <span style="color: #339933;">=</span> results<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">geometry</span>.<span style="color: #660066;">location</span>.<span style="color: #660066;">lat</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #003366; font-weight: bold;">var</span> lng <span style="color: #339933;">=</span> results<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">geometry</span>.<span style="color: #660066;">location</span>.<span style="color: #660066;">lng</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #003366; font-weight: bold;">var</span> newCenter <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #660066;">maps</span>.<span style="color: #660066;">LatLng</span><span style="color: #009900;">&#40;</span>lat<span style="color: #339933;">,</span> lng<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      gmap.<span style="color: #660066;">setCenter</span><span style="color: #009900;">&#40;</span>newCenter<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #660066;">maps</span>.<span style="color: #660066;">Marker</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
        position<span style="color: #339933;">:</span>  newCenter<span style="color: #339933;">,</span>
        map<span style="color: #339933;">:</span>       gmap
      <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #006600; font-style: italic;">//on ajoute le nouveau point à notre path, le Polyline associé se met automatiquement à jour</span>
      path.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>newCenter<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #006600; font-style: italic;">//on affiche la longueur du path dans notre div</span>
      <span style="color: #006600; font-style: italic;">//c'est ici qu'intervient la librairie Geometry, qui va gérer automatiquement tous les calculs nécessaires</span>
&nbsp;
      <span style="color: #003366; font-weight: bold;">var</span> pathLength <span style="color: #339933;">=</span> parseInt<span style="color: #009900;">&#40;</span>google.<span style="color: #660066;">maps</span>.<span style="color: #660066;">geometry</span>.<span style="color: #660066;">spherical</span>.<span style="color: #660066;">computeLength</span><span style="color: #009900;">&#40;</span>path<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> <span style="color: #CC0000;">1000</span><span style="color: #339933;">;</span>
      <span style="color: #006600; font-style: italic;">//computeLength nous renvoie des mètres que l'on transforme en kilomètres</span>
&nbsp;
      <span style="color: #006600; font-style: italic;">//on met à jour l'affichage</span>
      $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#total-length'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span>pathLength <span style="color: #339933;">+</span> <span style="color: #3366CC;">' km'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
      console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'aucun résultat'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #006600; font-style: italic;">/* ... */</span></pre></td></tr></table></div>

<p>Il a suffi d&#8217;une poignée de lignes pour rajouter ces informations, et le résultat est plutôt sympathique.</p>
<p>On remarque tout de même un détail ennuyeux: il faut déplacer et zoomer à la main si on veut avoir une vue globale et centrée de notre itinéraire à chaque nouvel ajout de marqueur. A la manière du &laquo;&nbsp;path&nbsp;&raquo; qui stocke les informations d&#8217;une Polyline, une map possède des &laquo;&nbsp;bounds&nbsp;&raquo; qui définissent les limites de son affichage. La classe &laquo;&nbsp;LatLngBounds&nbsp;&raquo; arrive ici en jeu et va nous permettre d&#8217;optimiser automatiquement l&#8217;affichage de notre itinéraire.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1509code30'); return false;">View Code</a> JAVASCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p150930"><td class="code" id="p1509code30"><pre class="javascript" style="font-family:monospace;">  <span style="color: #006600; font-style: italic;">//en début de script avec les déclarations, on créé notre objet bounds</span>
  <span style="color: #003366; font-weight: bold;">var</span> bounds <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #660066;">maps</span>.<span style="color: #660066;">LatLngBounds</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009966; font-style: italic;">/* ... */</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">//à la suite de l'ajout d'un nouveau marqueur, on étend la zone &quot;bounds&quot; en lui demandant d'inclure le nouveau point</span>
  bounds.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span>newCenter<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #006600; font-style: italic;">//on demande en suite à la map de s'adapter à cette zone</span>
  gmap.<span style="color: #660066;">fitBounds</span><span style="color: #009900;">&#40;</span>bounds<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">/* ... */</span></pre></td></tr></table></div>

<p>Et c&#8217;est tout ! Encore trois malheureuses lignes pour une fonctionnalité relativement puissante. Vous pouvez voir l&#8217;exemple tourner <a href="http://www.lexik.fr/sandbox/1509_exemple_googlemaps_v3.html">sur cette page</a>.</p>
<p>La richesse de cette dernière version de l&#8217;api, couplée à la fluidité de son utilisation, rend l&#8217;intégration d&#8217;une GoogleMap dans une application riche vraiment agréable. Jetez un oeil à la <a href="http://code.google.com/intl/fr/apis/maps/documentation/javascript/basics.html">documentation officielle</a> très complète si vous souhaitez en apprendre plus !</p>
<p>Les sources de l&#8217;exemple de cet article sont disponibles <a href="https://gist.github.com/865652">sur Github</a>.</p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/3Dbn8rqe0D8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/javascript/survol-de-la-googlemaps-api-v3-1509/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/javascript/survol-de-la-googlemaps-api-v3-1509</feedburner:origLink></item>
		<item>
		<title>Lexik sera présent au symfony live 2011 à paris</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/3M803dlTQBY/lexik-sera-present-au-symfony-live-2011-a-paris-1505</link>
		<comments>http://www.lexik.fr/blog/symfony/lexik-life/lexik-sera-present-au-symfony-live-2011-a-paris-1505#comments</comments>
		<pubDate>Wed, 02 Mar 2011 14:00:08 +0000</pubDate>
		<dc:creator>thomas</dc:creator>
				<category><![CDATA[Lexik Life]]></category>
		<category><![CDATA[2011]]></category>
		<category><![CDATA[paris]]></category>
		<category><![CDATA[Symfony live]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1505</guid>
		<description><![CDATA[Jérémy Barthe et Cédric Girard seront présent au symfony live à Paris les 3 et 4 mars pour la présentation de symfony 2. Retrouvez le programme ici: http://www.symfony-live.com/paris/schedule et pour les inscriptions ca doit surement être trop tard! Les prochains &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/lexik-life/lexik-sera-present-au-symfony-live-2011-a-paris-1505">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Jérémy Barthe et Cédric Girard seront présent au symfony live à Paris les 3 et 4 mars pour la présentation de symfony 2.</p>
<p>Retrouvez le programme ici: <a href="http://www.symfony-live.com/paris/schedule">http://www.symfony-live.com/paris/schedule</a> et pour les inscriptions ca doit surement être trop tard!</p>
<p>Les prochains billets feront un retour sur le sfLive.</p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/3M803dlTQBY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/lexik-life/lexik-sera-present-au-symfony-live-2011-a-paris-1505/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/lexik-life/lexik-sera-present-au-symfony-live-2011-a-paris-1505</feedburner:origLink></item>
		<item>
		<title>Présentation du lxErrorLoggerPlugin</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/t2SLoMLi3dA/presentation-du-lxerrorloggerplugin-1433</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/presentation-du-lxerrorloggerplugin-1433#comments</comments>
		<pubDate>Wed, 16 Feb 2011 10:31:12 +0000</pubDate>
		<dc:creator>cedric</dc:creator>
				<category><![CDATA[1.4.x]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1433</guid>
		<description><![CDATA[Voici le petit dernier des plugins Symfony de chez Lexik, lxErrorLoggerPlugin, son but est simple : vous alerter en cas d&#8217;erreurs PHP ou Exceptions sur vos projets Symfony. Le besoin est simple, être alerté et éventuellement logger chaque erreurs, qu&#8217;elles &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony/presentation-du-lxerrorloggerplugin-1433">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Voici le petit dernier des plugins Symfony de chez Lexik, <a href="https://github.com/lexik/lxErrorLoggerPlugin">lxErrorLoggerPlugin</a>, son but est simple : <strong>vous alerter en cas d&#8217;erreurs PHP ou Exceptions sur vos projets Symfony</strong>.<br />
Le besoin est simple, être alerté et éventuellement logger chaque erreurs, qu&#8217;elles soient PHP, Exception ou erreurs remontées par Symfony. En effet le logger de base de Symfony s&#8217;arrête aux erreurs remontées par ses soins mais ne remontent pas forcément aux erreurs PHP. Le système de notification du plugin est très flexible grâce à une série de &laquo;&nbsp;notifier&nbsp;&raquo; que l&#8217;on peut activer ou non de façon indépendante les uns des autres.</p>
<p><span id="more-1433"></span></p>
<p>Voici les différents notifiers que nous proposons :</p>
<ul>
<li>stockage en base de données (celle par défaut, ou via un dsn personnalisé) ;</li>
<li>stockage en fichier XML ;</li>
<li>stockage en fichier de log classique (fichier texte) ;</li>
<li>notification via un envoi de mail ;</li>
<li>notification via <a href="http://hoptoadapp.com/" target="_blank">Hoptoad</a>, un webservice de log d&#8217;erreur.</li>
</ul>
<p>Le plugin va par défaut logger toutes les exceptions levées, par contre pour les erreurs PHP il est évidement possible de configurer l&#8217;<strong>error_reporting</strong>, ce qui permet de remonter seulement les erreurs et non les notices par exemple. La configuration du plugin se fait tout simplement dans le fichier app.yml de votre application (ou du projet). Chaque &laquo;&nbsp;notifier&nbsp;&raquo; possède ses propres options, pour plus de détail je vous invite à regarder le <a href="https://github.com/lexik/lxErrorLoggerPlugin">README</a> du plugin.</p>
<p>Voici par exemple une capture d&#8217;écran d&#8217;un email envoyé par <a href="https://github.com/lexik/lxErrorLoggerPlugin">lxErrorLoggerPlugin</a> :</p>
<p><img src="http://www.lexik.fr/blog/symfony/wp-content/uploads/2011/02/lxCoreExampleProject1.png" alt="" title="lxCoreExampleProject" width="512" height="450" class="aligncenter size-full wp-image-1500" /></p>
<p>Comme il a été précisé en introduction, lxErrorLoggerPlugin permet de notifier les erreurs <strong>mais également de les stocker</strong>. Le stockage se fait via une base de données ou un fichier XML. Cela apporte 2 avantages indéniables :</p>
<ul>
<li>la possibilité de repérer des erreurs similaires à d&#8217;autres, il est alors possible de prévenir les notifiers tels que le notifier email pour ne pas envoyer un email doublon, tout ceci est configurable ;</li>
<li>la possibilité de générer un flux RSS des erreurs, l&#8217;URL du flux sera protégé par un token paramètrable par vos soins.</li>
</ul>
<h4>Exemple d&#8217;utilisation :</h4>
<p>Supposons que nous avons besoin de logger les erreurs qui se produisent sur notre application frontend.</p>
<p><strong>1. Activer le plugin :</strong></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1433code34'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p143334"><td class="code" id="p1433code34"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// config/ProjectConfiguration.class.php</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setup<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">enablePlugins</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span>
      <span style="color: #339933;">...,</span>
      <span style="color: #0000ff;">'lxErrorLoggerPlugin'</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><strong>2. Configurer le plugin dans l&#8217;application souhaité, frontend dans cet exemple :</strong><br />
Ici nous allons utiliser la notification des erreurs en base de données et par email.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1433code35'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p143335"><td class="code" id="p1433code35"><pre class="yml" style="font-family:monospace;"># apps/frontend/config/app.yml
all:
  lx_error_logger_plugin:
    enabled:              true # Enable error notification
    php_error_reporting:  &lt;?php echo (E_ALL | E_STRICT).&quot;\n&quot; ?&gt;
    rss:
      token:              264864156479631564841687 # token to access to the rss
      items:              10 # items in the rss
    notifier:
      db:
        enabled:          true
        options:
          similar_error:  true
      mail:
        enabled:          true
        options:
          to:             [bob@example.com, chuck@example.com]
          subject:        A new error occured on your website
          always_send:    true # always send an email even if db or xml notifiers detect the error as similar</pre></td></tr></table></div>

<p><strong>3. Activer le flux RSS des dernières erreurs :</strong><br />
Dans cet exemple la notification des erreurs en base de données est activée donc le flux RSS peut récupérer des données.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1433code36'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p143336"><td class="code" id="p1433code36"><pre class="yml" style="font-family:monospace;"># apps/frontend/config/settings.yml
all:
  .settings:
    enabled_modules: [..., lxErrorNotifierRss]</pre></td></tr></table></div>

<p>Le flux RSS est maintenant accessible avec l&#8217;url :</p>
<p>http://super-website.com/lx-error/rss.xml?token=264864156479631564841687</p>
<p>Et c&#8217;est tout <img src='http://www.lexik.fr/blog/symfony/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </p>
<p><i><u>Note</u> : le plugin ne fournit aucune interface permettant de lister les erreurs loggées, libre à chacun de créer son CRUD, module d&#8217;admin generator ou autre interface comme il le souhaite en fonction du besoin.</i></p>
<p>Dépôt du plugin sur Github : <a href="https://github.com/lexik/lxErrorLoggerPlugin">https://github.com/lexik/lxErrorLoggerPlugin</a>.</p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/t2SLoMLi3dA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/presentation-du-lxerrorloggerplugin-1433/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/symfony/presentation-du-lxerrorloggerplugin-1433</feedburner:origLink></item>
		<item>
		<title>Présentation du plugin lxJavascriptPlugin</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/Mfa6qw-2Dek/presentation-du-plugin-lxjavascriptplugin-1408</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/presentation-du-plugin-lxjavascriptplugin-1408#comments</comments>
		<pubDate>Tue, 18 Jan 2011 09:53:28 +0000</pubDate>
		<dc:creator>laurent</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[Méthodologie]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[error]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1408</guid>
		<description><![CDATA[L&#8217;article d&#8217;hier sur les bonnes pratiques Javascript dans un projet Symfony faisait mention d&#8217;un plugin que nous utilisons en interne et qui est maintenant disponible sur Github: lxJavascriptPlugin. Ce court article va brièvement présenter son fonctionnement et son utilisation. L&#8217;installation &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony/presentation-du-plugin-lxjavascriptplugin-1408">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>L&#8217;article d&#8217;hier sur les bonnes pratiques Javascript dans un projet Symfony faisait mention d&#8217;un plugin que nous utilisons en interne et qui est maintenant disponible sur Github: lxJavascriptPlugin. Ce court article va brièvement présenter son fonctionnement et son utilisation.</p>
<p><span id="more-1408"></span></p>
<p>L&#8217;installation du plugin est très rapide:</p>
<ul>
<li>téléchargez <a href="https://github.com/lexik/lxJavascriptPlugin" target="_blank">les sources sur Github</a> dans le répertoire plugins de votre projet,</li>
<li>éditez le fichier config/settings.yml pour y inclure le helper lxJavascript:

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1408code45'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p140845"><td class="code" id="p1408code45"><pre class="yml" style="font-family:monospace;">all:
  .settings:
    standard_helpers: [ ... , lxJavascript ]</pre></td></tr></table></div>

</li>
</ul>
<p>Et c&#8217;est tout! Voyons maintenant le fonctionnement.</p>
<p>Le premier but du plugin est de solutionner les problèmes de granularité du code Javascript dans un projet Symfony. Lorsque l&#8217;on utilise par exemple des widgets JQuery, des partials pour les réseaux sociaux, ou des composants pour des GoogleMap, on se retrouve vite avec du code Javascript éparpillé dans tout notre projet, et par conséquent tout autant éparpillé dans le code des pages générées.</p>
<p>Pour régler ce problème lxJavascriptPlugin propose un premier outil: le helper lxJavascriptHelper. Son utilisation est très similaire à celle du javascriptHelper de Symfony, mais avec la méthode lx_javascript:</p>
<ul>
<li>pour inclure un fichier source externe à la page:

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1408code46'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p140846"><td class="code" id="p1408code46"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> lx_javascript<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

</li>
<li>pour inclure directement du code javascript, par exemple le bout de code pour Google Analytics, le fonctionnement est similaire à celui d&#8217;un slot:

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1408code47'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p140847"><td class="code" id="p1408code47"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> lx_javascript<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  <span style="color: #000000; font-weight: bold;">var</span> _gaq <span style="color: #339933;">=</span> _gaq <span style="color: #339933;">||</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  _gaq<span style="color: #339933;">.</span>push<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'_setAccount'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'*********'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  _gaq<span style="color: #339933;">.</span>push<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'_trackPageview'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">var</span> ga <span style="color: #339933;">=</span> document<span style="color: #339933;">.</span>createElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'script'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ga<span style="color: #339933;">.</span>src <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'https:'</span> <span style="color: #339933;">==</span> document<span style="color: #339933;">.</span>location<span style="color: #339933;">.</span>protocol ? <span style="color: #0000ff;">'https://ssl'</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">'http://www'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">'.google-analytics.com/ga.js'</span><span style="color: #339933;">;</span>
    ga<span style="color: #339933;">.</span>setAttribute<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'async'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'true'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    document<span style="color: #339933;">.</span>documentElement<span style="color: #339933;">.</span>firstChild<span style="color: #339933;">.</span>appendChild<span style="color: #009900;">&#40;</span>ga<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> lx_end_javascript<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Ici la balise &lt;script&gt; n&#8217;est pas nécessaire, mais vous pouvez l&#8217;utiliser si vous le souhaitez (par exemple pour garder la coloration syntaxique de votre IDE)</li>
<li>pour insérer tout le code javascript déclaré via lx_javascript() à la fin de votre layout.php:

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1408code48'); return false;">View Code</a> HTML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p140848"><td class="code" id="p1408code48"><pre class="html" style="font-family:monospace;">&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;en&quot; lang=&quot;en&quot;&gt;
  &lt;head&gt;
    ...
  &lt;/head&gt;
  &lt;body&gt;
    ...
    &lt;?php lx_include_javascripts() ?&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre></td></tr></table></div>

</li>
</ul>
<p>Le soucis de javascript dans les templates est adressé. Reste maintenant le problème du code javascript inséré via d&#8217;autres moyens, comme par exemple un widget qui utilise JQuery. Pour cela lxJavascriptPlugin propose une classe statique lxJavascriptStorage qui offre les fonctionnalités du helper depuis n&#8217;importe où dans votre code:</p>
<ul>
<li>pour ajouter une source externe:

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1408code49'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p140849"><td class="code" id="p1408code49"><pre class="php" style="font-family:monospace;">lxJavascriptStorage<span style="color: #339933;">::</span><span style="color: #004000;">addRemoteJavascript</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

</li>
<li>pour ajouter du code javascript. Voyons par exemple la méthode render() du widget sfWidgetFormJQueryDate:

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1408code50'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p140850"><td class="code" id="p1408code50"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> render<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$attributes</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errors</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">//code</span>
  <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'date_widget'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">render</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #000088;">$attributes</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errors</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>
           <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderTag</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'input'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'hidden'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'size'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">10</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'id'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">generateId</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'_jquery_control'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'disabled'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'disabled'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>
           <a href="http://www.php.net/sprintf"><span style="color: #990000;">sprintf</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000cc; font-style: italic;">&lt;&lt;&lt;EOF
&lt;script type=&quot;text/javascript&quot;&gt;// &lt;![CDATA[
  [...]
// ]]&gt;&lt;/script&gt;
EOF</span>
    <span style="color: #339933;">,</span>
    <span style="color: #666666; font-style: italic;">//arguments du sprintf</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Nous voyons bien le javascript retourné dans le code du widget, et donc en milieu de page. Cette fonction render() pourrait, avec lxJavascriptPlugin, ressembler à ça:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1408code51'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p140851"><td class="code" id="p1408code51"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> render<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$attributes</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errors</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">//code &lt;/code&gt;</span>
&nbsp;
  <span style="color: #000088;">$js</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/sprintf"><span style="color: #990000;">sprintf</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000cc; font-style: italic;">&lt;&lt;&lt;EOF
&lt;script type=&quot;text/javascript&quot;&gt;// &lt;![CDATA[
  [...]
// ]]&gt;&lt;/script&gt;
EOF</span>
    <span style="color: #339933;">,</span>
    <span style="color: #666666; font-style: italic;">//arguments du sprintf</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  lxJavascriptStorage<span style="color: #339933;">::</span><span style="color: #004000;">addJavascriptCode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$js</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'date_widget'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">render</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #000088;">$attributes</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errors</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>
           <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderTag</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'input'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'hidden'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'size'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">10</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'id'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">generateId</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'_jquery_control'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'disabled'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'disabled'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Peu de changements, mais ici le javascript sera rendu avec tout le reste du javascript en pied de page. </code></li>
</ul>
<p>Notez enfin que la méthode lx_include_javascripts() rendra en premier les sources externes, puis le code javascript concaténé dans une unique balise &lt;script&gt;. Si tous les exemples précédents sont utilisés dans une application, le javascript en pied de page donnera ceci:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1408code52'); return false;">View Code</a> JAVASCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p140852"><td class="code" id="p1408code52"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>script src<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&quot;</span> type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;&lt;/</span>script<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #006600; font-style: italic;">// &lt;![CDATA[</span>
  <span style="color: #006600; font-style: italic;">//javascript du widget</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> _gaq <span style="color: #339933;">=</span> _gaq <span style="color: #339933;">||</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
  _gaq.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'_setAccount'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'*********'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  _gaq.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'_trackPageview'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> ga <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'script'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ga.<span style="color: #660066;">src</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'https:'</span> <span style="color: #339933;">==</span> document.<span style="color: #660066;">location</span>.<span style="color: #660066;">protocol</span> <span style="color: #339933;">?</span> <span style="color: #3366CC;">'https://ssl'</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'http://www'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'.google-analytics.com/ga.js'</span><span style="color: #339933;">;</span>
    ga.<span style="color: #660066;">setAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'async'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'true'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    document.<span style="color: #660066;">documentElement</span>.<span style="color: #660066;">firstChild</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>ga<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #006600; font-style: italic;">/* ]]&gt; */</span><span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

</li>
</ul>
<p>Vous pouvez obtenir <a href="https://github.com/lexik/lxJavascriptPlugin">lxJavascriptPlugin sur Github</a>.</p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/Mfa6qw-2Dek" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/presentation-du-plugin-lxjavascriptplugin-1408/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/symfony/presentation-du-plugin-lxjavascriptplugin-1408</feedburner:origLink></item>
		<item>
		<title>Astuces de développement javascript avec symfony</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/HGVXKSYrKZg/astuces-de-developpement-javascript-avec-symfony-1382</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/astuces-de-developpement-javascript-avec-symfony-1382#comments</comments>
		<pubDate>Mon, 17 Jan 2011 15:06:09 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1382</guid>
		<description><![CDATA[Dans cet article nous allons voir quelques astuces et bonnes pratiques, non pas directement de développement symfony mais de développement javascript au sein d’un projet symfony. Si l&#8217;on reprend quelques bases de bonnes pratiques de développement javascript, on constate : &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony/astuces-de-developpement-javascript-avec-symfony-1382">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Dans cet article nous allons voir quelques astuces et bonnes pratiques, non pas directement de développement symfony mais de développement javascript au sein d’un projet symfony.</p>
<p>Si l&#8217;on reprend quelques bases de bonnes pratiques de développement javascript, on constate :</p>
<ul>
<li>que vos javascripts doivent être non-intrusifs, autrement dit là pour améliorer l&#8217;expérience utilisateur et en aucun cas être indispensable au fonctionnement d&#8217;une page ;</li>
<li>que les javascript doivent être combinés en 1 seul fichier et minifié (ceci afin de limiter le nombre de requête HTTP et car le chargement de la page est arrêté à chaque balise script, notamment à cause d&#8217;un éventuel <code>document.write();</code> ;</li>
<li>que l&#8217;appel au javascript doit être en bas de page ;</li>
</ul>
<p><em>Cette liste est bien entendu non exhaustive, vous trouverez une <a href="http://developer.yahoo.com/performance/rules.html" target="_blank">liste plus détaillée par ici</a>.</em></p>
<p>Toutes ces bonnes pratiques de développement Javascript n’ont pas toujours été facilitées dans symfony, notamment à la grande époque des helpers link_to_remote() &#038; co. qui en ont ravi certains et fait cauchemarder d’autres. Et aujourd&#8217;hui encore bon nombre de widgets de formulaire retournent directement du code javascript (dépendant de jQuery ou autre) et qui ne fonctionneront évidemment plus dès lors que vos javascripts se trouveront en bas de page.</p>
<p><span id="more-1382"></span></p>
<h4>1. Où placer les javascripts dans le document</h4>
<p>Idéalement et selon les recommandations de Yslow, en bas de page, donc juste avant la balise fermante <code><body></code> de votre layout.php. Ceci afin de ne pas ralentir inutilement le début du chargement de votre page, puisque chaque balise script bloque le chargement de la page (notamment pour gérer le <code>document.write();</code>).<br />
Source : <a href="http://developer.yahoo.com/performance/rules.html#js_bottom" target="_blank">http://developer.yahoo.com/performance/rules.html#js_bottom</a></p>
<p>Si cette méthode ne vous gênera pas pour les librairies tierces telles que jQuery, qu&#8217;en est-il par contre de vos codes javascript ? Ils doivent également se trouver dans des fichiers séparés, dissociés de votre document HTML. Néanmoins comme je vois souvent le besoin pour les développeurs d&#8217;avoir le code javascript au sein du template symfony, voici une technique pour qu&#8217;il soit tout de même placé en fin de page : via un slot.</p>
<p>Un petit exemple de code :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1382code54'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p138254"><td class="code" id="p1382code54"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// indexSuccess.php :</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> slot<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'javascript'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
  console<span style="color: #339933;">.</span><a href="http://www.php.net/log"><span style="color: #990000;">log</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'javascript @ bottom'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> end_slot<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// layout.php :</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> include_javascripts<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> include_slot<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'javascript'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Vous pourrez ainsi éditer votre code javascript depuis votre template PHP, bénéficier par exemple de valeurs dynamiques de PHP et pour autant que le code soit bien inclus en bas de page. Toutefois je vous recommande d&#8217;écrire du javascript là où il doit se trouver, à savoir dans un fichier JS&#8230;</p>
<p>De plus l&#8217;inconvénient majeur du slot est qu&#8217;il ne peut contenir qu&#8217;une valeur, il est écrasé à chaque utilisation. La technique fonctionne mais est très limitée. Pour ces besoins nous avons écrit chez Lexik un petit plugin &laquo;&nbsp;lxJavascript&nbsp;&raquo;, très similaire à l&#8217;utilisation d&#8217;un slot mais optimisé pour l&#8217;inclusion de javascripts. Il gère donc le multiple ajout, supprime les éventuelles multiples balises script pour en conserver qu&#8217;une seule, etc. Vous en saurez plus demain, le plugin sort en OpenSource sur le <a href="https://github.com/lexik" target="_blank">Github de Lexik</a>.</p>
<h4>2. Compression</h4>
<p>La compression des javascripts (c&#8217;est valable aussi pour les CSS) est une des tâches d&#8217;optimisations les plus importantes et également une des plus simples, du moins via les plugins symfony. Cette technique consiste à compresser tous vos fichiers javascript en 1 seul et surtout d&#8217;y appliquer un numéro de version (un timestamp le plus souvent) afin de prévenir des problèmes de cache dans vos mises à jour.</p>
<p>Les principaux plugins :</p>
<ul>
<li><a href="http://www.symfony-project.org/plugins/sfCombinePlugin" target="_blank">sfCombinePlugin</a>
<li><a href="http://www.symfony-project.org/plugins/npAssetsOptimizerPlugin" target="_blank">npAssetsOptimizerPlugin</a></li>
<li><a href="http://www.symfony-project.org/plugins/swCombinePlugin" target="_blank">swCombinePlugin</a></li>
</ul>
<p>Chez Lexik, nous utilisons <a href="http://www.symfony-project.org/plugins/npAssetsOptimizerPlugin" target="_blank">npAssetsOptimizerPlugin</a>, un plugin de <a href="http://www.akei.com/" target="_blank">Nicolas Perriault</a>, extrêmement simple à installer et paramétrer. Sur votre environnement de production, vous obtiendrez ainsi un fichier javascript compressé <code>/js/optimized.js?1294759429</code> qui contient un timestamp permettant à chaque modifications des fichiers d&#8217;être prises en compte sans problème de cache.</p>
<p>Nous n&#8217;appliquons pas la compression pour les librairies externes telles que jQuery que nous déléguons aux <a href="http://code.google.com/apis/libraries/devguide.html" target="_blank">serveurs CDN de Google</a>, cela apporte ces avantages notables :</p>
<ul>
<li>l&#8217;avantage du <abbr title="Content Delivery Network">CDN</abbr>, à savoir de proposer des données statiques via un réseau de multiples serveurs dans de multiples points géographiques, afin de permettre un accès très court ;</li>
<li>les navigateurs sont limités sur le nombre de connexions HTTP simultanées sur un même domaine, le téléchargement d&#8217;un javascript sur les serveurs de Google se fera en parallèle ;</li>
<li>les librairies du CDN ont les bonnes en-têtes de cache, par exemple la version 1.4.4 de jQuery restera en cache pendant 1 an sur le client, cela signifie également qu&#8217;un internaute peut bénéficier du cache téléchargé depuis un autre site, pas forcément sur le votre.</li>
</ul>
<h4>3. Accéder à certaines données dynamiques depuis javascript</h4>
<p>Il peut parfois être très utile depuis javascript d&#8217;accéder à certaines données dynamiques telles que la culture de l&#8217;utilisateur, du routing pour des appels Ajax ou encore de l&#8217;i18n. Il suffit de s&#8217;appuyer sur un simple fichier de configuration via un tableau de données JSON généré depuis une action symfony. J&#8217;ai écrit sur mon blog personnel un article détaillé sur le sujet <a href="http://blog.jeremybarthe.com/post/1465024153/configurations-javascript-dynamiques-en-symfony" target="_blank">Configurations Javascript dynamiques en Symfony</a>.</p>
<h4>4. Javascript depuis les widget</h4>
<p>Maintenant que vos inclusions de javascripts se trouvent en bas de page, jQuery par exemple, que faire de nos chers widgets jQuery Autocompleter <code>sfWidgetFormJQueryAutocompleter</code> et autre Datepicker <code>sfWidgetFormJQueryDate</code> qui retournent des champs de formulaire et le javascript d’initialisation du composant ? Eh bien, ne plus les utiliser&#8230; Simplement car ils seront inclus avant jQuery et vous aurez donc droit à l’erreur &laquo;&nbsp;jQuery is not defined&nbsp;&raquo;. Sans être aussi extrême, vous pouvez charger jQuery en haut de page (via les CDN de Google) et votre script compressé en bas de page, les widgets de formulaire seront alors à nouveau fonctionnels.</p>
<p>Cela fait déjà quelques temps que chez Lexik nous avons fait le choix d&#8217;enlever tous ces widgets pour les ré-écrire et les adapter à nos besoins. Les javascripts des widgets passent par notre plugin lxJavascript ce qui permet de les inclure là où on le souhaite. Egalement, le javascript retourné par ces widgets correspond à une utilisation basique du composant, dans un cas concrêt il est souvent nécessaire d&#8217;en ré-écrire une bonne part. Il peut être pratique par contre que le widget retourne seulement la sémantique HTML adaptée, par exemple dans le cas d&#8217;un Autocomplete un champ hidden pour stocker la valeur et un champ texte pour l&#8217;autocomplete, aussi nos widgets ont une option pour retourner ou non le code javascript.</p>
<h4>5. Optimisation frontend</h4>
<p>Presque aussi important que la compression, la configuration d&#8217;apache pour mettre en cache certains de vos fichiers statiques. Typiquement, maintenant que vos fichiers javascripts et CSS sont compressés en 1 seul et possèdent un timestamp unique par version, il serait dommage de les recharger à chaque chargement de page&#8230; Vous devez donc configurer le module Expires d&#8217;apache via le fichier de config du vhost ou via le .htaccess, en voici un exemple :</p>
<pre>
<IfModule mod_expires.c>
  ExpiresActive on
  ExpiresByType text/css "access plus 1 year"
  ExpiresByType text/javascript "access plus 1 year"
</IfModule>
</pre>
<p>Vos fichiers javascript et CSS seront ainsi en cache pendant 1 an, attention du coup à ne pas avoir de fichier sans numéro de version, car ils resteraient en cache et vos internautes ne bénéficieraient pas de vos mises à jour&#8230;</p>
<p>&nbsp;</p>
<p>Dernière chose, si ce n&#8217;est pas encore fait, installez et testez <a href="http://developer.yahoo.com/yslow/" target="_blank">Yslow</a> pour trouver des pistes d&#8217;optimisations de performance de vos sites.</p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/HGVXKSYrKZg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/astuces-de-developpement-javascript-avec-symfony-1382/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/symfony/astuces-de-developpement-javascript-avec-symfony-1382</feedburner:origLink></item>
		<item>
		<title>Utilisation de l’event dispatcher depuis les classes du modèle.</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/t8ifAWTznm4/utilisation-de-levent-dispatcher-depuis-les-classes-du-modele-1337</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/utilisation-de-levent-dispatcher-depuis-les-classes-du-modele-1337#comments</comments>
		<pubDate>Mon, 20 Dec 2010 09:17:03 +0000</pubDate>
		<dc:creator>Samuel Breton</dc:creator>
				<category><![CDATA[1.4.x]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[event dispatcher]]></category>
		<category><![CDATA[model]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1337</guid>
		<description><![CDATA[Le but de cet article n&#8217;est pas d&#8217;expliquer le fonctionnement des événements symfony, la documentation officielle est très bien faite à ce sujet, et pas mal d&#8217;articles expliquant leur implementation existent déjà. Le but est juste de savoir comment faire &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony/utilisation-de-levent-dispatcher-depuis-les-classes-du-modele-1337">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Le but de cet article n&#8217;est pas d&#8217;expliquer le fonctionnement des événements symfony, <a href="http://www.symfony-project.org/reference/1_4/fr/15-Events" target="_blank">la documentation officielle</a> est très bien faite à ce sujet, et pas mal d&#8217;articles expliquant leur implementation existent déjà.</p>
<p>Le but est juste de savoir comment faire pour avoir accès à l&#8217;event dispatcher depuis les classes du modèle, de manière à pouvoir lever des événements &laquo;&nbsp;métiers&nbsp;&raquo; qui permettent des traitements qui se rapprochent des trigger sql. L&#8217;avantage est de rester au sein de l&#8217;application symfony et ne pas disperser la logique. C&#8217;est une problèmatique que nous avons rencontré à plusieurs reprises dans les projets et nous avons pu trouver cette implementation grace à n1k0 de chez <a href="http://www.akei.com/fr" target="_blank">Akei</a>.</p>
<p><span id="more-1337"></span></p>
<p>(Pour la suite, je vais me servir d&#8217;une partie du modèle de Jobeet comme je l&#8217;avais fait dans <a href="http://www.lexik.fr/blog/symfony/symfony/qui-leu-crud-ou-comment-creer-un-theme-pour-les-crud-doctrine-de-symfony-1181">mon post précédent</a>)</p>
<p>A la base, l&#8217;event dispatcher se trouve dans le contexte, et donc accessible principalement depuis les actions des modules. L&#8217;idée est de le rendre accessible aux classes du modèle doctrine de manière à pouvoir notifier des événements &laquo;&nbsp;métier&nbsp;&raquo; directement depuis les méthodes. On va donc passer l&#8217;event dispatcher à la classe de base dont hérite toutes les classes du modèle. Ou plus exactement, on va rajouter une classe custom dans la pile d&#8217;héritage des classes du modèle.</p>
<p>On créé donc une classe CustomDoctrineRecord, que je place dans /lib/model/doctrine/record/CustomDoctrineRecord.class.php pour éviter qu&#8217;elle se retrouve noyée avec les classes du modèle. On va faire passer à cette classe l&#8217;event dispatcher par des méthodes statiques.<br />
Les classes de base du modèle héritent de sfDoctrineRecord, il faut donc impérativement que la classe custom hérite elle aussi de sfDoctrineRecord.</p>
<p>Fichier : /lib/model/doctrine/record/CustomDoctrineRecord.class.php</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1337code61'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p133761"><td class="code" id="p1337code61"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
abstract <span style="color: #000000; font-weight: bold;">class</span> CustomDoctrineRecord <span style="color: #000000; font-weight: bold;">extends</span> sfDoctrineRecord
<span style="color: #009900;">&#123;</span>
  static <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$dispatcher</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Sets the EventDispatcher
   *
   * @param sfEventDispatcher $dispatcher 
   */</span>
  static <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setEventDispatcher<span style="color: #009900;">&#40;</span>sfEventDispatcher <span style="color: #000088;">$dispatcher</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$dispatcher</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$dispatcher</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Returns the EventDispatcher
   *
   * @return sfEventDispatcher
   */</span>
  static <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getEventDispatcher<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$dispatcher</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Returns if EventDispatcher is available
   *
   * @return boolean
   */</span>
  static <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> hasDispatcher<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">getEventDispatcher</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> instanceOf sfEventDispatcher<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Maintenant il faut spécifier à doctrine d&#8217;utiliser notre classe custom comme classe de référence des classes modèles, on utilise la méthode configureDoctrine() de sfProjectConfiguration. Aprés quoi on va avoir besoin de passer l&#8217;event dispatcher à notre classe. On va donc catcher l&#8217;événement &laquo;&nbsp;context.load_factories&nbsp;&raquo; qui est déclenché une fois que le contexte est initialisé pour aller initialiser la classe CustomDoctrineRecord.</p>
<p>Fichier : /config/ProjectConfiguration.class.php</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1337code62'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p133762"><td class="code" id="p1337code62"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #b1b100;">require_once</span> <a href="http://www.php.net/dirname"><span style="color: #990000;">dirname</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/../lib/vendor/symfony/lib/autoload/sfCoreAutoload.class.php'</span><span style="color: #339933;">;</span>
sfCoreAutoload<span style="color: #339933;">::</span><span style="color: #004000;">register</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> ProjectConfiguration <span style="color: #000000; font-weight: bold;">extends</span> sfProjectConfiguration
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setup<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    parent<span style="color: #339933;">::</span><span style="color: #004000;">setup</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">enablePlugins</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span>
      <span style="color: #0000ff;">'sfDoctrinePlugin'</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">dispatcher</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'context.load_factories'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'listenToContextFactoriesLoaded'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Defines the base objects' classe
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configureDoctrine<span style="color: #009900;">&#40;</span>Doctrine_Manager <span style="color: #000088;">$manager</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'doctrine_model_builder_options'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span>
      <span style="color: #0000ff;">'baseClassName'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'CustomDoctrineRecord'</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Objects can acces the EventDispatcher
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> listenToContextFactoriesLoaded<span style="color: #009900;">&#40;</span>sfEvent <span style="color: #000088;">$event</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    CustomDoctrineRecord<span style="color: #339933;">::</span><span style="color: #004000;">setEventDispatcher</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$event</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSubject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getEventDispatcher</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Aprés ca, il nous reste à faire un petit</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1337code63'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p133763"><td class="code" id="p1337code63"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">./</span>symfony doctrine<span style="color: #339933;">:</span>build <span style="color: #339933;">--</span>all<span style="color: #339933;">-</span>classes</pre></td></tr></table></div>

<p>Et on peut vérifier l&#8217;inpact en ouvrant une classe de base, et on trouve bien que la classe hérite de notre classe CustomDoctrineRecord</p>
<p>Fichier : /lib/model/doctrine/base/BaseJobeetJob.class.php</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1337code64'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p133764"><td class="code" id="p1337code64"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #339933;">...</span>
abstract <span style="color: #000000; font-weight: bold;">class</span> BaseJobeetJob <span style="color: #000000; font-weight: bold;">extends</span> CustomDoctrineRecord
<span style="color: #009900;">&#123;</span>
<span style="color: #339933;">...</span></pre></td></tr></table></div>

<p>Il est donc maintenant possible de lever des événements depuis les classes du modèle. Pour exemple je vais lever un événement à l&#8217;insertion d&#8217;un nouveau Job. Cet événement pourra être utilisé par la suite pour faire ce que l&#8217;on veut, comme par exemple envoyer une email au modèrateur l&#8217;informant qu&#8217;un nouveau job a été saisi sur le site.</p>
<p>Fichier : /lib/model/doctrine/JobeetJob.class.php</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1337code65'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p133765"><td class="code" id="p1337code65"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> JobeetJob <span style="color: #000000; font-weight: bold;">extends</span> BaseJobeetJob
<span style="color: #009900;">&#123;</span>
  <span style="color: #009933; font-style: italic;">/**
   * @param Doctrine_Event $event 
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> postInsert<span style="color: #009900;">&#40;</span><span style="color: #000088;">$event</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">hasDispatcher</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">getEventDispatcher</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasListeners</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'JobeetJob.Inserted'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">getEventDispatcher</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">notify</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> sfEvent<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'JobeetJob.Inserted'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>C&#8217;est un exemple tout simple, mais les possibilités sont immenses. Attention aux événements en cascades, ca peut très vite devenir un casse tête à debugger !</p>
<p>Dernier petit tips, pour pouvoir faire des tests de vos méthodes qui lèvent des événements : c&#8217;est à mis chemin entre les tests unitaires et les tests fonctionnels. J&#8217;ai voulu tester des enchainements de méthodes qui levaient des événements, et je voulais vérifier que les règles de gestion étaient respectées. Je suis donc parti du bootstap unitaire où j&#8217;ai initialisé un contexte que je passe à ma classe de base, de manière à ce que les événements soient diffusés.</p>
<p>Fichier : /test/bootstrap/unit_event.php</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1337code66'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p133766"><td class="code" id="p1337code66"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #b1b100;">include</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/dirname"><span style="color: #990000;">dirname</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/unit.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$configuration</span> <span style="color: #339933;">=</span> ProjectConfiguration<span style="color: #339933;">::</span><span style="color: #004000;">getApplicationConfiguration</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'frontend'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'test'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> sfContext<span style="color: #339933;">::</span><span style="color: #004000;">createInstance</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$configuration</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
CustomDoctrineRecord<span style="color: #339933;">::</span><span style="color: #004000;">setEventDispatcher</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$configuration</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getEventDispatcher</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Quand on commence à utiliser les événements, il y a deux réactions possibles. Il y a les réfractaires qui disent &laquo;&nbsp;c&#8217;est null, ca sert a rien&nbsp;&raquo;, soit on devient accro et on commence à en mettre de partout. Si vous faites parti du deuxième groupe, voici quelques conseils élémentaires mais important à respecter pour éviter que le debuggage se transforme en calvaire :</p>
<ul>
<li>mettre des noms d&#8217;événements explicites ;</li>
<li>centraliser les écouteurs.</li>
</ul>
<p>Bon codage à tous, et bonnes fêtes <img src='http://www.lexik.fr/blog/symfony/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/t8ifAWTznm4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/utilisation-de-levent-dispatcher-depuis-les-classes-du-modele-1337/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/symfony/utilisation-de-levent-dispatcher-depuis-les-classes-du-modele-1337</feedburner:origLink></item>
		<item>
		<title>Utilisation de VHost pour l’accès au backend</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/duYCFUOoO9U/utilisation-de-vhost-pour-lacces-au-backend-1307</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/utilisation-de-vhost-pour-lacces-au-backend-1307#comments</comments>
		<pubDate>Wed, 27 Oct 2010 07:54:59 +0000</pubDate>
		<dc:creator>cedric</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[virtual hosts]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1307</guid>
		<description><![CDATA[L&#8217;idée est de ne plus accéder au backend de notre site web en utilisant backend.php dans l&#8217;url, mais de passer par un sous domaine. http://www.super-website.com &#8594; frontend http://admin.super-website.com &#8594; backend Supposons que mon projet Symfony se trouve dans /home/public_html/. Commençons &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony/utilisation-de-vhost-pour-lacces-au-backend-1307">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>L&#8217;idée est de ne plus accéder au backend de notre site web en utilisant backend.php dans l&#8217;url, mais de passer par un sous domaine.</p>
<ul>
<li>http://www.super-website.com &rarr; frontend</li>
<li>http://admin.super-website.com &rarr; backend</li>
</ul>
<p>Supposons que mon projet Symfony se trouve dans /home/public_html/.<br />
Commençons par ajouter un vhost pour définir le sous domaine dans Apache. On précise au sous domaine que le fichier index pour ce sous domaine sera backend.php à l&#8217;aide de la directive DirectoryIndex.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1307code70'); return false;">View Code</a> CONSOLE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p130770"><td class="code" id="p1307code70"><pre class="console" style="font-family:monospace;">&lt;VirtualHost *:80&gt;
  ServerName admin.super-website.fr
  DocumentRoot &quot;/home/public_html/web&quot;
  DirectoryIndex backend.php
&nbsp;
  &lt;Directory &quot;/home/public_html/web&quot;&gt;
    AllowOverride All
    Allow from All
  &lt;/Directory&gt;
&nbsp;
  Alias /sf /home/public_html/lib/vendor/symfony/data/web/sf
  &lt;Directory &quot;/home/public_html/lib/vendor/symfony/data/web/sf&quot;&gt;
    AllowOverride All
    Allow from All
  &lt;/Directory&gt;
&lt;/VirtualHost&gt;</pre></td></tr></table></div>

<p>Ensuite il faut modifier le .htaccess de Symfony afin qu&#8217;il redirige les requêtes http du sous domaine vers le fichier backend.php.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1307code71'); return false;">View Code</a> CONSOLE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p130771"><td class="code" id="p1307code71"><pre class="console" style="font-family:monospace;">Options +FollowSymLinks +ExecCGI
&nbsp;
&lt;IfModule mod_rewrite.c&gt;
  RewriteEngine On
&nbsp;
  # uncomment the following line, if you are having trouble
  # getting no_script_name to work
  #RewriteBase /
&nbsp;
  # we skip all files with .something
  #RewriteCond %{REQUEST_URI} \..+$
  #RewriteCond %{REQUEST_URI} !\.html$
  #RewriteRule .* - [L]
&nbsp;
  # we check if the .html version is here (caching)
  RewriteRule ^$ index.html [QSA]
  RewriteRule ^([^.]+)$ $1.html [QSA]
&nbsp;
  # redirect to the backend web controller
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{HTTP_HOST}  ^admin.*
  RewriteRule ^(.*)$ backend.php [QSA,L]
&nbsp;
  # no, so we redirect to our front web controller
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)$ index.php [QSA,L]
&lt;/IfModule&gt;</pre></td></tr></table></div>

<p>Au niveau de la config Symfony, nous pouvons maintenant masquer le nom du script dans les urls du backend:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1307code72'); return false;">View Code</a> CONSOLE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p130772"><td class="code" id="p1307code72"><pre class="console" style="font-family:monospace;"># apps/backend/config/settings.yml
prod:
  .settings:
    no_script_name:    true
    ...</pre></td></tr></table></div>

<p>Et pour finir ne pas oublier de vider le cache =), le backend est maintenant accessible sur http://admin.super-website.com.</p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/duYCFUOoO9U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/utilisation-de-vhost-pour-lacces-au-backend-1307/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/symfony/utilisation-de-vhost-pour-lacces-au-backend-1307</feedburner:origLink></item>
		<item>
		<title>Qui l’eu CRUD ? Ou comment créer un thème pour les CRUD Doctrine de Symfony.</title>
		<link>http://feedproxy.google.com/~r/BlogSymfony-LexikMontpellier/~3/_CMjGHY4q7Q/qui-leu-crud-ou-comment-creer-un-theme-pour-les-crud-doctrine-de-symfony-1181</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/qui-leu-crud-ou-comment-creer-un-theme-pour-les-crud-doctrine-de-symfony-1181#comments</comments>
		<pubDate>Mon, 09 Aug 2010 08:28:18 +0000</pubDate>
		<dc:creator>olivier</dc:creator>
				<category><![CDATA[1.3.x]]></category>
		<category><![CDATA[1.4.x]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[crud]]></category>
		<category><![CDATA[generate]]></category>
		<category><![CDATA[module]]></category>
		<category><![CDATA[theme]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1181</guid>
		<description><![CDATA[Symfony propose des outils très puissants pour faciliter le développement d&#8217;applications et surtout la génération des modules grâce à l&#8217;Admin Generator et le CRUD. Chacunes de ces solutions à ses avantages et ses inconvénients. L&#8217;admin generator permet en une commande &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony/qui-leu-crud-ou-comment-creer-un-theme-pour-les-crud-doctrine-de-symfony-1181">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Symfony propose des outils très puissants pour faciliter le développement d&#8217;applications et surtout la génération des modules grâce à l&#8217;Admin Generator et le CRUD. Chacunes de ces solutions  à ses avantages et ses inconvénients.</p>
<p>L&#8217;admin generator permet en une commande d&#8217;avoir un module complet et fonctionnel avec de nombreuses fonctionnalités, le tout relativement configurable. En contre partie, l&#8217;ajout de fonctionnalités spécifiques et la mise en forme peuvent rapidement s&#8217;avérer fastidieuses. Être obligé d&#8217;aller fouiller dans le cache pour aller faire des copier/coller afin de pouvoir surcharger une action, c&#8217;est comme qui dirait, bien mais pas top&#8230;</p>
<p><span id="more-1181"></span></p>
<p>  D&#8217;autre part le CRUD permet lui aussi de générer en une seule commade un module, mais ce module est plus que limité et on se retrouve systématiquement à ré-implémenter les mêmes fonctionnalités de base comme le pager, les filters, etc. Par contre travailler avec un CRUD permet de garder la main sur le code, ce qui n&#8217;est pas négligeable.</p>
<p>C&#8217;est pourquoi je vous propose de voir comment fabriquer un thème pour le CRUD de manière à l&#8217;enrichir de quelques fonctionnalités indispensables pour ne pas avoir à les ré-écrire systematiquement et ainsi ganger du temps. Je vais en profiter pour développer ce thème au sein d&#8217;un plugin de manière à pouvoir s&#8217;en resservir facilement.</p>
<p>Pour se faire je vais partir d&#8217;un projet vierge type sandbox auquel je rajoute le plugin <a href="http://www.symfony-project.org/plugins/sfTaskExtraPlugin">sfTaskExtraPlugin</a> qui facilite grandement la génération de plugins.<br />
Pour me simplifier la vie, je vais reprendre <a href="http://www.symfony-project.org/jobeet/1_4/Doctrine/en/03#chapter_03_the_schema">le schema.yml</a> et les fixtures (<a href="http://svn.jobeet.org/doctrine/trunk/data/fixtures/affiliates.yml">affiliates.yml</a>, <a href="http://svn.jobeet.org/doctrine/trunk/data/fixtures/category.yml">category.yml</a> et <a href="http://svn.jobeet.org/doctrine/trunk/data/fixtures/jobs.yml">jobs.yml</a>) de Jobeet pour avoir un modèle sur lequel m&#8217;appuyer pour les exemples.</p>
<p>(Attention le fichier de fixture category.yml comporte les traductions, alors que le schema n&#8217;a pas le behavior I18n. Il faut au choix modifier le schema.yml pour rajouter le behavior ou modifier les categories pour supprimer les traductions)</p>
<p>Un petit <i>./symfony doctrine:build &#8211;all &#8211;and-load</i> et nous voilà parti.</p>
<h2>Let&#8217;s rock!</h2>
<p>Pour fabriquer un module de type CRUD symfony se sert de template de code pour générer les actions et les vues. Ces fichiers sont bien cachés au fin fond du symfony ! On les trouve dans</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code89'); return false;">View Code</a> PATH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p118189"><td class="code" id="p1181code89"><pre class="path" style="font-family:monospace;">/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/data/generator/sfDoctrineModule/default</pre></td></tr></table></div>

</p>
<p>On va donc utiliser le thème par défaut que l&#8217;on va enrichir.</p>
<p>Tout d&#8217;abord, on va générer l&#8217;arborescence du plugin grâce à la commande generate:plugin de sfTaskExtraPlugin.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code90'); return false;">View Code</a> CONSOLE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p118190"><td class="code" id="p1181code90"><pre class="console" style="font-family:monospace;">./symfony generate:plugin myCrudThemePlugin</pre></td></tr></table></div>

<p>Puis on prépare l&#8217;arborescence qui va accueillir les fichiers du template à l&#8217;intérieur du plugin.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code91'); return false;">View Code</a> CONSOLE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p118191"><td class="code" id="p1181code91"><pre class="console" style="font-family:monospace;">mkdir -p plugins/myCrudThemePlugin/data/generator/sfDoctrineModule/myCrudTheme</pre></td></tr></table></div>

<p>Et on y copie tous les fichiers du thème par défaut.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code92'); return false;">View Code</a> CONSOLE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p118192"><td class="code" id="p1181code92"><pre class="console" style="font-family:monospace;">cp -r lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/data/generator/sfDoctrineModule/default/* plugins/myCrudThemePlugin/data/generator/sfDoctrineModule/myCrudTheme</pre></td></tr></table></div>

<p>Si vous avez fait un checkout de symfony, les fichiers que vous avez copiés contiennent les informations de svn. Il faut nettoyer tout ça. Je vous propose une petite ligne de commande qui permet de faire ca.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code93'); return false;">View Code</a> CONSOLE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p118193"><td class="code" id="p1181code93"><pre class="console" style="font-family:monospace;">find plugins/myCrudThemePlugin/data/generator/sfDoctrineModule/myCrudTheme -name .svn -exec rm -rf {} \;</pre></td></tr></table></div>

<p>Les fichiers sont prêts. A ce stade, on pourrait déjà générer un thème en utilisant notre thème. Il sufirait d&#8217;activer le plugin dans</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code94'); return false;">View Code</a> PATH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p118194"><td class="code" id="p1181code94"><pre class="path" style="font-family:monospace;">/config/ProjectConfiguration.class.php</pre></td></tr></table></div>

</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code95'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p118195"><td class="code" id="p1181code95"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> ProjectConfiguration <span style="color: #000000; font-weight: bold;">extends</span> sfProjectConfiguration
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setup<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">enablePlugins</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span>
      <span style="color: #339933;">...</span>
      <span style="color: #0000ff;">'myCrudThemePlugin'</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Et de lancer la commande :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code96'); return false;">View Code</a> CONSOLE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p118196"><td class="code" id="p1181code96"><pre class="console" style="font-family:monospace;">./symfony doctrine:generate-module --theme=&quot;myCrudTheme&quot; frontend job JobeetJob</pre></td></tr></table></div>

<p>Mais ne le faites pas ! :p Ca n&#8217;aurait pas un grand intérêt étant donné que l&#8217;on a rien changé par rapport au thème par défaut.</p>
<p>Nous allons commencer par rajouter un pager sur la page de listing. Il faut modifier l&#8217;action dans</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code97'); return false;">View Code</a> PATH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p118197"><td class="code" id="p1181code97"><pre class="path" style="font-family:monospace;">/plugins/myCrudThemePlugin/data/generator/sfDoctrineModule/myCrudTheme/parts/indexAction.php</pre></td></tr></table></div>

</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code98'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p118198"><td class="code" id="p1181code98"><pre class="php" style="font-family:monospace;">&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeIndex<span style="color: #009900;">&#40;</span>sfWebRequest <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$query</span> <span style="color: #339933;">=</span> Doctrine_Core<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'&lt;?php echo $this-&gt;getModelClass() ?&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createQuery</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'&lt;?php echo strtolower(substr($this-&gt;getModelClass(), 0, 1)) ?&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">pager</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfDoctrinePager<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'&lt;?php echo $this-&gt;getModelClass() ?&gt;'</span><span style="color: #339933;">,</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'app_myCrudThemePlugin_pagination'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">20</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">pager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setQuery</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$query</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">pager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setPage</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'page'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">pager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Pour l&#8217;affichage du pager, je vous propose de créer un partial que l&#8217;on va inclure dans un module du plugin. Etant donné que le fonctionnement est générique, on a pas besoin qu&#8217;il soit recopié systèmatiquement dans les modules générés.</p>
<p>On va générer un module appelé shared qui va accueillir le partial du pager et éventuellement d&#8217;autres éléments que l&#8217;on voudra mutualiser.<br />
La encore sfTaskExtraPlugin nous aide bien car il intégre une commande qui fais ca.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code99'); return false;">View Code</a> CONSOLE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p118199"><td class="code" id="p1181code99"><pre class="console" style="font-family:monospace;">./symfony generate:plugin-module myCrudThemePlugin shared</pre></td></tr></table></div>

<p>Il nous reste à aller créer notre partial dans</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code100'); return false;">View Code</a> PATH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1181100"><td class="code" id="p1181code100"><pre class="path" style="font-family:monospace;">/plugins/myCrudThemePlugin/modules/shared/templates/_pager.php</pre></td></tr></table></div>

</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code101'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1181101"><td class="code" id="p1181code101"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$pager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">haveToPaginate</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  <span style="color: #339933;">&lt;</span>div <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;pagination&quot;</span><span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>a title<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;First Page&quot;</span> href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&lt;?php echo (isset(<span style="color: #006699; font-weight: bold;">$object</span>)) ? url_for(<span style="color: #006699; font-weight: bold;">$route</span>, <span style="color: #006699; font-weight: bold;">$object</span>) : url_for(<span style="color: #006699; font-weight: bold;">$route</span>) ?&gt;?page=&lt;?php echo <span style="color: #006699; font-weight: bold;">$pager-&gt;getFirstPage</span>() ?&gt;&quot;</span><span style="color: #339933;">&gt;</span>« First<span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>a title<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;Previous Page&quot;</span> href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&lt;?php echo (isset(<span style="color: #006699; font-weight: bold;">$object</span>)) ? url_for(<span style="color: #006699; font-weight: bold;">$route</span>, <span style="color: #006699; font-weight: bold;">$object</span>) : url_for(<span style="color: #006699; font-weight: bold;">$route</span>) ?&gt;?page=&lt;?php echo <span style="color: #006699; font-weight: bold;">$pager-&gt;getPreviousPage</span>() ?&gt;&quot;</span><span style="color: #339933;">&gt;</span>« Previous<span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$pager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLinks</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$page</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    <span style="color: #339933;">&lt;</span>a title<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&lt;?php echo <span style="color: #006699; font-weight: bold;">$page</span> ?&gt;&quot;</span> <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;number&lt;?php echo (<span style="color: #006699; font-weight: bold;">$page</span> == <span style="color: #006699; font-weight: bold;">$pager-&gt;getPage</span>()) ? ' current' : '' ?&gt;&quot;</span> href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&lt;?php echo (isset(<span style="color: #006699; font-weight: bold;">$object</span>)) ? url_for(<span style="color: #006699; font-weight: bold;">$route</span>, <span style="color: #006699; font-weight: bold;">$object</span>) : url_for(<span style="color: #006699; font-weight: bold;">$route</span>) ?&gt;?page=&lt;?php echo <span style="color: #006699; font-weight: bold;">$page</span> ?&gt;&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$page</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    <span style="color: #339933;">&lt;</span>a title<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;Next Page&quot;</span> href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&lt;?php echo (isset(<span style="color: #006699; font-weight: bold;">$object</span>)) ? url_for(<span style="color: #006699; font-weight: bold;">$route</span>, <span style="color: #006699; font-weight: bold;">$object</span>) : url_for(<span style="color: #006699; font-weight: bold;">$route</span>) ?&gt;?page=&lt;?php echo <span style="color: #006699; font-weight: bold;">$pager-&gt;getNextPage</span>() ?&gt;&quot;</span><span style="color: #339933;">&gt;</span>Next »<span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>a title<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;Last Page&quot;</span> href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&lt;?php echo (isset(<span style="color: #006699; font-weight: bold;">$object</span>)) ? url_for(<span style="color: #006699; font-weight: bold;">$route</span>, <span style="color: #006699; font-weight: bold;">$object</span>) : url_for(<span style="color: #006699; font-weight: bold;">$route</span>) ?&gt;?page=&lt;?php echo <span style="color: #006699; font-weight: bold;">$pager-&gt;getLastPage</span>() ?&gt;&quot;</span><span style="color: #339933;">&gt;</span>Last »<span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
  <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
  <span style="color: #339933;">&lt;</span>div <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;clear&quot;</span><span style="color: #339933;">&gt;&lt;/</span>div<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Un pager générique qui fonctionne pour les <i>sfDoctrineRoute</i> et les <i>sfRequestRoute</i>. Il prends deux paramètres, route (obligatoire) et object (facultatif).</p>
<p>On modifie la vue indexSuccess.php pour la faire fonctionner avec le pager et ajouter le partial du pager.
<p> Dans</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code102'); return false;">View Code</a> PATH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1181102"><td class="code" id="p1181code102"><pre class="path" style="font-family:monospace;">/plugins/myCrudThemePlugin/data/generator/sfDoctrineModule/myCrudTheme/template/templates/indexSuccess.php</pre></td></tr></table></div>

</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code103'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1181103"><td class="code" id="p1181code103"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>h1<span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #b1b100;">echo</span> sfInflector<span style="color: #339933;">::</span><span style="color: #004000;">humanize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPluralName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span> List<span style="color: #339933;">&lt;/</span>h1<span style="color: #339933;">&gt;</span>
&nbsp;
<span style="color: #339933;">&lt;</span>table<span style="color: #339933;">&gt;</span>
  <span style="color: #339933;">&lt;</span>thead<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>tr<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getColumns</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$column</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
      <span style="color: #339933;">&lt;</span>th<span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #b1b100;">echo</span> sfInflector<span style="color: #339933;">::</span><span style="color: #004000;">humanize</span><span style="color: #009900;">&#40;</span>sfInflector<span style="color: #339933;">::</span><span style="color: #004000;">underscore</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$column</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPhpName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>th<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    <span style="color: #339933;">&lt;/</span>tr<span style="color: #339933;">&gt;</span>
  <span style="color: #339933;">&lt;/</span>thead<span style="color: #339933;">&gt;</span>
  <span style="color: #339933;">&lt;</span>tbody<span style="color: #339933;">&gt;</span>
    <span style="color: #009900;">&#91;</span>?php <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$pager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResults</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> $<span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSingularName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> ?<span style="color: #009900;">&#93;</span>
    <span style="color: #339933;">&lt;</span>tr<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getColumns</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$column</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$column</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isPrimaryKey</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/isset"><span style="color: #990000;">isset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'route_prefix'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'route_prefix'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
      <span style="color: #339933;">&lt;</span>td<span style="color: #339933;">&gt;&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;[?php echo url_for('&lt;?php echo <span style="color: #006699; font-weight: bold;">$this-&gt;getUrlForAction</span>(isset(<span style="color: #006699; font-weight: bold;">$this-&gt;params</span>['with_show']) &amp;&amp; <span style="color: #006699; font-weight: bold;">$this-&gt;params</span>['with_show'] ? 'show' : 'edit') ?&gt;', $&lt;?php echo <span style="color: #006699; font-weight: bold;">$this-&gt;getSingularName</span>() ?&gt;) ?]&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#91;</span>?php <span style="color: #b1b100;">echo</span> $<span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSingularName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #b1b100;">echo</span> sfInflector<span style="color: #339933;">::</span><span style="color: #004000;">camelize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$column</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPhpName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> ?<span style="color: #009900;">&#93;</span><span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;&lt;/</span>td<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">else</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
      <span style="color: #339933;">&lt;</span>td<span style="color: #339933;">&gt;&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;[?php echo url_for('&lt;?php echo <span style="color: #006699; font-weight: bold;">$this-&gt;getModuleName</span>() ?&gt;/&lt;?php echo isset(<span style="color: #006699; font-weight: bold;">$this-&gt;params</span>['with_show']) &amp;&amp; <span style="color: #006699; font-weight: bold;">$this-&gt;params</span>['with_show'] ? 'show' : 'edit' ?&gt;?&lt;?php echo <span style="color: #006699; font-weight: bold;">$this-&gt;getPrimaryKeyUrlParams</span>() ?&gt;) ?]&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#91;</span>?php <span style="color: #b1b100;">echo</span> $<span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSingularName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #b1b100;">echo</span> sfInflector<span style="color: #339933;">::</span><span style="color: #004000;">camelize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$column</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPhpName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> ?<span style="color: #009900;">&#93;</span><span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;&lt;/</span>td<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">else</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
      <span style="color: #339933;">&lt;</span>td<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#91;</span>?php <span style="color: #b1b100;">echo</span> $<span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSingularName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #b1b100;">echo</span> sfInflector<span style="color: #339933;">::</span><span style="color: #004000;">camelize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$column</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPhpName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> ?<span style="color: #009900;">&#93;</span><span style="color: #339933;">&lt;/</span>td<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    <span style="color: #339933;">&lt;/</span>tr<span style="color: #339933;">&gt;</span>
    <span style="color: #009900;">&#91;</span>?php <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> ?<span style="color: #009900;">&#93;</span>
  <span style="color: #339933;">&lt;/</span>tbody<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;/</span>table<span style="color: #339933;">&gt;</span>
&nbsp;
<span style="color: #009900;">&#91;</span>?php include_partial<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'shared/pager'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'pager'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$pager</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'route'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'&lt;?php echo (isset($this-&gt;params['</span>route_prefix<span style="color: #0000ff;">']) &amp;&amp; $this-&gt;params['</span>route_prefix<span style="color: #0000ff;">']) ? $this-&gt;getUrlForAction('</span>index<span style="color: #0000ff;">') : $this-&gt;getModuleName().'</span><span style="color: #339933;">/</span>index<span style="color: #0000ff;">' ?&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> ?<span style="color: #009900;">&#93;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/isset"><span style="color: #990000;">isset</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'route_prefix'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'route_prefix'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  <span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;[?php echo url_for('&lt;?php echo <span style="color: #006699; font-weight: bold;">$this-&gt;getUrlForAction</span>('new') ?&gt;') ?]&quot;</span><span style="color: #339933;">&gt;</span>New<span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">else</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  <span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;[?php echo url_for('&lt;?php echo <span style="color: #006699; font-weight: bold;">$this-&gt;getModuleName</span>() ?&gt;/new') ?]&quot;</span><span style="color: #339933;">&gt;</span>New<span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>On peut d&#8217;ores et déjà générer le crud pour tester,</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1181code104'); return false;">View Code</a> CONSOLE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1181104"><td class="code" id="p1181code104"><pre class="console" style="font-family:monospace;">./symfony doctrine:generate-module --theme=&quot;myCrudTheme&quot; frontend job JobeetJob</pre></td></tr></table></div>

<p>Et vous voilà libéré de la tâche rébarbative des pagers ! :p</p>
<p>Ca faisait un petit moment que je voulais traiter ce sujet sur le blog, et je comptais continuer en intégrant les formFilter. Malheureusement, je manque de temps pour aller plus loin.<br />
Mais vous avez désormais en votre possession les éléments pour pouvoir faire votre propre thème et l&#8217;enrichir à votre guise.</p>
<p>J&#8217;espére que ca vous aura été utile et si j&#8217;en ai le temps je ferais un prochain post pour voir cette intégration des formFilter <img src='http://www.lexik.fr/blog/symfony/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/BlogSymfony-LexikMontpellier/~4/_CMjGHY4q7Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/qui-leu-crud-ou-comment-creer-un-theme-pour-les-crud-doctrine-de-symfony-1181/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.lexik.fr/blog/symfony/symfony/qui-leu-crud-ou-comment-creer-un-theme-pour-les-crud-doctrine-de-symfony-1181</feedburner:origLink></item>
	</channel>
</rss>

