<?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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>anonymation - blog - développement et architecture web</title>
	
	<link>http://code.anonymation.com</link>
	<description />
	<lastBuildDate>Mon, 19 Dec 2011 09:27:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/anonymation-blog-developpement-architecture-web" /><feedburner:info uri="anonymation-blog-developpement-architecture-web" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Bases: Value Object et Domain Model</title>
		<link>http://feedproxy.google.com/~r/anonymation-blog-developpement-architecture-web/~3/8J-w9mNnfA0/</link>
		<comments>http://code.anonymation.com/architecture/bases-value-object-et-domain-model/#comments</comments>
		<pubDate>Mon, 19 Dec 2011 09:27:39 +0000</pubDate>
		<dc:creator>Benjamin Dulau</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Domain Model]]></category>
		<category><![CDATA[Modèle métier]]></category>
		<category><![CDATA[Value Object]]></category>
		<category><![CDATA[VO]]></category>

		<guid isPermaLink="false">http://code.anonymation.com/?p=300</guid>
		<description><![CDATA[Introduction

Dès que les termes VO ou Value Object ressortent dans une discussion, je constate qu&#8217;une remarque revient presque systématiquement :
&#171;&#160;VO ?&#160;&#187; ou encore &#171;&#160;VO, tu veux dire un DTO c&#8217;est ça ?&#160;&#187;

Ces sujets ont déjà été débattus il y a plus de 15 ans, mais certains développeurs &#171;&#160;neufs&#160;&#187; peuvent parfois ne pas les connaitre (ce qui n&#8217;est pas illogique).
Je voulais donc faire un billet pour rappeler en quelques lignes de quoi il s&#8217;agit.

Notez que très souvent les développeurs utilisent les [...]]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>

<p>Dès que les termes <strong>VO</strong> ou <strong>Value Object</strong> ressortent dans une discussion, je constate qu&#8217;une remarque revient presque systématiquement :
<em>&laquo;&nbsp;VO ?&nbsp;&raquo;</em> ou encore <em>&laquo;&nbsp;VO, tu veux dire un DTO c&#8217;est ça ?&nbsp;&raquo;</em></p>

<p>Ces sujets ont déjà été débattus il y a plus de 15 ans, mais certains développeurs &laquo;&nbsp;neufs&nbsp;&raquo; peuvent parfois ne pas les connaitre (ce qui n&#8217;est pas illogique).
Je voulais donc faire un billet pour rappeler en quelques lignes de quoi il s&#8217;agit.</p>

<p>Notez que très souvent les développeurs utilisent les <strong>Value Objects</strong> mais ne savent tout simplement pas qu&#8217;il y a 15 ou 20 ans, d&#8217;autres personnes leur ont donné un nom <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>

<h2>Qu&#8217;est-ce qu&#8217;un Value Object (VO)</h2>

<p>Si on reprend la définition de Martin Fowler dans P of EAA :</p>

<p>&laquo;&nbsp;<em>A small simple object, like money or a date range, whose equality isn&#8217;t based on identity</em>&nbsp;&raquo;
<a href="http://martinfowler.com/eaaCatalog/valueObject.html" title="">http://martinfowler.com/eaaCatalog/valueObject.html</a></p>

<p>Il n&#8217;y vraiment pas grand chose à ajouter à cette définition !
Un <strong>Value Object</strong> est simplement un objet sans identité, c&#8217;est à dire un objet dont l&#8217;unicité n&#8217;est pas déterminée par un attribut du type &laquo;&nbsp;Id&nbsp;&raquo; (ou autre selon le système de persistance utilisé), mais par simple comparaison de l&#8217;ensemble de ses propriétés.</p>

<p>Concrètement ça signifie également qu&#8217;un <strong>VO</strong> n&#8217;a pas de vie en dehors de l&#8217;objet qui le contient. Il vie et meurt avec cet objet, qui lui, aura sans doute une identité.</p>

<h2>L&#8217;importance des VOs dans le design du Modèle</h2>

<p>En PHP, les <strong>VO</strong>s étaient très peu utilisés jusqu&#8217;à maintenant. Pour la simple raison qu&#8217;ils sont compliqués à stocker et à utiliser avec un système de persistance. Il sera par exemple complexe d&#8217;effectuer des requêtes avec des conditions sur les propriétés d&#8217;un <strong>VO</strong>.</p>

<p>Ceci est en train de changer (je dis bien &laquo;&nbsp;en train&nbsp;&raquo;, il y a encore du chemin à faire) grâce à l&#8217;arrivée d&#8217;ORMs qui laissent de plus en plus de libertés aux développeurs dans leur design objet.</p>

<p>Et c&#8217;est une grande nouvelle, car les <strong>VO</strong>s représentent vraiment un outil essentiel pour designer un modèle solide et consistent.</p>

<h2>La preuve par l&#8217;exemple</h2>

<p>J&#8217;espère vous le prouvez à travers un exemple très simple (et réaliste) : &laquo;&nbsp;Un bout de système de réservation de véhicules de location&nbsp;&raquo; (un bout simplifié :p)</p>

<h3>Le sujet</h3>

<p>Le système propose aux utilisateurs de louer des véhicules sur une période donnée, et en tenant compte des demi-journées.
Le prix de la location diminue à partir du 2ème jour.
Le prix de la location inclut une distance en kilomètres, et chaque kilomètre supplémentaire sera facturé.</p>

<h3>Design basique &laquo;&nbsp;à plat&nbsp;&raquo;</h3>

<p>Ceci est le type de design que nous retrouvons le plus fréquemment.</p>

<div class="wp-caption aligncenter" style="width: 310px"><a href="http://code.anonymation.com/wp-content/uploads/2011/12/value_objects_before.png"><img src="http://code.anonymation.com/wp-content/uploads/2011/12/value_objects_before-300x108.png" alt="" title="value_objects_before" width="300" height="108" class="aligncenter size-medium wp-image-302" /></a><p class="wp-caption-text">Avant</p></div>

<h4>Analyse</h4>

<p>En analysant le diagramme, il est facile de comprendre pourquoi je parle de design &laquo;&nbsp;à plat&nbsp;&raquo;. Nous constatons la nature &laquo;&nbsp;inflexible&nbsp;&raquo; des données ici.</p>

<p>Première chose, à partir du moment où un développeur manipule des données monétaires, un objet <em>Money</em> devrait systématiquement faire partie du design. Je ne comprend d&#8217;ailleurs pas pourquoi ce type d&#8217;objet ne fait pas partie intégrante de tous les langages.</p>

<p>Manipuler une donnée monétaire n&#8217;est pas simplement manipuler un type double. Il s&#8217;agit de gérer des arrondis, une devise, et éventuellement des opérations de conversions.</p>

<p>Que se passe-t&#8217;il si des doubles se baladent un peu partout dans le code et que le développeur n&#8217;applique pas les mêmes règles d&#8217;arrondi dans tous les calculs ?
Et que se passera-t&#8217;il le jour où il est nécessaire de proposer le service dans une autre devise ?</p>

<p>Je pense que vous avez deviné&#8230;</p>

<p>En partant de ce principe, nous pouvons extrapoler ces idées aux autres composants du design.</p>

<p>Par exemple, notre métier possède ici des règles particulières sur les dates de réservation. Il ne s&#8217;agit pas simplement d&#8217;une date de départ et d&#8217;une date d&#8217;arrivée.
Il existe une règle concernant les demi-journées. Cette règle a une influence directe sur le prix de la réservation. Quelle sera la règle pour borner une demi-journée ? Pour borner un ensemble de dates (début et fin) ?</p>

<p>Le design actuel ne laisse entrevoir aucune de ses règles. Comment seront-elles appliquées alors ? Et bien je vous donne la réponse, même si vous la connaissez, un peu partout dans le code, dedans et en dehors de l&#8217;objet <em>Booking</em>, dès lors qu&#8217;une date de réservation devra être manipulée.</p>

<p>Ceci aura pour incidence d&#8217;éparpiller les règles métier, et si ces dernières changent, le système peut facilement devenir défectueux.</p>

<p>De même pour les prix, le prix d&#8217;une réservation n&#8217;est pas seulement déterminé par un double, factoriser la règle de calcul du prix dans un objet peut s&#8217;avérer également payant dans l&#8217;avenir.</p>

<p>Pas besoin d&#8217;aller plus loin, je pense qu&#8217;à ce stade vous avez compris où je veux en venir.</p>

<h3>Design &laquo;&nbsp;riche&nbsp;&raquo; (factorisation et VOs)</h3>

<p>Voici maintenant le design que je vous propose pour remplacer le précédent:</p>

<div class="wp-caption aligncenter" style="width: 310px"><a href="http://code.anonymation.com/wp-content/uploads/2011/12/value_objects-after.png"><img src="http://code.anonymation.com/wp-content/uploads/2011/12/value_objects-after-300x108.png" alt="" title="value_objects-after" width="300" height="108" class="aligncenter size-medium wp-image-317" /></a><p class="wp-caption-text">Après</p></div>

<p>Le diagramme parle de lui même. Dès qu&#8217;une valeur monétaire entre en jeu un type <em>Money</em> sera retourné.
Lors du calcul du prix d&#8217;une annonce, l&#8217;objet <em>Booking</em> délègue le boulot à l&#8217;objet <em>Rental</em> qui lui même le délègue à l&#8217;objet <em>PricePack</em>.
Les quelques notes vous montrent de quelle manière les différentes règles métier liées aux prix ou aux dates peuvent être implémentées. Si elles changent, un seul objet à modifier et le système fonctionne.</p>

<p>Le design pourrait sans doute être encore amélioré, mais peu importe, le principe est là <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>

<h2>Les VOs ne sont pas des DTOs</h2>

<p>Je terminerai avec quelque chose d&#8217;<strong>important</strong> à savoir et qui clarifiera sans doute les choses pour certains:</p>

<p><strong>NON UN VO ET UN DTO CE N&#8217;EST PAS LA MÊME CHOSE !</strong></p>

<p>Un <strong>DTO</strong> (Data Transfer Object) a un rôle bien précis dans l&#8217;application. Il s&#8217;agit d&#8217;un objet transportant le maximum d&#8217;informations pour diminuer le nombre de requêtes et d&#8217;appels de méthodes. Le but est de transférer le plus de données possible en une seule fois.</p>

<p>Je dirais presque (j&#8217;ai dit presque) qu&#8217;un <strong>DTO</strong> est l&#8217;inverse d&#8217;un <strong>VO</strong>. Un <strong>DTO</strong> est un objet qui tente d&#8217;aplatir au maximum les données, l&#8217;exemple très simple de Martin Fowler illustre très bien ce principe: <a href="http://martinfowler.com/eaaCatalog/dataTransferObject.html" title="">http://martinfowler.com/eaaCatalog/dataTransferObject.html</a></p>

<p>Alors qu&#8217;un <strong>VO</strong>, au contraire, va servir à enrichir un design par composition.</p>

<p>Ceci étant dit, merci d&#8217;avoir lu cet article, j&#8217;espère qu&#8217;il vous aura apporté quelque chose !</p>
<div class="shr-publisher-300"></div><img src="http://feeds.feedburner.com/~r/anonymation-blog-developpement-architecture-web/~4/8J-w9mNnfA0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code.anonymation.com/architecture/bases-value-object-et-domain-model/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code.anonymation.com/architecture/bases-value-object-et-domain-model/</feedburner:origLink></item>
		<item>
		<title>Bases: retour aux sources de la programmation objet</title>
		<link>http://feedproxy.google.com/~r/anonymation-blog-developpement-architecture-web/~3/0KGsb72sr-A/</link>
		<comments>http://code.anonymation.com/architecture/bases-retour-aux-sources-de-la-programmation-objet/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 09:13:32 +0000</pubDate>
		<dc:creator>Benjamin Dulau</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[POO]]></category>
		<category><![CDATA[programmation objet]]></category>

		<guid isPermaLink="false">http://code.anonymation.com/?p=275</guid>
		<description><![CDATA[Me revoilà, après quelques mois la tête sous l&#8217;eau (ce qui est plutôt une bonne nouvelle), et j&#8217;ai des choses à dire !

J&#8217;aurais une bonne palette de billets à faire sur Symfony 2, ou encore un avis à donner sur l&#8217;arrivée de Zend Framework 2, mais cette nouvelle génération de frameworks et les conversations que j&#8217;ai avec d&#8217;autres développeurs me donnent plutôt envie de parler du fond et non de la forme.

Le fond, c&#8217;est à dire les bases d&#8217;une architecture [...]]]></description>
			<content:encoded><![CDATA[<p>Me revoilà, après quelques mois la tête sous l&#8217;eau (ce qui est plutôt une bonne nouvelle), et j&#8217;ai des choses à dire !</p>

<p>J&#8217;aurais une bonne palette de billets à faire sur Symfony 2, ou encore un avis à donner sur l&#8217;arrivée de Zend Framework 2, mais cette nouvelle génération de frameworks et les conversations que j&#8217;ai avec d&#8217;autres développeurs me donnent plutôt envie de parler du fond et non de la forme.</p>

<p>Le fond, c&#8217;est à dire les bases d&#8217;une architecture objet.</p>

<p>Après plusieurs discussions avec toutes sortes de développeurs, débutants ou expérimentés, je fais le constat que durant ces quelques dernières années, les frameworks PHP ont eu un double effet sur les développeurs. Le premier positif, l&#8217;autre plutôt négatif.</p>

<h2>Le bon côté de la force</h2>

<p>Ce qui est indéniable avec des frameworks tels que Zend Framework ou Symfony (pour ne citer que ces deux là), c&#8217;est qu&#8217;ils ont réussi à professionnaliser le développement PHP et à redorer le blason du langage.</p>

<p>PHP a souffert d&#8217;une mauvaise réputation, et ce pendant longtemps. Et pour cause, ça a toujours été un langage très simple et très permissif. A tel point que beaucoup de &laquo;&nbsp;bidouilleurs&nbsp;&raquo; ont pu s&#8217;auto-proclamer &laquo;&nbsp;développeurs&nbsp;&raquo;.</p>

<p>Depuis, le langage a beaucoup évolué et sa place dans le monde professionnel et dans la programmation orientée objet est largement méritée. Cette propulsion du langage dans l&#8217;entreprise est due aux évolutions du langage lui-même mais aussi en grande partie à l&#8217;arrivée de frameworks aboutis revendiquant les bonnes pratiques.</p>

<p>Les développeurs qui ont adopté de tels outils ce sont vus peu à peu, avec ou sans difficultés, ingérer des concepts de programmation objet, parfois avancés, et ce sont habitués avec plus ou moins de compréhension à une certaine gymnastique de développement web.</p>

<p>Si ce phénomène est sans conteste une très bonne chose, il vient aussi avec son lot de &laquo;&nbsp;nouvelles mauvaises pratiques&nbsp;&raquo;.</p>

<h2>Le côté obscur de la force</h2>

<p>Il existe donc un mauvais côté à cette élévation intellectuelle du langage, et je pense ne pas être le seul à le constater.</p>

<p>Beaucoup de développeurs se voient ainsi manipuler des concepts objets avancés, et ce parfois sans connaitre le pourquoi du comment. Pourtant, ces concepts existent depuis bien longtemps, les connaitre et les comprendre fait normalement partie de l&#8217;éducation d&#8217;un développeur objet.</p>

<p>Mais c&#8217;est là tout l&#8217;art du cerveau humain, c&#8217;est d&#8217;être capable de produire quelque chose par simple mimétisme jusqu&#8217;à ce que ça devienne machinal.</p>

<p>Ces frameworks ont donc habitué les développeurs à appliquer de bonnes pratiques, mais en imposant tellement de règles et une telle application concrète prête à l&#8217;emploi, que pas mal d&#8217;étapes ont été brûlées au passage.</p>

<p>On peut comparer ça à un chirurgien qu&#8217;on aurait tellement habitué à pratiquer une opération complexe, qu&#8217;il l&#8217;a maîtriserait, mais ne serait pas capable d&#8217;opérer une simple appendicite.</p>

<h2>Conséquences</h2>

<p>Les conséquences de ce phénomène sont simples. Aujourd&#8217;hui les frameworks sont devenus si complexes, magiques ou trop peu performants, qu&#8217;ils doivent être repensés et développés pour mieux coller aux standards et aux concepts de base.</p>

<p>Et devinez qui en pâtit ?</p>

<p>Les développeurs ont tellement été habitués que maintenant qu&#8217;on leur demande de comprendre ce qu&#8217;on leur a fait faire sans réfléchir ces dernières années, ils sont perdus. Et cette nouvelle vague de frameworks, qui sont censés être plus simples et plus universels, semblent au contraire bien plus complexes à leurs yeux.</p>

<p>Evidemment c&#8217;est un faux semblant !</p>

<h2>Retour aux sources</h2>

<p>C&#8217;est vrai que je donne une note un peu dramatique à tout ça.
En fait, je pense que c&#8217;est vraiment une bonne chose, et ce que je vois c&#8217;est que les développeurs qui prennent conscience de tout ça donnent une nouvelle dimension à leur métier, et se découvrent de nouvelles passions.</p>

<p>Je n&#8217;ai jamais vu autant de développeurs PHP acheter des livres sur les design patterns que ces derniers temps. Hallelujah ! Je dis enfin, car la plupart de ces concepts existent depuis les années 1990 :p</p>

<p>Quoi qu&#8217;il en soit, cette nouvelle génération de frameworks est excitante et ça me motive à écrire des billets sur les bases de la programmation objet ! Ce billet fera d&#8217;ailleurs figure d&#8217;introduction.</p>

<h2>Addendum</h2>

<p>J&#8217;aimerais préciser que je fais évidemment une généralisation concernant les développeurs. Tous ne sont pas concernés par ce que j&#8217;écris et certains ont acquis tous ces concepts depuis bien longtemps. Ce n&#8217;est donc pas à prendre pour argent comptant, chacun y verra son compte et se reconnaîtra ou non <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<div class="shr-publisher-275"></div><img src="http://feeds.feedburner.com/~r/anonymation-blog-developpement-architecture-web/~4/0KGsb72sr-A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code.anonymation.com/architecture/bases-retour-aux-sources-de-la-programmation-objet/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://code.anonymation.com/architecture/bases-retour-aux-sources-de-la-programmation-objet/</feedburner:origLink></item>
		<item>
		<title>Le MVC dans Symfony 2: cheminement d’une requête HTTP</title>
		<link>http://feedproxy.google.com/~r/anonymation-blog-developpement-architecture-web/~3/PRJB9nSS2pY/</link>
		<comments>http://code.anonymation.com/symfony-2/le-mvc-dans-symfony-2-cheminement-dune-requete-http/#comments</comments>
		<pubDate>Fri, 25 Feb 2011 17:45:42 +0000</pubDate>
		<dc:creator>Benjamin Dulau</dc:creator>
				<category><![CDATA[Symfony 2]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[requête http]]></category>
		<category><![CDATA[symfony 2]]></category>

		<guid isPermaLink="false">http://code.anonymation.com/?p=257</guid>
		<description><![CDATA[L&#8217;activité autour de Symfony 2 est très importante depuis quelques mois. Certaines décisions concernant l&#8217;architecture du framework et de ses composants devaient être prises avant la phase de stabilisation pour éviter de traîner des casseroles dans les belles années à venir pour l&#8217;outil.

Heureusement, je pense pouvoir dire sans trop me tromper que le framework est entré dans une véritable phase de stabilisation et que la core team et les contributeurs travaillent d&#8217;arrache pied pour l&#8217;arrivée du Symfony Live 2011 à [...]]]></description>
			<content:encoded><![CDATA[<p>L&#8217;activité autour de Symfony 2 est très importante depuis quelques mois. Certaines décisions concernant l&#8217;architecture du framework et de ses composants devaient être prises avant la phase de stabilisation pour éviter de traîner des casseroles dans les belles années à venir pour l&#8217;outil.</p>

<p>Heureusement, je pense pouvoir dire sans trop me tromper que le framework est entré dans une véritable phase de stabilisation et que la core team et les contributeurs travaillent d&#8217;arrache pied pour l&#8217;arrivée du Symfony Live 2011 à Paris.</p>

<p>Ce qui me permet de démarrer une série d&#8217;articles sur Symfony 2, dont la première partie concernera le MVC tel qu&#8217;il est introduit dans le framework.</p>

<h2>Introduction</h2>

<p>Une introduction logique pour analyser l&#8217;implémentation du MVC et de suivre le parcours d&#8217;une requête HTTP.</p>

<p>Un gros travail de <a href="http://docs.symfony-reloaded.org/master/index.html" title="">documentation sur le framework</a> est en cours et je vous invite vivement à lire les différents guides, regroupés maintenant dans une section intitulée « <strong>Book</strong> », et deviennent donc des chapitres, qui plus qu&#8217;une simple documentation de référence, expliquent de façon simple et accessible (si vous maîtrisez l&#8217;anglais bien entendu) les différents concepts derrière la philosophie et les composants et/ou bundles de Symfony 2. Il y a une continuité dans les sujets, c&#8217;est très appréciable pour de la doc. <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p>Concernant notre requête HTTP, si ce n&#8217;est pas déjà fait, je vous recommande avant de continuer, de lire ce chapitre : <a href="http://docs.symfony-reloaded.org/master/book/http_fundamentals.html" title="">The HTTP Spec and Symfony2 Fundamentals</a>, qui est d&#8217;ailleurs le premier chapitre, c&#8217;est bien, jusque là nous restons logiques !</p>

<h2>Cheminement d&#8217;une requête HTTP : diagramme</h2>

<p>Le chapitre pré-cité étant très bien écrit, je n&#8217;ai rien à y ajouter, d&#8217;autant plus que ça ne serait pas mieux raconté que part un développeur concerné.</p>

<p>Je vous propose par contre de découvrir le cheminement d&#8217;une requête HTTP dans Symfony 2 sous forme de diagramme, plus ou moins un Workflow. Sachant que je n&#8217;ai pas respecté de règles particulières pour faire cette représentation, et que je ne peux malheureusement pas tout détailler. Mais si vous êtes comme moi, et que vous aimez avoir un schéma sous la main, servez-vous.</p>

<div id="attachment_266" class="wp-caption aligncenter" style="width: 310px"><a href="http://code.anonymation.com/wp-content/uploads/2011/02/sf2-http-request-journey1.jpg" target="_blank"><img src="http://code.anonymation.com/wp-content/uploads/2011/02/sf2-http-request-journey1-300x288.jpg" alt="" title="Symfony 2 - HTTP Request Journey" width="300" height="288" class="size-medium wp-image-266" /></a><p class="wp-caption-text">Symfony 2 - Cheminement d'une requête HTTP</p></div>

<h2>Un framework « agnostic »</h2>

<p>Pour apporter un peu de précisions sur le diagramme, j&#8217;attire votre attention sur la forme agnostic du coeur du framework. Une implémentation du MVC est proposée, mais vous constatez qu&#8217;elle est totalement indépendante de la gestion de la requête HTTP, et pourrait être très facilement remplacée.</p>

<p>Comme l&#8217;explique très bien la documentation, le coeur du framework propose simplement une série d&#8217;objets permettant de manipuler facilement une requête et une réponse HTTP (HttpFoundation).</p>

<p>Autour de ces composants, les opérations sont orchestrées par le gestionnaire d&#8217;événements (Event Dispatcher), qui va notifier à ceux qui écoutent ces événements (listeners) que c&#8217;est le moment d&#8217;intervenir. Ils vont donc altérer tour à tour l&#8217;objet de réponse (Response).</p>

<p>Grâce au conteneur de dépendances, il apparait très clairement que nous pouvons détacher n&#8217;importe qu&#8217;elle partie, pour la remplacer par une autre. D&#8217;ailleurs à ce sujet, vous constatez que je met en avant des implémentations concrètes de certaines briques, notamment le routage et la résolution du contrôleur et de ses paramètres. Sachez que le coeur du framework ne propose la plupart du temps que des interfaces, voir des implémentations très génériques, et que les implémentations ne font pas partie des composants du core, mais sont dans le bundle FrameworkBundle. Je cite celles-ci car c&#8217;est le fonctionnement par défaut, et celui que la plupart d&#8217;entre vous devrait adopter.</p>

<p>Mais il serait donc très simple de ne conserver que le coeur du système, et de créer votre propre framework MVC. Pour ça, il « suffit » d&#8217;implémenter les différentes interfaces (contrats), et de connecter des listeners sur les différents événements clés.</p>

<p>Note : il serait également possible de remplacer le HttpKernel par votre propre version, à condition de respecter certaines règles, même si, comme ça, je ne vois aucun intérêt particulier à faire ça.</p>

<h2>Evénement core.view</h2>

<p>Certains se poseront peut-être la question de l&#8217;utilité de l&#8217;événement &laquo;&nbsp;core.view&nbsp;&raquo;, qui est dispatché si un contrôleur n&#8217;a pas retourné d&#8217;objet de type HttpFoundation\Response.</p>

<p>Dans Symfony 2, la création de l&#8217;objet de réponse est explicite, c&#8217;est au contrôleur de le créer, de le nourrir avec ce qu&#8217;il veut, par exemple le résultat du rendu d&#8217;une vue/template, et de le retourner.</p>

<p>J&#8217;espère ne pas me tromper en disant ça, mais certains contributeurs se sont plains de ne pas avoir une véritable couche « Vue », et j&#8217;oserais croire que cet événement permettrait à qui veut, de créer sa propre couche présentation, du moment qu&#8217;un objet réponse est fournit en retour. Si quelqu&#8217;un veut préciser ce point, il est le bienvenu <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<h2>Addendum</h2>

<p>Je précise que ce diagramme n&#8217;est pas du tout officiel, et que je ne suis pas à l&#8217;abri d&#8217;une erreur. C&#8217;est une première version, je ne doute pas qu&#8217;elle sera améliorée.
Tous vos retours seront très appréciés.</p>

<p>J&#8217;ai décidé volontairement de détailler certaines parties du Worflow et d&#8217;autres non, pour ces dernières, il faudra fouiller le code <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<div class="shr-publisher-257"></div><img src="http://feeds.feedburner.com/~r/anonymation-blog-developpement-architecture-web/~4/PRJB9nSS2pY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code.anonymation.com/symfony-2/le-mvc-dans-symfony-2-cheminement-dune-requete-http/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://code.anonymation.com/symfony-2/le-mvc-dans-symfony-2-cheminement-dune-requete-http/</feedburner:origLink></item>
		<item>
		<title>Introduction à Symfony 2</title>
		<link>http://feedproxy.google.com/~r/anonymation-blog-developpement-architecture-web/~3/7ylGjRRpxRI/</link>
		<comments>http://code.anonymation.com/symfony-2/introduction-a-symfony-2/#comments</comments>
		<pubDate>Tue, 04 Jan 2011 14:37:19 +0000</pubDate>
		<dc:creator>Benjamin Dulau</dc:creator>
				<category><![CDATA[Symfony 2]]></category>
		<category><![CDATA[symfony 2]]></category>

		<guid isPermaLink="false">http://code.anonymation.com/?p=209</guid>
		<description><![CDATA[Résumé de la situation

Comme vous le savez, je suis un gros consommateur de Zend Framework, il y a une explication à celà. Lorsque je me suis décidé à adopter un framework PHP, mes choix s&#8217;étaient réduits à deux prétendants, Zend Framework et symfony. Alors pourquoi j&#8217;ai choisi ZF ? La réponse est très simple, pour sa flexibilité.

Bien que symfony premier du nom soit un très bon framework, il souffre malheureusement d&#8217;une rigidité trop importante. Pour résumer grossièrement, je dirais qu&#8217;avec [...]]]></description>
			<content:encoded><![CDATA[<h2>Résumé de la situation</h2>

<p>Comme vous le savez, je suis un gros consommateur de Zend Framework, il y a une explication à celà. Lorsque je me suis décidé à adopter un framework PHP, mes choix s&#8217;étaient réduits à deux prétendants, Zend Framework et symfony. Alors pourquoi j&#8217;ai choisi ZF ? La réponse est très simple, pour sa flexibilité.</p>

<p>Bien que symfony premier du nom soit un très bon framework, il souffre malheureusement d&#8217;une rigidité trop importante. Pour résumer grossièrement, je dirais qu&#8217;avec symfony, soit on fait tout avec le framework, soit on ne fait rien (ce qui n&#8217;est pas nécessairement une mauvaise chose). J&#8217;avais besoin d&#8217;un framework qui me laisse la liberté d&#8217;implémenter tout ce que je peux imaginer. D&#8217;autant plus qu&#8217;à ce moment là, les frameworks PHP étaient loin de proposer tout l&#8217;arsenal nécessaire, et il était évident que j&#8217;allais avoir une surcouche de code importante.</p>

<p>Ensuite, je crois que la force de Zend a été de mener une campagne de communication plutôt efficace, et j&#8217;avoue avoir été séduit.</p>

<p>Mais ce n&#8217;est pas pour autant que je m&#8217;enferme dans un outil sans me soucier de ce qui se passe autour.
Je surveille de très près l&#8217;évolution de PHP et son éco-système. J&#8217;essaie autant que possible d&#8217;effectuer une veille régulière et j&#8217;ai toujours quelques expérimentations en cours <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p>Au delà de ça, je me nourris de tous les concepts qui gravitent autour du développement web, qu&#8217;ils viennent de frameworks JAVA, .NET, Ruby ou autre et m&#8217;en inspire beaucoup pour nos développements autour de Zend Framework.</p>

<p>Mais voilà qu&#8217;est annoncé Symfony 2, depuis maintenant une dizaine de mois (ça passe vite !), et quelle était ma surprise quand j&#8217;ai vu que tout ce que j&#8217;attendais (ou presque) d&#8217;un framework PHP abouti était sur le point d&#8217;être intégré dans Symfony 2.</p>

<p>Entre promesses et réalité, où en est-on aujourd&#8217;hui et pourquoi Symfony 2 est-il si prometteur ?
Je vais tenter de répondre à cette question dans ce billet qui fera office d&#8217;introduction à ce <em>nouveau</em> framework.</p>

<h2>On casse tout et on recommence</h2>

<p>Je suis persuadé que la meilleure initiative a été de tout remettre en question.</p>

<p>Pour proposer un framework flexible, il faut que son cœur soit lui même flexible et conçu dans cette optique. Il doit être léger, simple et suffisamment intelligent pour permettre aux développeurs de laisser aller leur imagination et ne pas se retrouver bloqués par une trop grande rigidité du framework. Il n&#8217;y a rien de plus frustrant qu&#8217;avoir des idées mais ne pas pouvoir les mettre en œuvre correctement.</p>

<p>Avec Symfony 2, Fabien Potencier a pris le parti de tuer la magie (&laquo;&nbsp;kill the magic&nbsp;&raquo;) et d&#8217;emprunter et utiliser moins de concepts mais de manière plus efficace. Tout a été repensé et ré-écrit &laquo;&nbsp;from scratch&nbsp;&raquo;.</p>

<p>Une nouvelle orientation était aussi de vouloir transformer un objet requête en un objet réponse (qui j&#8217;entends dire &laquo;&nbsp;Ha ben oui, c&#8217;est logique en fait !&nbsp;&raquo; ?).</p>

<p>Je ne pourrai malheureusement pas faire l&#8217;analogie avec symfony 1 car je ne le connais pas assez, mais ce n&#8217;est pas très grave étant donné que Symfony 2 n&#8217;a plus rien à voir, sauf dans sa philosophie (Fabien).</p>

<h2>Pourquoi Symfony 2 est-t-il flexible ?</h2>

<p>Je ne vais pas détailler tous les composants du framework mais plutôt me concentrer sur les trois grandes composantes de l&#8217;architecture de Symfony 2 qui en font un noyau simple et flexible.</p>

<h3>Injection de dépendances</h3>

<p>De tous les concepts utilisés en programmation, celui qui me manquait le plus dans les frameworks PHP était l&#8217;<a href="http://fr.wikipedia.org/wiki/Inversion_de_contr%C3%B4le" title="">inversion de contrôle</a> (IOC) ou dans sa forme spécifique l&#8217;injection de dépendances. Pour pallier à ce manque j&#8217;ai écrit un <a href="http://code.anonymation.com/zend-framework/ioc-ou-injection-de-dependances-zend-application/" title="">conteneur très léger de dépendances pour Zend Framework</a> (incomplet) en espérant voir arriver un jour un conteneur abouti au sein des frameworks.</p>

<p>Mon souhait se réalise puisque Symfony 2 repose entièrement sur un conteneur de dépendances léger, puissant et simple à utiliser. Ce composant indépendant, de Sensio, existait déjà mais les frameworks n&#8217;étaient pas étudiés pour ce type de pratique. L&#8217;utilisation du conteneur n&#8217;avait alors qu&#8217;un intérêt limité. Dans Zend Framework 1, le coeur du système ne permet par exemple pas d&#8217;injecter certaines dépendances qui sont fortement liées. Ou encore l&#8217;utilisation abusive du pattern Singleton et l&#8217;accès statique à certains objets sont une contrainte limitant fortement la flexibilité du framework.</p>

<p>Dans Symfony 2 le conteneur de dépendances est utilisé dans le coeur du framework et tout est pensé pour un découplage total des composants. Ceci apporte en plus d&#8217;autres avantages, tout est par exemple plus explicite, il est très facile de connaitre les dépendances d&#8217;un composant en jetant un oeil à la configuration du conteneur.</p>

<p>Pour parler du conteneur lui même, baptisé tout simplement &laquo;&nbsp;Dependency Injection&nbsp;&raquo;, il est très simple à utiliser et permet tout type d&#8217;injection (par mutateur, par constructeur, etc.). Je ne rentre pas dans le détail dans ce billet et vous laisse consulter le <a href="http://components.symfony-project.org/dependency-injection/" title="Symfony Dependency Injection - Reinventing how you manage PHP classes">site officiel du composant</a> pour vous familiariser avec son utilisation.</p>

<p>Je citerai juste au passage la possibilité de &laquo;&nbsp;dumper&nbsp;&raquo; le conteneur et la liberté d&#8217;implémenter son propre driver de configuration (loader). Le premier point est très apprécié et permet de visualiser facilement le graph des dépendances des objets, ce qui facilite vraiment le débuggage <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<h3>Le système de Bundle</h3>

<p>Le succès de symfony 1 est en partie dû à sa communauté et notamment à la possibilité de partager des plugins. Il était logique que Symfony 2 conserve cet aspect. Mais la réflexion a été poussée et les petits gars de chez Sensio nous servent un système qui fait preuve d&#8217;une très grande flexibilité.</p>

<p>Derrière le nom &laquo;&nbsp;Bundle&nbsp;&raquo; qui peut être assez déroutant se cache un système modulaire très bien maîtrisé. Une fois le terme accepté (je suis peut-être fou mais j&#8217;ai eu du mal), c&#8217;est un régal pour le développement.</p>

<p>La <a href="http://docs.symfony-reloaded.org/?page=learn" title="">documentation officielle</a> assimile un bundle à un plugin, non pas un module, et à raison. En effet, un bundle dans Symfony 2 est totalement indépendant, mais est surtout très facile à intégrer au sein de l&#8217;application. Il suffit de coller le dossier du bundle dans l&#8217;application, d&#8217;ajouter sa configuration à l&#8217;environnement et ça roule tout seul.</p>

<p>Mais toute la puissance de la solution vient du fait que dans Symfony 2 tout est bundle, même les fonctionnalités du cœur sont réunies dans plusieurs bundles dont le chargement est explicite. Tout est donc modulable !</p>

<p>Ce point pourra d&#8217;ailleurs perturber certains d&#8217;entre vous car même la couche web est un bundle. Et c&#8217;est là que nous faisons la différence entre un module, un plugin et un bundle et que l&#8217;arrivée d&#8217;un nouveau terme prend du sens.</p>

<p>Pour ce qui est du partage, le coup est déjà prévu puisqu&#8217;une pré-version du site <a href="http://symfony2bundles.org/" title="Symfony2 Bundles">http://symfony2bundles.org/</a> est disponible et permet déjà de trouver quelques bundles intéressants. Le site renforce l&#8217;aspect collaboratif puisqu&#8217;il est en intéraction direct avec github et facilite la participation au développement d&#8217;un projet ou d&#8217;un bundle.</p>

<p>A noter que le site est réalisé à l&#8217;aide de Symfony 2 et Doctrine 2 et qu&#8217;une API est déjà disponible pour accéder aux données des bundles et de leurs développeurs. Une bonne vitrine donc <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<h3>Le dispatcheur d&#8217;événements (Event Dispatcher)</h3>

<p>Troisième atout dans l&#8217;architecture de Symfony 2, une implémentation nouvelle du <a href="http://fr.wikipedia.org/wiki/Observateur_(patron_de_conception)" title="">pattern Observer</a> pour le composant Event Dispatcher.</p>

<p>Un des problèmes les plus difficiles à résoudre en programmation lorsque plusieurs développeurs travaillent en parallèle sur différentes fonctionnalités d&#8217;un système est de permettre l’intéraction des différents composants sans avoir à les modifier pour qu&#8217;ils puissent fonctionner ensemble. Plus difficile encore, un plugin peut intervenir à différents moments de l’exécution d&#8217;une application.</p>

<p>Imaginez par exemple que vous souhaitez modifier l&#8217;objet requête avant que votre action de contrôleur soit exécutée. Ceci doit être réalisable sans avoir à mettre la main dans le code du contrôleur. D&#8217;autant plus que ce code aura peut-être été écrit par un autre développeur.</p>

<p>Le <a href="http://fr.wikipedia.org/wiki/Observateur_(patron_de_conception)" title="">pattern Observer</a> permet de résoudre ce problème, et Symfony 2 nous propose une implémentation simple et efficace. Une classe Event permet de créer des événements identifiés par une chaine de caractères unique et de lui assigner des attributs eux aussi identifiés par une chaine. Il sera donc inutile dans la plupart des cas de créer une classe spécifique pour vos événements.</p>

<p>Pour connecter un &laquo;&nbsp;listener&nbsp;&raquo; à l&#8217;événement c&#8217;est trivial, il suffit de créer une instance du dispatcher et d&#8217;utiliser une méthode connect qui prend en paramètre le nom de l&#8217;événement, une méthode de callback à exécuter au moment de la notification et un ordre de priorité.</p>

<p>Il existe trois manières de notifier l&#8217;événement, que je ne détaillerai pas ici, mais si nous reprenons l&#8217;exemple du contrôleur et de l&#8217;objet requête, lors de la construction de l&#8217;objet réponse à partir de l&#8217;objet requête, le cœur du framework utilise la méthode de notification <em><strong>filter()</strong></em> qui demande à tous les &laquo;&nbsp;listeners&nbsp;&raquo; connectés à l&#8217;événement de filtrer la valeur donnée (ici un objet Request) et de la retourner (filtrée). Très facile donc d&#8217;altérer l&#8217;état de l&#8217;objet avant de le récupérer dans notre action de contrôleur. Et ceci en toute transparence.</p>

<p>Symfony 2 nous permet donc de créer très facilement des &laquo;&nbsp;<a href="http://fr.wikipedia.org/wiki/Hook_(informatique)" title="">Hooks</a>&nbsp;&raquo; (le terme est peut-être plus parlant pour certains d&#8217;entre vous) et le framework permet déjà d&#8217;intervenir à certains moments clés de l&#8217;exécution de la requête.</p>

<p>Vous me direz que ceci n&#8217;est pas nouveau, Zend Framework 1 permet par exemple de créer des plugins de contrôleur ou des aides d&#8217;action, mais ceci reste très spécifique. Un dispatcheur générique tel que dans Symfony 2 permet une ouverture plus grande puisqu&#8217;il pourra être utilisé par n&#8217;importe quel objet et à tout moment, selon vos besoins.</p>

<h3>Autres éléments intéressants</h3>

<p>Je me concentre sur les trois éléments clés de l&#8217;architecture du framework mais il en existe quelques autres intéressants et renforçant encore la flexibilité.</p>

<ul>
<li>la structure du projet (dossiers) : la structure proposée offre une meilleure séparation des différents éléments de l&#8217;application, la configuration, la couche web (MVC) et les différents plugins (bundles) fonctionnels.</li>
<li>le chargement automatique des classes : un seul fichier php utilisant une classe <em>UniversalClassLoader</em> permet de configurer de manière explicite tous les espaces de noms ou les préfixes (PEAR) des différentes sources tiers.</li>
<li>une classe de bootstrap (AppKernel) unifiée : encore une fois la classe de bootstrap de l&#8217;application permet de charger explicitement les différents bundles et la configuration de l&#8217;environnement.</li>
</ul>

<p>Le mot qui revient souvent est &laquo;&nbsp;explicite&nbsp;&raquo;, et ce n&#8217;est pas pour rien. Tout est limpide, et il faut mettre les doigts dans le code pour configurer certaines parties du système (&laquo;&nbsp;convention over configuration&nbsp;&raquo;), ce qui permet d&#8217;avoir au passage une vue d&#8217;ensemble de ce qui est exécuté au moment de l&#8217;initialisation de l&#8217;application.</p>

<h2>Et les performances ?</h2>

<p>Encore une fois c&#8217;est une surprise. Symfony 2 est rapide, je dirai même très rapide.</p>

<h3>&laquo;&nbsp;Kill the magic&nbsp;&raquo;</h3>

<p>Je citais en début d&#8217;article le leitmotiv &laquo;&nbsp;kill the magic&nbsp;&raquo;. Dans les premières versions de Zend Framework et symfony, il y avait beaucoup de &laquo;&nbsp;magie&nbsp;&raquo;. C&#8217;est à dire que beaucoup d&#8217;éléments étaient accessibles de manière obscure pour économiser du code et limiter le nombre de caractères à saisir par ces paresseux de développeurs (ok je me moque un peu).</p>

<p>Le problème est que la &laquo;&nbsp;magie&nbsp;&raquo; a un coût assez élevé en performances. L&#8217;utilisation abusive des méthodes magiques <em><strong>__call</strong></em>, <em><strong>__get</strong></em>, <em><strong>__set</strong></em>, etc. demande une introspection du code et des fichiers importante, ce qui a impact très négatif non seulement sur les performances mais aussi sur la qualité et la compréhension du code.</p>

<p>Les développeurs de Symfony 2 ont pris le parti de tuer cette magie et de rendre les choses plus explicites et moins obscures pour les utilisateurs du framework. Ceci améliore non seulement les performances de manière significative mais adoucit aussi la courbe d&#8217;apprentissage du framework car tout y est beaucoup plus clair et compréhensible pour les développeurs. D&#8217;une pierre deux coups.</p>

<h3>Utilisation interne du cache</h3>

<p>Symfony 2 utilise beaucoup de cache (fichiers) en interne et notamment pour la configuration.</p>

<p>Lors de l&#8217;exécution de la première requête, certaines classes dépendantes de la configuration sont &laquo;&nbsp;compilées&nbsp;&raquo; (ou plutôt &laquo;&nbsp;empilées&nbsp;&raquo; <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ) en PHP dans le cache. Lors des exécutions suivantes, le cache sera utilisé. Pour vous donner une idée, sur une application de type &laquo;&nbsp;Hello World&nbsp;&raquo;, la première requête prendra 600ms et toutes les suivantes 25ms.</p>

<p>Certains autres composants utilisent abondamment le cache, comme Twig (moteur de templates) ou Doctrine (ORM), et le résultat est indéniable, l&#8217;impact sur les performances est énorme.</p>

<p>C&#8217;est donc un bon point pour Symfony 2 car le développeur n&#8217;aura pas à se soucier de ces problématiques et à intégrer sa propre gestion du cache pour cette partie de l&#8217;application.</p>

<h3>Le conteneur de dépendances</h3>

<p>Je reviens sur ce composant qui a également un impact positif sur les performances.</p>

<p>Grâce au conteneur, les éléments sont chargés à la demande, seulement quand nécessaire (lazy loading). Ceci réduit considérablement le nombre de classes chargées dès l&#8217;initialisation du système. C&#8217;est vrai pour le cœur du framework mais aussi pour vos propres développements.</p>

<h2>Autres atouts</h2>

<p>Je ne peux malheureusement pas trop m&#8217;étaler, cet article est déjà très long.</p>

<p>J&#8217;ajouterai simplement que certaines couches de Symfony 2 sont inspirées de très bons frameworks tels que Spring (JAVA) ou Django (Python) et que certains concepts que nous n&#8217;avions pas encore dans l&#8217;univers PHP font leur apparition.</p>

<p>Je pense notamment à <a href="http://www.twig-project.org/" title="">Twig</a>, le moteur de templates livré avec le framework, qui est très prometteur. J&#8217;ai d&#8217;ailleurs écrit une <a href="http://code.anonymation.com/zend-framework/utiliser-twig-avec-zend-framework-1-1x/" title="">intégration du moteur pour Zend Framework 1</a>, et nous (anonymation) allons migrer la couche présentation de certains de nos projets sur ce système.</p>

<p>Je pense aussi à des composants spécifiques, par exemple le composant &laquo;&nbsp;Form&nbsp;&raquo; pour la gestion des formulaires, qui intègre un data binder pour mapper automatiquement les valeurs d&#8217;un formulaire HTML sur un Objet PHP. Ou encore la couche de sécurité pour l&#8217;authentification et la gestion des droits des utilisateurs qui est nouvelle (en PHP) et puissante. Et j&#8217;en passe&#8230;</p>

<p>Tout est également &laquo;&nbsp;testable&nbsp;&raquo; et l&#8217;intégration des tests unitaires et fonctionnels a été simplifiée et renforcée. Rappelons que la pratique des tests unitaires en PHP est très récente, c&#8217;est donc une bonne chose que les frameworks professionnels encouragent les développeurs vers de telles pratiques en leur proposant des outils adaptés.</p>

<p>Pour finir, Symfony 2 intègre des outils facilitant le développement et qui ont fait le succès de symfony premier du nom. La debug bar, des exceptions travaillées et plus explicites, des logs, et bien sûr une commande CLI très utile.</p>

<h2>Où est l&#8217;anguille ?</h2>

<p>Jusqu&#8217;ici on pourrait croire que j&#8217;ai été soudoyé par Sensio pour vous expliquer combien Symfony 2 est merveilleux. Il n&#8217;en est rien !</p>

<p>Le framework se montre vraiment très prometteur, mais (et oui), j&#8217;ai bien sûr quelques réticences envers certains éléments.</p>

<p>Lorsque j&#8217;ai vu apparaître certains concepts dans Symfony 2, j&#8217;ai sauté de joie, mais malheureusement rien n&#8217;est jamais parfait ou comme on le voudrait.</p>

<p>Je pense par exemple au &laquo;&nbsp;data binder&nbsp;&raquo; dont l&#8217;implémentation est exclusive au composant &laquo;&nbsp;Form&nbsp;&raquo;. J&#8217;aurais aimé voir apparaître un composant dédié à cette tâche qui puisse être utilisable dans d&#8217;autres contextes qu&#8217;un formulaire HTML. J&#8217;ai essayé d&#8217;aborder le sujet sur le groupe de discussion mais sans succès. Je sais ce qu&#8217;il me reste à faire <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p>Autre chose que je n&#8217;aime pas, l&#8217;intégration trop poussée de certaines librairies tiers, comme Doctrine 2 par exemple. C&#8217;était vrai également pour symfony 1. Lorsque des nouvelles versions de ces librairies sont disponibles il faut compter sur la réactivité du développeur du Bundle en question pour bénéficier de l&#8217;intégration des nouvelles fonctionnalités. Mais ce point est discutable car une telle intégration apporte aussi des avantages ; dans le cas de Doctrine, pas besoin de jongler par exemple entre les lignes de commandes de Symfony et de Doctrine, tout peut-être fait par la CLI de Symfony.</p>

<p>Je n&#8217;ai malheureusement pas encore assez de recul pour apporter d&#8217;autres critiques, mais ça ne saurait tarder. Sans compter que le framework est encore en phase de développement et que certaines choses peuvent encore changer d&#8217;ici la première version stable prévue pour Mars 2011.</p>

<h2>Conclusion</h2>

<p>Vous l&#8217;aurez compris, je suis séduit. Sensio nous propose un framework très mature et très bien fichu. Une grosse réflexion a été menée sur le fond et ça se ressent dès les premières utilisations.</p>

<p>Je peux déjà vous dire que chez anonymation nous avons adopté Symfony 2 et nous prévoyons déjà la migration de certains &laquo;&nbsp;gros&nbsp;&raquo; projets sur le framework.</p>

<p>Mais attention, ça ne veut pas dire que j&#8217;abandonne Zend Framework. Certains projets démarrent encore sur ZF et j&#8217;attends avec impatience la refonte du MVC prévue pour Zend Framework 2 dont je suis de près le développement.</p>

<p>Je m&#8217;excuse pour la longueur de cet article, mais je vous promets que je me suis retenu de rentrer dans le détail sur certains points <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> 
Cet article fait office d&#8217;introduction et d&#8217;autres articles plus techniques et spécifiques seront publiés au fur et à mesure de mes aventures.</p>

<p><strong>Edit</strong> : Je me rend compte que je n&#8217;ai pas du tout parlé de PHP 5.3 mais évidemment Symfony 2 tire profit de toutes les nouveautés du langage. Il n&#8217;est d&#8217;ailleurs compatible qu&#8217;avec PHP 5.3.2 et supérieur. Les conventions sont respectées, les espaces de noms propres. Vous verrez même certaines utilisations des closures plutôt ingénieuses. Je tenais à préciser ce point important.</p>
<div class="shr-publisher-209"></div><img src="http://feeds.feedburner.com/~r/anonymation-blog-developpement-architecture-web/~4/7ylGjRRpxRI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code.anonymation.com/symfony-2/introduction-a-symfony-2/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		<feedburner:origLink>http://code.anonymation.com/symfony-2/introduction-a-symfony-2/</feedburner:origLink></item>
		<item>
		<title>Magento, alors, c’est comment ?</title>
		<link>http://feedproxy.google.com/~r/anonymation-blog-developpement-architecture-web/~3/XLXyTrAwb38/</link>
		<comments>http://code.anonymation.com/magento/magento-alors-cest-comment/#comments</comments>
		<pubDate>Thu, 16 Dec 2010 15:33:38 +0000</pubDate>
		<dc:creator>Benjamin Dulau</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[boutique]]></category>
		<category><![CDATA[e-commerce]]></category>
		<category><![CDATA[magento]]></category>

		<guid isPermaLink="false">http://code.anonymation.com/?p=170</guid>
		<description><![CDATA[Par la force des choses, j&#8217;ai été poussé à m&#8217;intéresser profondément à Magento, la solution e-commerce basée sur Zend Framework.

Le constat est très mitigé, après des heures et des heures sur le code, voilà ce que j&#8217;en tire.

Globalement

L&#8217;outil est très inaccessible. Pas de documentation efficace, une grosse communauté mais très peu réactive (aucune réponse sur les forums sur des questions critiques). Des heures et des heures de recherche, le plus souvent dans la source, pour réussir à s&#8217;en sortir en [...]]]></description>
			<content:encoded><![CDATA[<p>Par la force des choses, j&#8217;ai été poussé à m&#8217;intéresser profondément à Magento, la solution e-commerce basée sur Zend Framework.</p>

<p>Le constat est très mitigé, après des heures et des heures sur le code, voilà ce que j&#8217;en tire.</p>

<h2>Globalement</h2>

<p>L&#8217;outil est très inaccessible. Pas de documentation efficace, une grosse communauté mais très peu réactive (aucune réponse sur les forums sur des questions critiques). Des heures et des heures de recherche, le plus souvent dans la source, pour réussir à s&#8217;en sortir en ayant toujours à l&#8217;esprit : &laquo;&nbsp;Est-ce que je ne suis pas en train de prendre des raccourcis ?&nbsp;&raquo;</p>

<p>Ceci n&#8217;enlève pas la qualité du produit mais joue beaucoup dans la décision finale. Développer avec Magento, c&#8217;est long. Ça sera difficile pour la plupart des développeurs, et ne parlons même pas des néophytes. Pour créer un module, accrochez vous. Vous passerez par des phases enchantées mais aussi par des phases de déprime totale <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p>Par contre, si vous n&#8217;avez aucune spécificité technique particulière, vous aurez entre les mains un outil qui excelle dans la gestion d&#8217;une e-boutique. L&#8217;installation standard contient déjà la plupart des modules nécessaires à une boutique robuste : gestion de multiples &laquo;&nbsp;vues&nbsp;&raquo; (pour le multilingue par ex.), attributs des produits très flexibles, gestion des promotions, des newsletters, très bons outils de reporting, etc. etc.</p>

<h2>D&#8217;un point de vue technique</h2>

<h3>Modèle de données EAV</h3>

<p>L&#8217;organisation des données dans Magento repose sur le modèle EAV, acronyme pour Entity-Attribute-Value. Ce modèle de données permet de définir des entités dont le nombre d&#8217;attributs peut être très vaste et scalable. Ceci grâce à une séparation de l&#8217;entité et de ses paires attribut/valeur. En théorie, ce modèle de données est relativement simple.</p>

<p>En base de données, l&#8217;entité est stockée avec très peu d&#8217;attributs. La plupart du temps une clé primaire, des clés étrangères, et quelques attributs universels (par exemple la référence d&#8217;un produit).</p>

<p>Les attributs sont stockés dans une table commune à toutes les entités (liées par clé étrangère) qui contient tout type d&#8217;information : identifiant, nom, label, type (int, char, etc.), certaines contraintes (pour la validation par ex.).</p>

<p>Les valeurs sont souvent stockées dans des tables spécifiques avec comme clé étrangère l&#8217;identifiant de l&#8217;attribut. Mais pas toujours, dans des implémentations simples du modèle EAV les paires attribut/valeur peuvent être stockées dans la même table.</p>

<p>Sur le papier c&#8217;est très prometteur. Mais en pratique ça devient vite impraticable. Cette modélisation rend le code beaucoup plus difficile à déchiffrer. Les requêtes deviennent très complexes en plus d&#8217;être très coûteuses en ressources (beaucoup de jointures).</p>

<p>Bien que très flexible, cette modélisation est pour moi une manière de pervertir une base de données relationnelle. Et dans le cas de Magento, le modèle EAV force MySQL à se comporter d&#8217;une façon pour laquelle il n&#8217;est pas du tout prévu.</p>

<p>Mais qu&#8217;il en soit ainsi, les développeurs de Magento ont choisi la flexibilité par dessus la simplicité. Ce n&#8217;est pas nécessairement une mauvaise chose, mais vous êtes avertis <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p>L&#8217;implémentation du modèle EAV dans Magento est très poussée, il faut chercher dans beaucoup de tables pour une seule entité mais le modèle objet rend heureusement les choses plus faciles. Mais attention, il faut éviter le plus possible d&#8217;avoir recours à des requêtes SQL pures, sinon je vous promet qu&#8217;il vous manquera quelques cheveux à la fin de l&#8217;exercice !</p>

<h3>Architecture de Magento et qualité du code</h3>

<p>Ce sujet est très sensible. En tant qu&#8217;architecte et développeur web averti, je reste dubitatif.</p>

<p>L&#8217;architecture du système regorge de bonnes idées, parfois ingénieuses, mais leurs implémentations laissent parfois un arrière goût d&#8217;anti bonnes pratiques.
Mais globalement je dois avouer que je suis surpris par la réflexion qui a été menée sur ce projet. Je ne m&#8217;attendais pas à quelque chose d&#8217;aussi poussé.</p>

<h4>La vue dans Magento</h4>

<p>Magento propose une implémentation particulière de la couche présentation (vues) du modèle MVC.</p>

<p>Dans une implémentation classique, le contrôleur prépare le modèle et le donne à la vue qui n&#8217;a plus qu&#8217;à afficher les données correctement formatées.</p>

<p>Dans Magento, la vue elle-même est décortiquée en une architecture particulière. Tout repose sur un système de layout regroupant des &laquo;&nbsp;blocks&nbsp;&raquo; qui sont des portions de vue autonomes. Si on ferme les yeux sur les conséquences en termes de performances, cette modélisation est une véritable surprise.</p>

<p>Le contrôleur prépare toujours le modèle mais ne le passe pas à une vue. Il le stocke simplement dans un &laquo;&nbsp;registre&nbsp;&raquo; que chaque block pourra ensuite consulter pour récupérer les données nécessaires à l&#8217;affichage.</p>

<p>Une vue est un regroupement de blocks dont l&#8217;organisation est définie par un fichier XML, le layout.</p>

<p>Un block est un objet autonome totalement découplé du système qui peut être inclus dans n&#8217;importe quelle page du site et à n&#8217;importe quel moment. Il est composé concrètement d&#8217;une classe contenant des méthodes accessibles directement depuis un &laquo;&nbsp;template&nbsp;&raquo; (vocabulaire Magento pour le fichier phtml) qui met en forme le block (code HTML).</p>

<p>Si on essaie grossièrement de faire l&#8217;analogie avec une application Zend Framework classique, on peut dire que l&#8217;objet block est un regroupement d&#8217;aides de vue (view helpers), et que le template est la vue.</p>

<p>Je trouve ce système très bien foutu, et il montre une très grande flexibilité.</p>

<p>Mais <strong>attention</strong> (toujours un &laquo;&nbsp;mais&nbsp;&raquo;), cette architecture ouvre plus encore la porte vers les mauvaises pratiques. C&#8217;est à dire l&#8217;utilisation d&#8217;une couche pour laquelle elle n&#8217;est pas prévue.</p>

<p>Si vous vous demandez encore quel est précisément le rôle de chaque couche dans le paradigme MVC, ça sera pire avec Magento. Et c&#8217;est précisément le problème ici, beaucoup de développeurs utiliseront malheureusement le block comme un contrôleur d&#8217;actions, et un tel découplage laisse présager un véritable foutoir dans certains projets.</p>

<h4>Création de module dans Magento</h4>

<p>Je n&#8217;ai pas grand chose à dire sur cette partie. Une fois le système de block et la couche &laquo;&nbsp;Modèle&nbsp;&raquo; bien assimilés, la création de module ne devrait pas vous poser de problèmes. Si ce n&#8217;est quelques spécificités comme par exemple si vous souhaitez inclure une galerie d&#8217;images administrable (bon courage avec ça :p).</p>

<p>L&#8217;utilisation du modèle EAV n&#8217;est pas obligatoire, vous pouvez très bien définir des entités et les implémenter de manière classique.</p>

<p>La seule contrainte est l&#8217;utilisation abondante de XML pour configurer le module, et l&#8217;absence de documentation précise vous promet quelques heures de recherche.</p>

<p>L&#8217;ajout d&#8217;un module dans l&#8217;administration du site est un peu délicat au début (notamment les formulaires), mais une fois le baptême du feu passé, vous irez beaucoup plus vite. Magento propose des widgets permettant de créer &laquo;&nbsp;facilement&nbsp;&raquo; des grilles pour vos collections de données et des formulaires pré-formatés pour la modification de votre modèle.</p>

<p>Dans Magento tout doit être fait manuellement, en programmation. Si vous vous attendiez à créer simplement votre boutique à l&#8217;aide de la souris et d&#8217;une interface type CMS, c&#8217;est raté, vous devrez implémenter vous même vos modèles, contrôleurs, blocks et templates, comme vous le feriez avec Zend Framework (mais en plus complexe :p).</p>

<h3>CMS</h3>

<p>Ça va être très court. Le CMS de Magento laisse vraiment à désirer. Si vous comptiez inclure des pages de contenu avec une mise en page un peu recherchée et qui seraient administrables par le CMS, vous pouvez lâcher tout de suite l&#8217;affaire.</p>

<p>Ce module est plus qu&#8217;insuffisant et vous fera parfois abandonner Magento au profit d&#8217;un véritable CMS quitte à se contenter d&#8217;un module e-commerce très limité.</p>

<p>Le CMS vous permet de créer des pages ou des blocks statiques. Le petit plus est qu&#8217;il permet d&#8217;inclure des variables ou des blocks dynamiques au sein de votre page grâce à des &laquo;&nbsp;insert tags&nbsp;&raquo;.</p>

<p>Pour le reste, le CMS vous permet de modifier le layout XML de la page directement dans l&#8217;admin plutôt que dans un fichier. Il y a peu d&#8217;intérêt, sauf si vous formez votre client et qu&#8217;il se sent capable de modifier le layout, mais je dis <strong>attention</strong> ! <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<h3>Les petits plus</h3>

<p>Magento regorge de petites options pratiques, surtout pour les développeurs. Bien sûr c&#8217;est relatif, c&#8217;est pratique dans un contexte où tout est complexe <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p>Vous pouvez activer par exemple un mode de traduction qui vous permet de traduire les clés CSV directement dans le site. Ou encore activer un débuggueur, configurer des notifications pour vos tâches CRON, réunir tous les fichiers javascript et CSS en un seul fichier, etc etc.</p>

<p>Je citerai aussi Magento Connect et son écosystème de modules qui est vraiment très appréciable. Il s&#8217;agit en fait d&#8217;un GUI (interface) qui vous permet de déclencher des installations et des mises à jour façon PEAR, tout ça avec la souris. Les versions des modules sont bien gérées, mais attention tout de même à ne pas installer n&#8217;importe quoi.</p>

<h2>Conclusion</h2>

<p>Vous l&#8217;aurez compris, l&#8217;apprentissage de Magento demande une certaine maîtrise du développement et beaucoup d&#8217;investissement.</p>

<p>Cet article est un premier retour sur l&#8217;architecture du projet et je ne prétend pas maîtriser l&#8217;outil au point que mes arguments soient considérés comme une vérité générale. Si vous n&#8217;êtes pas d&#8217;accord avec certaines idées, n&#8217;hésitez pas à vous exprimer.</p>

<p>Je ne peux aussi pas faire le tour de toutes les possibilités dans un seul article. Je n&#8217;ai par exemple pas parlé du SEO ou de la gestion des droits, et j&#8217;en passe.</p>

<p>Bien que j&#8217;admire certaines parties du système, j&#8217;émets de grosses réserves sur les performances avec un catalogue produits conséquent (> à 5000 produits).</p>

<p>Je trouve aussi dommage que Varien n&#8217;ait pas fait plus d&#8217;efforts sur la documentation et ne propose pas de mieux guider les développeurs dans le choix de cette solution. C&#8217;est un véritable frein et beaucoup de développeurs abandonneront en cours de route.</p>

<p>Néanmoins, Magento reste pour le moment et pour moi, la Rolls des solutions e-commerce libres sur le marché.</p>
<div class="shr-publisher-170"></div><img src="http://feeds.feedburner.com/~r/anonymation-blog-developpement-architecture-web/~4/XLXyTrAwb38" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code.anonymation.com/magento/magento-alors-cest-comment/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://code.anonymation.com/magento/magento-alors-cest-comment/</feedburner:origLink></item>
		<item>
		<title>Amélioration de l’intégration ZF et Twig</title>
		<link>http://feedproxy.google.com/~r/anonymation-blog-developpement-architecture-web/~3/3JeoVfmnqM0/</link>
		<comments>http://code.anonymation.com/zend-framework/amelioration-de-lintegration-zf-et-twig/#comments</comments>
		<pubDate>Tue, 14 Dec 2010 10:05:08 +0000</pubDate>
		<dc:creator>Benjamin Dulau</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[moteur de template]]></category>
		<category><![CDATA[twig]]></category>
		<category><![CDATA[twig zend]]></category>

		<guid isPermaLink="false">http://code.anonymation.com/?p=152</guid>
		<description><![CDATA[Un billet très court pour faire une mise au point sur l&#8217;intégration de Twig avec Zend Framework 1.1x.

Pour ceux qui ne sont pas au courant, je vous invite à lire les billets suivants :


Utiliser un moteur de template avec PHP, pourquoi ?
Utiliser Twig avec Zend Framework 1.1x


J&#8217;ai apporté quelques améliorations, notamment grâce aux retours de Mickael Perraud que je remercie au passage.

La librairie supporte maintenant plusieurs moteurs de templates au sein d&#8217;une même application. Ceci implique quelques modifications dans la [...]]]></description>
			<content:encoded><![CDATA[<p>Un billet très court pour faire une mise au point sur l&#8217;intégration de Twig avec Zend Framework 1.1x.</p>

<p>Pour ceux qui ne sont pas au courant, je vous invite à lire les billets suivants :</p>

<ul>
<li><a href="http://code.anonymation.com/php5/utiliser-un-moteur-de-template-avec-php-pourquoi/" title="">Utiliser un moteur de template avec PHP, pourquoi ?</a></li>
<li><a href="http://code.anonymation.com/zend-framework/utiliser-twig-avec-zend-framework-1-1x/" title="">Utiliser Twig avec Zend Framework 1.1x</a></li>
</ul>

<p>J&#8217;ai apporté quelques améliorations, notamment grâce aux retours de Mickael Perraud que je remercie au passage.</p>

<p>La librairie supporte maintenant plusieurs moteurs de templates au sein d&#8217;une même application. Ceci implique quelques modifications dans la configuration :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container ini default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ini codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">resources.view.engines.php.class <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;Ano_View_Engine_PhpEngine&quot;</span><br />
resources.view.engines.php.viewSuffix <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;phtml&quot;</span><br />
<br />
resources.view.engines.twig.class <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;Ano_ZFTwig_View_Engine_TwigEngine&quot;</span><br />
resources.view.engines.twig.isDefault <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> 1</span><br />
resources.view.engines.twig.viewSuffix <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;twig&quot;</span> &nbsp; &nbsp;<br />
resources.view.engines.twig.options.charset <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;utf-8&quot;</span><br />
resources.view.engines.twig.options.strict_variables <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> 0</span><br />
resources.view.engines.twig.options.cache <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> APPLICATION_PATH </span><span style="color: #933;">&quot;/../var/cache/twig&quot;</span><br />
resources.view.engines.twig.options.auto_reload <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> 1</span><br />
resources.view.engines.twig.options.debug <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> 0</span><br />
resources.view.engines.twig.options.trim_blocks <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> 1 &nbsp; &nbsp;</span><br />
<br />
resources.view.helperPath.My_View_Helper_ <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;My/View/Helper&quot;</span><br />
<br />
# Si vous utilisez Zend_Layout<br />
resources.layout.layout <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;layout&quot;</span> <br />
resources.layout.layoutPath <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> APPLICATION_PATH </span><span style="color: #933;">&quot;/views/layouts&quot;</span></div></div></div>

<p>Pour des raisons pratiques (je suppose pour faciliter la migration vers Twig), Mickael a ajouté une aide d&#8217;action (et les tests unitaires qui vont avec, merci :p) qui permet de définir le moteur à utiliser selon l&#8217;action de contrôleur, grâce à une simple annotation.</p>

<p>Exemple :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #009933; font-style: italic;">/**<br />
&nbsp; &nbsp; &nbsp;* @render twig<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> barAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div></div>

<p>J&#8217;ai également ajouté une nouvelle extension : &laquo;&nbsp;trans&nbsp;&raquo;, qui s&#8217;utilise comme ceci :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">{% trans 'message' %}<br />
{% metaName 'description' with 'My message'|trans %}</div></div></div>

<p>Les modifications ont été fusionnées avec la branche &laquo;&nbsp;master&nbsp;&raquo; sur github : <a href="http://github.com/benjamindulau/Ano_ZFTwig" title="">http://github.com/benjamindulau/Ano_ZFTwig</a></p>

<p>Je vous invite aussi à consulter le README qui a été mis à jour.</p>

<p>Toute cette intégration peut sembler superflue avec l&#8217;arrivée des nouvelles versions majeures des frameworks Zend et Symfony, mais beaucoup de projets démarrent encore avec ZF 1.x.</p>

<p>Bon twig !</p>
<div class="shr-publisher-152"></div><img src="http://feeds.feedburner.com/~r/anonymation-blog-developpement-architecture-web/~4/3JeoVfmnqM0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code.anonymation.com/zend-framework/amelioration-de-lintegration-zf-et-twig/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://code.anonymation.com/zend-framework/amelioration-de-lintegration-zf-et-twig/</feedburner:origLink></item>
		<item>
		<title>Utiliser Twig avec Zend Framework 1.1x</title>
		<link>http://feedproxy.google.com/~r/anonymation-blog-developpement-architecture-web/~3/49Oq0R1DJCU/</link>
		<comments>http://code.anonymation.com/zend-framework/utiliser-twig-avec-zend-framework-1-1x/#comments</comments>
		<pubDate>Tue, 23 Nov 2010 11:35:20 +0000</pubDate>
		<dc:creator>Benjamin Dulau</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[moteur de template]]></category>
		<category><![CDATA[twig]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[zend_view]]></category>

		<guid isPermaLink="false">http://code.anonymation.com/?p=93</guid>
		<description><![CDATA[Cet article est un peu une suite de : Utiliser un moteur de template avec PHP, pourquoi ? que je vous invite à lire.

Comme je l&#8217;expliquais, avec les mauvaises expériences, je reviens sur mes positions concernant les moteurs de templates. Mais ce n&#8217;est pas la seule raison, si mon intérêt se porte de nouveaux sur un tel système c&#8217;est aussi grâce à l&#8217;arrivée de nouveaux moteurs de templates complets, flexibles, et surtout très performants.

Mon attention s&#8217;est récemment portée vers Twig, [...]]]></description>
			<content:encoded><![CDATA[<p>Cet article est un peu une suite de : <a href="http://code.anonymation.com/php5/utiliser-un-moteur-de-template-avec-php-pourquoi/" title="">Utiliser un moteur de template avec PHP, pourquoi ?</a> que je vous invite à lire.</p>

<p>Comme je l&#8217;expliquais, avec les mauvaises expériences, je reviens sur mes positions concernant les moteurs de templates. Mais ce n&#8217;est pas la seule raison, si mon intérêt se porte de nouveaux sur un tel système c&#8217;est aussi grâce à l&#8217;arrivée de nouveaux moteurs de templates complets, flexibles, et surtout très performants.</p>

<p>Mon attention s&#8217;est récemment portée vers <a href="http://www.twig-project.org/" title="TWIG The flexible, fast, and secure template language for PHP">Twig</a>, un moteur de templates proposé par Fabien Potencier (créateur de symfony). Fabien a fait revivre le moteur initialement créé par Armin Ronacher (pour une plateforme de blogs), a amélioré le code, et propose au moment où j&#8217;écris ces lignes, une version 0.9.9, plus qu&#8217;un pas vers une version &laquo;&nbsp;officiellement&nbsp;&raquo; stable donc.</p>

<p>En jouant avec le moteur, j&#8217;ai rapidement été convaincu, et je me suis vite mis à chercher si une intégration avec Zend Framework existait. J&#8217;ai trouvé quelques propositions d&#8217;intégration, certaines abandonnées, d&#8217;autres incomplètes, ou encore incompatibles avec la version actuelle de Twig.</p>

<p>Après quelques bidouillages, j&#8217;ai décidé de créer ma propre intégration du moteur, que je ferai évoluer en fonction des besoins.</p>

<h2>Comment fonctionne Twig ?</h2>

<p>Pour ce qui est des fonctionnalités du moteur, je vous laisse lire la <a href="http://www.twig-project.org/documentation" title="">documentation</a> sur le site officiel.</p>

<p>Ce qui nous intéresse plus ici, c&#8217;est la flexibilité de la bête. Et vous ne serez pas déçus.</p>

<p>Après avoir passé quelques heures à lire le code source et à faire quelques tests pour comprendre le fonctionnement du parser, j&#8217;avoue que je suis surpris par la facilité d&#8217;appréhension du système. Tout est extensible, il est assez simple d&#8217;étendre le coeur du moteur et simple aussi de créer de nouveaux tags. Je ne suis pas certain d&#8217;avoir utilisé toutes les possibilités offertes pour mon intégration dans Zend Framework, mais je ne manquerai pas de faire évoluer les choses au fur et à mesure de mes découvertes.</p>

<p>Twig utilise un objet appelé <strong>environment</strong> qui est utilisé pour stocker la configuration, les extensions et pour charger les templates. Dans la plupart des cas, un objet <strong>environment</strong> est créé et est ensuite utilisé pour rendre tous les templates de l&#8217;application.</p>

<p>Pour charger les templates, un objet <strong>loader</strong> est fourni à l&#8217;environnement, il est responsable de charger les templates depuis une resource, par exemple une chaine ou un fichier.</p>

<p>Une extension est un ensemble de fonctionnalités ajoutées à Twig. Dans Twig, tout est extension, même le coeur du moteur. Le moteur est livré avec plusieurs extensions permettant de proposer un panel de fonctionnalités très confortable.</p>

<p>Pour ce qui est de la création de nouveaux tags, le fonctionnement de Twig est assez simple, il faut au minimum :</p>

<ul>
<li>une extension qui sera pluggée à Twig et qui regroupe un ou plusieurs parsers</li>
<li>un ou plusieurs parser (soit un générique, soit un pour chaque tag)</li>
<li>un ou plusieurs noeuds, objets qui vont compiler le code en PHP.</li>
</ul>

<p>Pour parser la syntaxe d&#8217;un tag, Twig utilise une &laquo;&nbsp;grammaire&nbsp;&raquo; particulière pour chaque type d&#8217;expression (arguments de type constante, tableau, variable, etc.). Chaque grammaire est associée à un parser. De cette manière, Twig est capable d&#8217;analyser automatiquement le contenu d&#8217;un tag et d&#8217;en extraire différentes expressions.</p>

<p>Voici un exemple de tag :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">{% javascript 'js/myScript.js' with ['mode': 'prepend'] %}</div></div></div>

<p>Et voici la grammaire de ce tag :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;js&gt; [with &lt;arguments:array&gt;]</div></div></div>

<p>Un tag est considéré comme un noeud contenant un ensemble d&#8217;expressions (chacune associée à une grammaire) pouvant elles-mêmes être des noeuds. Une fois que le parser a interprété un tag, il invoque un objet <strong>node</strong> qui se charge de compiler (via un objet <strong>compiler</strong>) chaque expression du noeud en PHP. Pour pouvoir être compilée, chaque classe d&#8217;expression possède une méthode <em>compile</em> qui se charge de retourner la représentation PHP de l&#8217;expression.</p>

<p>Par exemple, l&#8217;expression :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">['param1': 'val1', 'param2': 'val2']</div></div></div>

<p>Dont la grammaire est :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;arguments:array&gt;</div></div></div>

<p>Sera compilée en :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'param1'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'val1'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'param2'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'val2'</span><span style="color: #009900;">&#41;</span></div></div></div>

<p>Il est donc possible d&#8217;ajouter de nouvelles &laquo;&nbsp;grammaires&nbsp;&raquo; selon les besoins et de créer les parsers et expressions associés.</p>

<p>Je ne vais pas m&#8217;étaler plus sur le fonctionnement interne du moteur. D&#8217;une part parce que je n&#8217;arriverai pas à couvrir toutes les possibilités dans un article et ensuite parce que c&#8217;est bien plus compliqué à expliquer qu&#8217;à utiliser. La meilleure façon pour vous de comprendre le fonctionnement est de parcourir les sources, de vous amusez avec le moteur et de tenter de créer vos propres extensions.</p>

<h2>Intégration avec Zend Framework</h2>

<p>Il existe deux points difficiles pour l&#8217;intégration avec ZF :</p>

<ul>
<li>conserver le fonctionnement de Zend_Layout</li>
<li>Proposer une syntaxe pour invoquer les aides d&#8217;actions.</li>
</ul>

<p>Il n&#8217;y a pas de magie, certaines aides d&#8217;actions devront être spécifiquement implémentées dans une extension pour pouvoir fonctionner. Pour cette première intégration, j&#8217;ai créé des tags pour certaines aides d&#8217;actions indispensables natives au framework. A vous de compléter mon travail en fonction de vos besoins.</p>

<h3>Utilisation de Zend_Layout ou non ?</h3>

<p>C&#8217;est une question de choix, et surtout de goûts.</p>

<p>Twig propose nativement un système d&#8217;héritage des templates. Vous pouvez vous passer complètement de Zend_Layout en utilisant cette fonctionnalité. La différence est que dans Twig, les templates enfants sont rendus après les templates parents. Certaines choses qui vous semblaient peut-être naturelles ne le seront plus.</p>

<h3>Exemples</h3>

<h4>Sans Zend Layout et avec l&#8217;héritage de templates :</h4>

<p><em>views/layouts/layout.twig</em></p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #00bbdd;">&lt;!DOCTYPE HTML&gt;</span> <br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">html</span></a>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;</span>{% block title %}{% endblock%}<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; {% block metas %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {% metaHttpEquiv 'Content-Type' with 'text/html; charset=utf-8' %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; {% endblock %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; {% block javascripts %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {% javascript 'js/jquery.js' %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; {% endblock %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; {% block stylesheets %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {% stylesheet 'css/layout.css' %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; {% endblock %}<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; {% metas %} <br />
&nbsp; &nbsp; &nbsp; &nbsp; {% javascripts %} <br />
&nbsp; &nbsp; &nbsp; &nbsp; {% stylesheets %} <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/h1.html"><span style="color: #000000; font-weight: bold;">h1</span></a>&gt;</span>{% block 'title1' %}Titre par défaut{% endblock %}<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/h1.html"><span style="color: #000000; font-weight: bold;">h1</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; {% block content %}{% endblock %}<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span> <br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">html</span></a>&gt;</span></div></div></div>

<p><em>views/index/twig-zf.twig</em></p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">{% extends 'layouts/layout.twig' %}<br />
<br />
{% block title 'Anonymation - Twig for Zend Framework' %}<br />
<br />
{% block metas %}<br />
&nbsp; &nbsp; {% parent %}<br />
&nbsp; &nbsp; {% metaName 'description' with 'My super twig description for SEO' %}<br />
{% endblock %}<br />
{% block javascripts %}<br />
&nbsp; &nbsp; {% parent %}<br />
&nbsp; &nbsp; {% javascript 'js/twig.js' %}<br />
{% endblock %}<br />
{% block stylesheets %}<br />
&nbsp; &nbsp; {% parent %}<br />
&nbsp; &nbsp; {% stylesheet 'css/twig.css' %}<br />
{% endblock %}<br />
<br />
{% block 'title1' 'Some help about Twig' %}<br />
<br />
{% block content %}<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;more-information&quot;</span>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">p</span></a>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Helpful Links: <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/br.html"><span style="color: #000000; font-weight: bold;">br</span></a> <span style="color: #66cc66;">/</span>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://www.twig-project.org/documentation&quot;</span>&gt;</span>Twig documentation<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span> | <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://github.com/benjamindulau/Ano_ZFTwig&quot;</span>&gt;</span>Ano_ZFTwig source code<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">p</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;{% route 'default' with ['controller': 'index', 'action': 'index'] %}&quot;</span>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ddbb00;">&amp;lt;</span> Back to homepage <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span> <br />
{% endblock %}</div></div></div>

<h4>Avec Zend Layout :</h4>

<p>Le même exemple en utilisant Zend Layout, sachant que la vue est rendue avant le layout, donc impossible d&#8217;utiliser les block. L&#8217;utilisation de Zend Layout implique aussi l&#8217;utilisation de certains tags spécifiques que vous retrouverez dans le package Ano_ZFTwig.</p>

<p><em>views/layouts/layout.twig</em></p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #00bbdd;">&lt;!DOCTYPE HTML&gt;</span> <br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">html</span></a>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; {% title %} <br />
&nbsp; &nbsp; &nbsp; &nbsp; {% metaHttpEquiv 'Content-Type' with 'text/html; charset=utf-8' %} <br />
&nbsp; &nbsp; &nbsp; &nbsp; {% javascript 'js/jquery.js' with ['mode': 'prepend'] %} <br />
&nbsp; &nbsp; &nbsp; &nbsp; {% stylesheet 'css/layout.css' with ['mode': 'prepend'] %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/base.html"><span style="color: #000000; font-weight: bold;">base</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;{% hlp 'serverUrl' %}/{% hlp 'baseUrl' %}&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; {% metas %} <br />
&nbsp; &nbsp; &nbsp; &nbsp; {% javascripts %} <br />
&nbsp; &nbsp; &nbsp; &nbsp; {% stylesheets %} <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/h1.html"><span style="color: #000000; font-weight: bold;">h1</span></a>&gt;</span>{% holder 'title1' %}<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/h1.html"><span style="color: #000000; font-weight: bold;">h1</span></a>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; {% layout 'content' %} <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span> <br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">html</span></a>&gt;</span></div></div></div>

<p><em>views/index/twig-zf.twig</em></p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">{# layout override #} <br />
<br />
{% headTitle 'Anonymation - Twig for Zend Framework' %}<br />
{% metaName 'description' with 'My super twig description for SEO' %}<br />
{% javascript 'js/twig.js' %} <br />
{% holder 'title1' with 'Some help about Twig' %} <br />
<br />
{# content #} <br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;more-information&quot;</span>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">p</span></a>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Helpful Links: <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/br.html"><span style="color: #000000; font-weight: bold;">br</span></a> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://www.twig-project.org/documentation&quot;</span>&gt;</span>Twig documentation<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span> | <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://github.com/benjamindulau/Ano_ZFTwig&quot;</span>&gt;</span>Ano_ZFTwig source code<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">p</span></a>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;{% route 'default' with ['controller': 'index', 'action': 'index'] %}&quot;</span>&gt;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ddbb00;">&amp;lt;</span> Back to homepage <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span></div></div></div>

<p>Vous remarquez ici les options <em>prepend</em> pour l&#8217;ajout de JS et de CSS, comme la vue est rendue avant, les scripts ajoutés dans le layout doivent aller au dessus de la pile, exactement comme si vous utilisiez le moteur de templates par défaut de Zend Framework.</p>

<p>Vous voyez aussi que les tags <em>javascripts</em> &amp; co n&#8217;ont pas besoin d&#8217;être dans un block, comme le layout est rendu après la vue, les stacks seront prêts au moment de l&#8217;affichage.</p>

<h3>Installation et configuration</h3>

<p>Pour installer la librairie :</p>

<ul>
<li>téléchargez les sources : <a href="http://github.com/benjamindulau/Ano_ZFTwig" title="">http://github.com/benjamindulau/Ano_ZFTwig</a></li>
<li>placez le package Ano dans le dossier library de votre projet</li>
<li>ajoutez les lignes suivantes dans votre application.ini :</li>
</ul>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container ini default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ini codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">autoloaderNamespaces<span style="">&#91;</span><span style="">&#93;</span> <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;Ano_&quot;</span><br />
pluginPaths.Ano_Application_Resource <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> APPLICATION_PATH </span><span style="color: #933;">&quot;/../library/Ano/Application/Resource&quot;</span></div></div></div>

<p>Pour configurer et activer Twig ça se passe dans application.ini :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container ini default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ini codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">resources.twig.options.charset <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;utf-8&quot;</span><br />
resources.twig.options.strict_variables <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> 0</span><br />
resources.twig.options.cache <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> APPLICATION_PATH </span><span style="color: #933;">&quot;/../var/cache/twig&quot;</span><br />
resources.twig.options.auto_reload <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> 1</span><br />
resources.twig.options.debug <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> 0</span><br />
resources.twig.options.trim_blocks <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> 1</span><br />
resources.twig.options.viewSuffix <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> twig</span><br />
resources.twig.viewPaths<span style="">&#91;</span><span style="">&#93;</span> <span style="color: #000066; font-weight:bold;">=</span> APPLICATION_PATH <span style="color: #933;">&quot;/views/layouts&quot;</span><br />
resources.twig.viewPaths<span style="">&#91;</span><span style="">&#93;</span> <span style="color: #000066; font-weight:bold;">=</span> APPLICATION_PATH <span style="color: #933;">&quot;/views/scripts&quot;</span><br />
resources.twig.helperPath.My_View_Helper_ <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;My/View/Helper&quot;</span></div></div></div>

<p>Pour les options de Twig je vous laisse lire la <a href="http://www.twig-project.org/book/03-Twig-for-Developers" title="">doc officielle pour les développeurs</a>.</p>

<p>Il faut penser à bien ajouter tous les chemins vers les scripts de vues, y compris les chemins vers les layouts si vous n&#8217;utilisez pas Zend_Layout.</p>

<p>Si vous souhaitez utiliser Zend_Layout, il suffit d&#8217;ajouter sa configuration :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container ini default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ini codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">resources.layout.layout <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;layout&quot;</span> <br />
resources.layout.layoutPath <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> APPLICATION_PATH </span><span style="color: #933;">&quot;/views/layouts&quot;</span> <br />
resources.layout.viewSuffix <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;twig&quot;</span></div></div></div>

<p>Et c&#8217;est tout <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<h3>Utilisation</h3>

<p>Vous n&#8217;avez rien à changer dans vos contrôleurs pour utiliser Twig, vous continuez à développer comme d&#8217;habitude, le <em>viewrenderer</em> se chargera automatiquement de rendre les vues avec le moteur de Twig.</p>

<p>Pour les fonctionnalités courantes du moteur je vous redirige encore vers la <a href="http://www.twig-project.org/book/02-Twig-for-Template-Designers" title="">doc officielle</a> (pour les designers cette fois-ci).</p>

<h4>Les tags additionnels inclus dans le package Ano_ZFTwig :</h4>

<p>(pas de coloration syntaxique, désolé :p)</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">&lt;!-- Invoquer n'importe quelle aide de vue (mais pas leurs méthodes) --&gt;</span><br />
{% hlp 'myHelper' with ['arg1', ['key1': 'val1', 'key2': 'val2'], 'arg3'] %}<br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- Ajouter un fichier script javascript à la pile --&gt;</span><br />
<span style="color: #808080; font-style: italic;">&lt;!-- Le mode est optionel, par défaut : append --&gt;</span><br />
{% javascript 'js/shared.js' %}<br />
{% javascript 'js/form.js' with ['mode': 'prepend'] %}<br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- Rendre les tags javascripts (dans la section &lt;head&gt; par ex.) --&gt;</span><br />
{% javascripts %}<br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- Ajouter une feuille de style (css) à la pile --&gt;</span><br />
<span style="color: #808080; font-style: italic;">&lt;!-- Le mode est optionel, par défaut : append --&gt;</span><br />
{% stylesheet 'css/layout.css' %}<br />
{% stylesheet 'css/ma-page.css' with ['mode': 'prepend'] %}<br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- Rendre les tags link css (dans la section &lt;head&gt; par ex.) --&gt;</span><br />
{% stylesheets %}<br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- Ajouter un balise meta http-equiv à la pile --&gt;</span><br />
<span style="color: #808080; font-style: italic;">&lt;!-- Option : mode =&gt; append/prepend --&gt;</span><br />
{% metaHttpEquiv 'Content-Type' with 'text/html; charset=utf-8' %}<br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- Ajouter un balise meta name à la pile --&gt;</span><br />
<span style="color: #808080; font-style: italic;">&lt;!-- Option : mode =&gt; append/prepend --&gt;</span><br />
{% metaName 'description' with 'My super website SEO description' %}<br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- Rendre les balises metas --&gt;</span><br />
{% metas %}<br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- Changer la balise &lt;title&gt;&lt;/title&gt; --&gt;</span><br />
{% headTitle 'My page title' %}<br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- Rendre la balise &lt;title&gt;&lt;/title&gt; --&gt;</span><br />
{% title %}<br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- Construire une url depuis une route --&gt;</span><br />
{% route 'photo_route' with ['id': photo.id] %}<br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- Rendre une section du layout --&gt;</span><br />
<span style="color: #808080; font-style: italic;">&lt;!-- ex. équivalent à : &lt;?php echo $this-&gt;layout()-&gt;content; ?&gt; --&gt;</span><br />
{% layout 'content' %}<br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- Assigner la valeur d'un placeholder --&gt;</span><br />
{% holder 'titleh1' with 'My main title for SEO' %}<br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- Afficher un placeholder --&gt;</span><br />
{% holder 'titleh1' %}</div></div></div>

<h2>Conclusion sur un exemple avancé</h2>

<p>Avant de vous laisser, je vous propose de voir la version Twig de l&#8217;exemple que j&#8217;ai donné dans l&#8217;article : <a href="http://code.anonymation.com/php5/utiliser-un-moteur-de-template-avec-php-pourquoi/" title="">Utiliser un moteur de template avec PHP, pourquoi ?</a></p>

<p>Souvenez-vous, notre vue qui affiche une vidéo utilisateur :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;?php </span><br />
<span style="color: #009900;"><span style="color: #66cc66;">//</span> &lt;<a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;</span><br />
$this-&gt;headTitle($this-&gt;escape($this-&gt;video-&gt;title));<br />
<br />
$this-&gt;headMeta()-&gt;appendName('description', $this-&gt;excerpt($this-&gt;escape($this-&gt;video-&gt;description), 200, true));<br />
<br />
$this-&gt;headScript()-&gt;appendFile('videos.js');<br />
$this-&gt;placeholder('title1')-&gt;set($this-&gt;escape($this-&gt;video-&gt;title));<br />
?&gt;<br />
<br />
<span style="color: #009900;">&lt;?php <span style="color: #66cc66;">/</span>* Video owner <span style="color: #000066;">action</span> *<span style="color: #66cc66;">/</span> ?&gt;</span><br />
<span style="color: #009900;">&lt;?php if <span style="color: #66cc66;">&#40;</span>$this-&gt;</span>auth-&gt;isAllowed($this-&gt;currentUser, $this-&gt;video, 'edit')) : ?&gt;<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;actions&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?php echo $this-&gt;</span></span>url(array('controller' =&gt; 'videos', 'action' =&gt; 'edit', 'id' =&gt; $this-&gt;video-&gt;id), 'default'); ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Editer<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?php echo $this-&gt;</span></span>url(array('controller' =&gt; 'videos', 'action' =&gt; 'delete', 'id' =&gt; $this-&gt;video-&gt;id), 'default'); ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Supprimer<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;?php endif; ?&gt;</span><br />
<br />
<span style="color: #009900;">&lt;?php <span style="color: #66cc66;">/</span>* Video &lt;<a href="http://december.com/html/4/element/object.html"><span style="color: #000000; font-weight: bold;">object</span></a>&gt;</span> */ ?&gt;<br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;video&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;video-inner&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php echo $this-&gt;</span>getVideoObject($this-&gt;video-&gt;code); ?&gt;<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<br />
<span style="color: #009900;">&lt;?php <span style="color: #66cc66;">/</span>* Video details *<span style="color: #66cc66;">/</span> ?&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;video-details&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;description&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php echo nl2br<span style="color: #66cc66;">&#40;</span>$this-&gt;</span>escape($this-&gt;video-&gt;description)); ?&gt;<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;author&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?php echo $this-&gt;</span></span>url(array('id' =&gt; $this-&gt;video-&gt;user-&gt;id), 'user_route'); ?&gt;&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;title=&quot;Voir le profil de <span style="color: #009900;">&lt;?php echo $this-&gt;</span>escape($this-&gt;video-&gt;user-&gt;login); ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&lt;?php echo $this-&gt;</span>escape($this-&gt;video-&gt;user-&gt;login); ?&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<br />
<span style="color: #009900;">&lt;?php <span style="color: #66cc66;">/</span>* List of video comments *<span style="color: #66cc66;">/</span> ?&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comments&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;?php foreach<span style="color: #66cc66;">&#40;</span>$this-&gt;</span>comments as $comment) : ?&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-item&quot;</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-&lt;?php echo $comment-&gt;</span></span>id; ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-author&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?php echo $this-&gt;</span></span>url(array('id' =&gt; $comment-&gt;user-&gt;id), 'user_route'); ?&gt;&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;title=&quot;Voir le profil de <span style="color: #009900;">&lt;?php echo $this-&gt;</span>escape($comment-&gt;user-&gt;login); ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&lt;?php echo $this-&gt;</span>escape($comment-&gt;user-&gt;login); ?&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-text&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php echo nl2br<span style="color: #66cc66;">&#40;</span>$this-&gt;</span>escape($comment-&gt;text)); ?&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-actions&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php if <span style="color: #66cc66;">&#40;</span>$this-&gt;</span>auth-&gt;isAllowed($this-&gt;currentUser, $this-&gt;video, 'comment')) : ?&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?php echo $this-&gt;</span></span>url(array('controller' =&gt; 'videos', 'action' =&gt; 'add-comment', 'id' =&gt; $this-&gt;video-&gt;id), 'default', true); ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Ajouter<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php endif; ?&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php if <span style="color: #66cc66;">&#40;</span>$this-&gt;</span>auth-&gt;isAllowed($this-&gt;currentUser, $comment, 'edit')) : ?&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?php echo $this-&gt;</span></span>url(array('controller' =&gt; 'videos', 'action' =&gt; 'edit-comment', 'id' =&gt; $comment-&gt;id), 'default', true); ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Editer<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php endif; ?&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;?php endforeach; ?&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span></div></div></div>

<p><strong>La version Twig</strong> :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">{# OVERRIDE #}<br />
<br />
{% headTitle video.title %}<br />
{% metaName 'description' with video.description|excerpt(200) %}<br />
{% javascript 'js/videos.js' %}<br />
<br />
{% holder 'title1' with video.title %}<br />
<br />
<br />
{# CONTENT #}<br />
<br />
{# Video owner action #}<br />
{% if currentUser is allowed(video, 'edit') %}<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;actions&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;{% route 'default' with ['controller': 'videos', 'action': 'edit', 'id': video.id] %}&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Editer<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;{% route 'default' with ['controller': 'videos', 'action': 'delete', 'id': video.id] %}&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Supprimer<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
{% endif %}<br />
<br />
{# Video object #}<br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;video&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;video-inner&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; {% hlp 'getVideoOject' with [video.code] %}<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<br />
{# Video details #}<br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;video-details&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;description&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; {{ video.description|nl2br }}<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;author&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;{% route 'user_route' with ['id': video.user.id] %}&quot;</span> <span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Voir le profil de {{ video.user.login }}&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{ video.user.login }}<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<br />
{# List of video comments #}<br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comments&quot;</span>&gt;</span><br />
&nbsp; &nbsp; {% for comment in comments %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-item&quot;</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-{{ comment.id }}&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-author&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;{% route 'user_route' with ['id': comment.user.id] %}&quot;</span> <span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Voir le profil de {{ comment.user.login }}&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{{ comment.user.login }}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-text&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{ comment.text|nl2br }}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-actions&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {% if currentUser is allowed(video, 'comment') %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;{% route 'default' with ['controller': 'video', 'action': 'add-comment', 'id': video.id] %}&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Ajouter<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {% endif %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {% if currentUser is allowed(comment, 'edit') %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;{% route 'default' with ['controller': 'video', 'action': 'edit-comment', 'id': comment.id] %}&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Editer<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {% endif %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; {% endfor %}<br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span></div></div></div>

<p><strong>Attention</strong></p>

<p>Dans cet exemple j&#8217;utilise certaines expressions (is allowed par ex.) que vous ne retrouverez pas dans le package Ano_ZFTwig. C&#8217;est une indication pour vous donner une idée de la syntaxe équivalente avec Twig. Ces fonctionnalités sont spécifiques, à vous de les implémenter.</p>

<p>Je suis conscient qu&#8217;il reste encore un peu de travail pour une intégration complète dans ZF, mais je vous laisse le soin d&#8217;ajouter vos propres briques à l&#8217;édifice, je ne doute pas que vous allez jouer avec les sources et les adapter selon vos besoins.</p>

<p>Au plaisir !</p>
<div class="shr-publisher-93"></div><img src="http://feeds.feedburner.com/~r/anonymation-blog-developpement-architecture-web/~4/49Oq0R1DJCU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code.anonymation.com/zend-framework/utiliser-twig-avec-zend-framework-1-1x/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://code.anonymation.com/zend-framework/utiliser-twig-avec-zend-framework-1-1x/</feedburner:origLink></item>
		<item>
		<title>Utiliser un moteur de template avec PHP, pourquoi ?</title>
		<link>http://feedproxy.google.com/~r/anonymation-blog-developpement-architecture-web/~3/cIao3ZPOLws/</link>
		<comments>http://code.anonymation.com/php5/utiliser-un-moteur-de-template-avec-php-pourquoi/#comments</comments>
		<pubDate>Tue, 23 Nov 2010 10:17:47 +0000</pubDate>
		<dc:creator>Benjamin Dulau</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[moteur de template]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[smarty]]></category>
		<category><![CDATA[twig]]></category>

		<guid isPermaLink="false">http://code.anonymation.com/?p=64</guid>
		<description><![CDATA[Pendant longtemps j&#8217;ai dénigré les moteurs de template comme Smarty &#38; Co. Tout simplement parce qu&#8217;en pesant les pours et les contres, les contres l&#8217;emportaient toujours. Le principal argument serait : &#171;&#160;PHP est lui même un moteur de rendu, pourquoi ajouter une couche supplémentaire pour faire exactement la même chose ?&#160;&#187;.

Premièrement, PHP a évolué, et même si son inventeur, Rasmus Lerdorf, l&#8217;a crée dans le but de dynamiser plus facilement son code HTML, le langage a depuis beaucoup changé. Il [...]]]></description>
			<content:encoded><![CDATA[<p>Pendant longtemps j&#8217;ai dénigré les moteurs de template comme Smarty &amp; Co. Tout simplement parce qu&#8217;en pesant les pours et les contres, les contres l&#8217;emportaient toujours. Le principal argument serait : &laquo;&nbsp;PHP est lui même un moteur de rendu, pourquoi ajouter une couche supplémentaire pour faire exactement la même chose ?&nbsp;&raquo;.</p>

<p>Premièrement, PHP a évolué, et même si son inventeur, Rasmus Lerdorf, l&#8217;a crée dans le but de dynamiser plus facilement son code HTML, le langage a depuis beaucoup changé. Il s&#8217;est professionnalisé, son modèle objet est devenu robuste, et avec la démocratisation des bonnes pratiques de développement web et notamment la séparation &laquo;&nbsp;of concerns&nbsp;&raquo; (qui peut me donner la bonne traduction ?), il est devenu bien plus qu&#8217;un simple moteur de rendu.</p>

<p>Ensuite, avec le recul et après avoir expérimenté pas mal de projets MVC dans lesquels la couche présentation (vues) est construite avec PHP, la question d&#8217;utiliser un moteur de templates revient naturellement.</p>

<p>Ce thème est sujet à débats, et vous ne serez certainement pas tous d&#8217;accord avec mes arguments, tout comme moi auparavant.
Je vais tenter de vous faire comprendre pourquoi je suis revenu sur mes positions.</p>

<h2>La preuve par l&#8217;exemple</h2>

<p>Pour vous aider à comprendre ce qui me fait changer d&#8217;avis, jetons un coup d&#8217;oeil au script de vue suivant :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;?php </span><br />
<span style="color: #009900;"><span style="color: #66cc66;">//</span> &lt;<a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;</span><br />
$this-&gt;headTitle($this-&gt;escape($this-&gt;video-&gt;title));<br />
<br />
$this-&gt;headMeta()-&gt;appendName('description', $this-&gt;excerpt($this-&gt;escape($this-&gt;video-&gt;description), 200, true));<br />
<br />
$this-&gt;headScript()-&gt;appendFile('videos.js');<br />
$this-&gt;placeholder('title1')-&gt;set($this-&gt;escape($this-&gt;video-&gt;title));<br />
?&gt;<br />
<br />
<span style="color: #009900;">&lt;?php <span style="color: #66cc66;">/</span>* Video owner <span style="color: #000066;">action</span> *<span style="color: #66cc66;">/</span> ?&gt;</span><br />
<span style="color: #009900;">&lt;?php if <span style="color: #66cc66;">&#40;</span>$this-&gt;</span>auth-&gt;isAllowed($this-&gt;currentUser, $this-&gt;video, 'edit')) : ?&gt;<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;actions&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?php echo $this-&gt;</span></span>url(array('controller' =&gt; 'videos', 'action' =&gt; 'edit', 'id' =&gt; $this-&gt;video-&gt;id), 'default'); ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Editer<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?php echo $this-&gt;</span></span>url(array('controller' =&gt; 'videos', 'action' =&gt; 'delete', 'id' =&gt; $this-&gt;video-&gt;id), 'default'); ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Supprimer<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;?php endif; ?&gt;</span><br />
<br />
<span style="color: #009900;">&lt;?php <span style="color: #66cc66;">/</span>* Video &lt;<a href="http://december.com/html/4/element/object.html"><span style="color: #000000; font-weight: bold;">object</span></a>&gt;</span> */ ?&gt;<br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;video&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;video-inner&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php echo $this-&gt;</span>getVideoObject($this-&gt;video-&gt;code); ?&gt;<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<br />
<span style="color: #009900;">&lt;?php <span style="color: #66cc66;">/</span>* Video details *<span style="color: #66cc66;">/</span> ?&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;video-details&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;description&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php echo nl2br<span style="color: #66cc66;">&#40;</span>$this-&gt;</span>escape($this-&gt;video-&gt;description)); ?&gt;<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;author&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?php echo $this-&gt;</span></span>url(array('id' =&gt; $this-&gt;video-&gt;user-&gt;id), 'user_route'); ?&gt;&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;title=&quot;Voir le profil de <span style="color: #009900;">&lt;?php echo $this-&gt;</span>escape($this-&gt;video-&gt;user-&gt;login); ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&lt;?php echo $this-&gt;</span>escape($this-&gt;video-&gt;user-&gt;login); ?&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<br />
<span style="color: #009900;">&lt;?php <span style="color: #66cc66;">/</span>* List of video comments *<span style="color: #66cc66;">/</span> ?&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comments&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;?php foreach<span style="color: #66cc66;">&#40;</span>$this-&gt;</span>comments as $comment) : ?&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-item&quot;</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-&lt;?php echo $comment-&gt;</span></span>id; ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-author&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?php echo $this-&gt;</span></span>url(array('id' =&gt; $comment-&gt;user-&gt;id), 'user_route'); ?&gt;&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;title=&quot;Voir le profil de <span style="color: #009900;">&lt;?php echo $this-&gt;</span>escape($comment-&gt;user-&gt;login); ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&lt;?php echo $this-&gt;</span>escape($comment-&gt;user-&gt;login); ?&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-text&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php echo nl2br<span style="color: #66cc66;">&#40;</span>$this-&gt;</span>escape($comment-&gt;text)); ?&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;comment-actions&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php if <span style="color: #66cc66;">&#40;</span>$this-&gt;</span>auth-&gt;isAllowed($this-&gt;currentUser, $this-&gt;video, 'comment')) : ?&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?php echo $this-&gt;</span></span>url(array('controller' =&gt; 'videos', 'action' =&gt; 'add-comment', 'id' =&gt; $this-&gt;video-&gt;id), 'default', true); ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Ajouter<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php endif; ?&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php if <span style="color: #66cc66;">&#40;</span>$this-&gt;</span>auth-&gt;isAllowed($this-&gt;currentUser, $comment, 'edit')) : ?&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?php echo $this-&gt;</span></span>url(array('controller' =&gt; 'videos', 'action' =&gt; 'edit-comment', 'id' =&gt; $comment-&gt;id), 'default', true); ?&gt;&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Editer<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;?php endif; ?&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;?php endforeach; ?&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span></div></div></div>

<p>Vous l&#8217;aurez compris, il s&#8217;agit d&#8217;une vue qui affiche une vidéo d&#8217;un utilisateur, avec ses commentaires.
L&#8217;exemple est simplifié, pas de traductions, pas d&#8217;avatars pour les auteurs, pas de partials, etc. Et ici je ne parle même pas du layout.</p>

<p>Osez me dire que c&#8217;est facile à maintenir ! :p</p>

<p>Des $this et des &lt; ?php echo &#8230; ?>, mangez-en&#8230;</p>

<p>Sur un de nos projets, nous nous sommes finalement perdus et c&#8217;est devenu très difficile de maintenir la couche présentation du site.</p>

<p>De plus, lors de l&#8217;intégration, nous sommes souvent tentés de faire du traitement dans les vues, chose à éviter, la vue affiche les données et c&#8217;est tout, il ne faut pas mélanger les responsabilités de chaque couche de l&#8217;application. Un moteur de templates aide à résoudre ce problème.</p>

<h2>Les avantages d&#8217;un moteur de templates</h2>

<p>Les avantages apportés par un moteur de templates tel que Twig sont simples :</p>

<h3>Une syntaxe propre et condensée dédiée au design (réutisabilité)</h3>

<p>Les intégrateurs peuvent se concentrer sur un langage et une syntaxe qui à priori ne changeront pas, contrairement à PHP qui évolue (dépréciation de fonctions par exemple).</p>

<p>Que dire de plus sur ce point, c&#8217;est aussi une histoire de goût.</p>

<h3>Un code HTML beaucoup plus lisible</h3>

<p>Ceci est indéniable, le code HTML devient beaucoup plus lisible, si le moteur de templates est maitrisé il y aura moins de chance de se perdre dans le code.</p>

<p>Ce point est facile à défendre mathématiquement. Pour afficher une variable de manière sécurisée avec PHP et Zend Framework, il faut compter au moins 36 caractères, sans compter le nom de la variable en elle-même et en supposant que nous n&#8217;accédons pas une propriété d&#8217;un objet ou une valeur de tableau.</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">escape</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">foo</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></div></div></div>

<p>Avec un moteur tel que Twig :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">{{ foo }}</div></div></div>

<p>Quelque chose à ajouter ?</p>

<h3>Interdir du traitement dans les vues</h3>

<p>Ce point est crucial et reste pour moi un des avantages les plus importants.
Impossible (en théorie) de s&#8217;enfoncer dans un code alambiqué dans lequel nous finirons par nous perdre.</p>

<h3>Sécurité</h3>

<p>Certains me diront que c&#8217;est au développeur de faire attention et que celui qui oublie d&#8217;échapper une variable avant de l&#8217;afficher mériterait une sanction pire que la mort. Je suis plus ou moins d&#8217;accord (mais je suis ok sur la sanction <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).</p>

<p>C&#8217;est très facile dans la jungle PHP d&#8217;une vue d&#8217;oublier un &laquo;&nbsp;escape&nbsp;&raquo; ou pire, sans framework, le très verbeux &laquo;&nbsp;htmlspecialchars(&#8230;.)&nbsp;&raquo;. Ça arrive au meilleur d&#8217;entre nous.</p>

<p>Dans la plupart des moteurs de templates il est possible d&#8217;activer un échappement automatique des variables et une intervention n&#8217;est nécessaire que si nous  ne souhaitons pas échapper une expression, ce qui est quand même relativement rare. Fonctionner dans ce sens est donc logique, et nous n&#8217;avons plus besoin de nous soucier de ça. Sans parler de la lisibilité qui est largement accrue.</p>

<p>Je sais que dans le cas de Javascript il faut faire très attention à l&#8217;échappement des tags, mais quand bien même, c&#8217;est toujours mieux que de devoir systématiquement tout échapper à la main.</p>

<p>Dans un monde parfait, j&#8217;ajouterai à cette liste l’interopérabilité entre langages/framework, mais ça insinuerait une syntaxe universelle et un portage du moteur vers les différents langages, c&#8217;est toujours bon de rêver <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<h2>Les inconvénients d&#8217;un moteur de templates</h2>

<p>Bien entendu, rien ne vient sans son lot de problèmes <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p>Voici les inconvénients majeurs d&#8217;un moteur de templates :</p>

<h3>Coloration syntaxique dans les IDE</h3>

<p>A moins que le moteur de templates soit suffisamment réputé pour bénéficier d&#8217;un plugin pour votre IDE, il ne faudra pas espérer avoir une coloration syntaxique (à moins de le faire soi-même), ce qui peut être frustrant.</p>

<h3>Chute de performances. Pour certains moteurs c&#8217;est même épouvantable.</h3>

<p>Les performances de l&#8217;application sont inévitablement touchées. Il faut parser et compiler le template en PHP, ce qui demande un certain temps.
Parfois, certains moteurs pourtant assez pauvres en fonctionnalités sont une véritable catastrophe en terme de performances. Il faut donc faire très attention à ça au moment de choisir son moteur de templates.</p>

<p>Pour pallier à ce problème, des moteurs comme Twig ou Smarty permettent de mettre en cache le résultat de la compilation PHP des templates. Mais pour Smarty par exemple, ce n&#8217;est pas suffisant, le moteur étant devenu une véritable usine à gaz, les performances sont assez médiocres.</p>

<h3>Un manque de fonctionnalités frustrant et dangereux</h3>

<p>Parfois, les moteurs ne proposent pas de solutions pour obtenir ce qu&#8217;on veut, ce qui poussent à utiliser PHP quand même par des feintes pas très jolies jolies (qui se reconnait ? :p).</p>

<h3>Difficile de parser/débugger un template</h3>

<p>Autre point qui peut en rebuter certains. Il devient plus difficile de débugger un template. Le moteur doit soit intégrer sont propre débuggueur, soit il faut aller débugger manuellement le résultat des compilations dans le cache, je n&#8217;en dis pas plus, vous comprendrez la lourdeur de la manipulation.</p>

<p>Il devient également difficile de parser les fichiers. Dans le cas d&#8217;une internationalisation avec gettext par exemple. Mais ce problème n&#8217;est pas sans solution.</p>

<h3>Casse la structure (x)HTML</h3>

<p>Dans certains cas, les moteurs de templates cassent la structure du (x)HTML. Un exemple parfait :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/table.html"><span style="color: #000000; font-weight: bold;">table</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/thead.html"><span style="color: #000000; font-weight: bold;">thead</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">tr</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/th.html"><span style="color: #000000; font-weight: bold;">th</span></a>&gt;</span>Nom<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/th.html"><span style="color: #000000; font-weight: bold;">th</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/th.html"><span style="color: #000000; font-weight: bold;">th</span></a>&gt;</span>Prénom<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/th.html"><span style="color: #000000; font-weight: bold;">th</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">tr</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/thead.html"><span style="color: #000000; font-weight: bold;">thead</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/tbody.html"><span style="color: #000000; font-weight: bold;">tbody</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; {% for user in users %}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">tr</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">td</span></a>&gt;</span>{{ user.name }}<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">td</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">td</span></a>&gt;</span>{{ user.firstname }}<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">td</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">tr</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; {% endfor %}<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/tbody.html"><span style="color: #000000; font-weight: bold;">tbody</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/table.html"><span style="color: #000000; font-weight: bold;">table</span></a>&gt;</span></div></div></div>

<p>Alors qu&#8217;en (x)HTML le W3C recommande que rien ne doit être présent entre les tags tbody et tr.</p>

<p>Je dirais tout simplement que c&#8217;est un faux problème étant donné qu&#8217;il existe aussi si on utilise PHP comme moteur de rendu.</p>

<h3>Difficile d&#8217;insérer du Javascript</h3>

<h2>Conclusion</h2>

<p>En étant pragmatique :</p>

<ul>
<li>avantages : 4</li>
<li>inconvénients : 6</li>
</ul>

<p>6 > 4, il ne faut donc pas utiliser un moteur de templates.</p>

<p>Non, je n&#8217;oserai pas. D&#8217;une part parce que je ne suis pas certain d&#8217;avoir cité tous les avantages et les inconvénients. D&#8217;autre part parce qu&#8217;il y a les puristes, les grand défenseurs de PHP ou de Smarty, et j&#8217;en passe.</p>

<p>Sachez seulement que je me suis finalement laissé séduire. Les raisons sont finalement simples, une maintenance du code beaucoup plus facile et l&#8217;arrivée de nouveaux moteurs de templates qui offrent un excellent rapport fonctionnalités/performances.</p>

<p>Le dernier en date qui m&#8217;a convaincu : <a href="http://www.twig-project.org/" title="TWIG The flexible, fast, and secure template language for PHP">Twig</a>.</p>

<p>Je vous propose d&#8217;ailleurs une intégration de Twig avec Zend Framework 1.1x dans l&#8217;article :
<a href="http://code.anonymation.com/zend-framework/utiliser-twig-avec-zend-framework-1-1x/" title="">Utiliser Twig avec Zend Framework 1.1x</a></p>
<div class="shr-publisher-64"></div><img src="http://feeds.feedburner.com/~r/anonymation-blog-developpement-architecture-web/~4/cIao3ZPOLws" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code.anonymation.com/php5/utiliser-un-moteur-de-template-avec-php-pourquoi/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://code.anonymation.com/php5/utiliser-un-moteur-de-template-avec-php-pourquoi/</feedburner:origLink></item>
		<item>
		<title>Aide de vue Mkurl : simplifier l’assemblage des urls</title>
		<link>http://feedproxy.google.com/~r/anonymation-blog-developpement-architecture-web/~3/b0LyPCV8kxg/</link>
		<comments>http://code.anonymation.com/zend-framework/aide-de-vue-mkurl-simplifier-lassemblage-des-urls/#comments</comments>
		<pubDate>Fri, 29 Oct 2010 08:19:34 +0000</pubDate>
		<dc:creator>Benjamin Dulau</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[aide de vue]]></category>
		<category><![CDATA[phtml]]></category>
		<category><![CDATA[url]]></category>
		<category><![CDATA[view helper]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://code.anonymation.com/?p=52</guid>
		<description><![CDATA[Un billet très court pour vous proposer une alternative à l&#8217;aide de vue url livrée avec Zend Framework.

Utiliser PHP comme moteur de template est une bonne chose mais implique une légère complexité du code dans les vues. Du $this, du escape, des array et j&#8217;en passe, certains morceaux de code deviennent très pénibles à lire et polluent le html.

Aujourd&#8217;hui nous nous intéressons à l&#8217;aide de vue url, dont la syntaxe est :

 $this-&#62;url&#40;array&#40;
&#160; &#160; 'module' =&#62; 'mon-module',
&#160; &#160; 'controller' =&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>Un billet très court pour vous proposer une alternative à l&#8217;aide de vue <em><strong>url</strong></em> livrée avec Zend Framework.</p>

<p>Utiliser PHP comme moteur de template est une bonne chose mais implique une légère complexité du code dans les vues. Du <em>$this</em>, du <em>escape</em>, des array et j&#8217;en passe, certains morceaux de code deviennent très pénibles à lire et polluent le html.</p>

<p>Aujourd&#8217;hui nous nous intéressons à l&#8217;aide de vue url, dont la syntaxe est :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">url</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><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'module'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'mon-module'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'controller'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'mon-controller'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'action'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'mon-action'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'param1'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'val1'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'param2'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'val2'</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'ma-route'</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></div></div></div>

<p>Ce qui intégré donne :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">url</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><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'module'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'mon-module'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'controller'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'mon-controller'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'action'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'mon-action'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'param1'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'val1'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'param2'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'val2'</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'ma-route'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; title=&quot;&quot;&gt;Le lien de la mort&lt;/a&gt;</div></div></div>

<p>Je pense que ça se passe de commentaires, tout ça devient très vite un véritable foutoir.</p>

<p>La syntaxe avec les routes et les paramètres par défaut peut être raccourcie :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">url</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><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'param1'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'val1'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'param2'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'val2'</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'ma-route'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; title=&quot;&quot;&gt;Le lien de la mort moins violente&lt;/a&gt;</div></div></div>

<p>Mais ce n&#8217;est pas encore idéal.</p>

<h2>Utiliser un pattern pour composer les URLs</h2>

<p>Je vous propose une aide de vue qui va générer les URLs en fonction d&#8217;un pattern inspiré de l&#8217;aide de symfony premier du nom et qui permet de transformer les exemples ci-dessus en :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mkurl</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'mon-module/mon-controller/mon-action?param1=val1&amp;param2=val2'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; title=&quot;&quot;&gt;Le lien moins mortel&lt;/a&gt;<br />
<br />
&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mkurl</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'@ma-route?param1=val1&amp;param2=val2'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; title=&quot;&quot;&gt;Le lien encore moins mortel&lt;/a&gt;</div></div></div>

<p>Pour ce qui est du code, j&#8217;avoue ne pas avoir regardé la source dans symfony 1.x qui est peut-être meilleure, mais voilà le code :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
<span style="color: #009933; font-style: italic;">/** Zend_View_Helper_Abstract.php */</span><br />
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'Zend/View/Helper/Abstract.php'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #009933; font-style: italic;">/**<br />
&nbsp;* Helper for making easy links and getting urls that depend on the routes and router<br />
&nbsp;*<br />
&nbsp;* @package &nbsp; &nbsp;Tight_View<br />
&nbsp;* @subpackage Helper<br />
&nbsp;* @author &nbsp; &nbsp; Benjamin Dulau<br />
&nbsp;*/</span><br />
<span style="color: #000000; font-weight: bold;">class</span> Tight_View_Helper_Mkurl <span style="color: #000000; font-weight: bold;">extends</span> Zend_View_Helper_Abstract<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #009933; font-style: italic;">/**<br />
&nbsp; &nbsp; &nbsp;* Generates an url from a string pattern<br />
&nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp;* @access public<br />
&nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp;* @param &nbsp;array $urlPattern String pattern for url<br />
&nbsp; &nbsp; &nbsp;* @param &nbsp;bool &nbsp;$reset &nbsp; &nbsp; &nbsp;Whether or not to reset the route defaults with those provided<br />
&nbsp; &nbsp; &nbsp;* @param &nbsp;bool &nbsp;$encode &nbsp; &nbsp; Whether or not to encode the url<br />
&nbsp; &nbsp; &nbsp;* @return string Url for the link href attribute.<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> mkurl<span style="color: #009900;">&#40;</span><span style="color: #000088;">$urlPattern</span><span style="color: #339933;">,</span> <span style="color: #000088;">$reset</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #000088;">$encode</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$module</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$controller</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$action</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$routeName</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'default'</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$urlParts</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/explode"><span style="color: #990000;">explode</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$urlPattern</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$route</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>string<span style="color: #009900;">&#41;</span><span style="color: #000088;">$urlParts</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$queryString</span> <span style="color: #339933;">=</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;">$urlParts</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$urlParts</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</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><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// if starts with @ =&gt; route name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/empty"><span style="color: #990000;">empty</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$route</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$route</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'@'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$routeName</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/mb_substr"><span style="color: #990000;">mb_substr</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$route</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span> <span style="color: #666666; font-style: italic;">// else standard &quot;:module/:controller/:action&quot; fragments</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mca</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/explode"><span style="color: #990000;">explode</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$route</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// shift starting '/' if present</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/empty"><span style="color: #990000;">empty</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mca</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/array_shift"><span style="color: #990000;">array_shift</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mca</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/count"><span style="color: #990000;">count</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mca</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">case</span> <span style="color: #cc66cc;">3</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// :module/:controller/:action</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$module</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$mca</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$controller</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$mca</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$action</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$mca</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">case</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// :controller/:action</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$controller</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$mca</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$action</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$mca</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">case</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// :controller/index</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$controller</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$mca</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$action</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'index'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">default</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> InvalidArgumentException<span style="color: #009900;">&#40;</span><a href="http://www.php.net/sprintf"><span style="color: #990000;">sprintf</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Mkurl helper =&gt; Invalid URL pattern. The URL pattern must be formatted like as :module/:controller/:action?params, :controller/:action?params, or :controller?params (&quot;%s&quot; given).'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$urlPattern</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$urlOptions</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><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/empty"><span style="color: #990000;">empty</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$module</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$urlOptions</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'module'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$module</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/empty"><span style="color: #990000;">empty</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$controller</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$urlOptions</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'controller'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$controller</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/empty"><span style="color: #990000;">empty</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$action</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$urlOptions</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'action'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$action</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> &nbsp; &nbsp; &nbsp; &nbsp;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><a href="http://www.php.net/empty"><span style="color: #990000;">empty</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$queryString</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$matched</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/preg_match_all"><span style="color: #990000;">preg_match_all</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'@([^&amp;=]+)=(.*?)(?:(?=&amp;[^&amp;=]+=) | $)@x'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$queryString</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #339933;">,</span> PREG_SET_ORDER <span style="color: #339933;">|</span> PREG_OFFSET_CAPTURE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$match</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$urlOptions</span><span style="color: #009900;">&#91;</span> <a href="http://www.php.net/urldecode"><span style="color: #990000;">urldecode</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/urldecode"><span style="color: #990000;">urldecode</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$match</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$router</span> <span style="color: #339933;">=</span> Zend_Controller_Front<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRouter</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$router</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assemble</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$urlOptions</span><span style="color: #339933;">,</span> <span style="color: #000088;">$routeName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$reset</span><span style="color: #339933;">,</span> <span style="color: #000088;">$encode</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div></div>

<p>Ce fichier est à placer dans votre dossier &laquo;&nbsp;library&nbsp;&raquo; (ou autre nom), et vous devez ajouter le namespace dans le fichier de config. <em>application.ini</em> :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container ini default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ini codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">resources.view.helperPath.Tight_View_Helper_ <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;Tight/View/Helper&quot;</span></div></div></div>

<p>Rien ne vous empêche de l&#8217;améliorer si nécessaire (même dans les commentaires :p).</p>

<h2>Utilisation</h2>

<h3>URLs &laquo;&nbsp;standards&nbsp;&raquo;</h3>

<p>Comme vous pouvez le voir dans le code, j&#8217;ai décidé de 3 cas d&#8217;utilisation :</p>

<h4>/:module/:controller/:action/*</h4>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mkurl</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/mon-module/mon-controleur/mon-action?param1=val1'</span><span style="color: #009900;">&#41;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; title=&quot;Mon super lien&quot;&gt;<br />
&nbsp; &nbsp; Super lien<br />
&lt;/a&gt;</div></div></div>

<h4>/:controller/:action/*</h4>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mkurl</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/mon-controleur/mon-action?param1=val1'</span><span style="color: #009900;">&#41;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; title=&quot;Mon super lien&quot;&gt;<br />
&nbsp; &nbsp; Super lien<br />
&lt;/a&gt;</div></div></div>

<p>Le module par défaut sera utilisé.</p>

<h4>/:controller/*</h4>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mkurl</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/mon-controleur?param1=val1'</span><span style="color: #009900;">&#41;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; title=&quot;Mon super lien&quot;&gt;<br />
&nbsp; &nbsp; Super lien<br />
&lt;/a&gt;</div></div></div>

<p>Le module par défaut et l&#8217;action <em>index</em> seront utilisés.</p>

<h3>Avec une route</h3>

<p>Imaginons la route suivante :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container ini default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ini codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">resources.router.routes.photos.route <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;/photos/:s/:t&quot;</span><br />
resources.router.routes.photos.defaults.module <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> front</span><br />
resources.router.routes.photos.defaults.controller <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> photos</span><br />
resources.router.routes.photos.defaults.action <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> index</span><br />
resources.router.routes.photos.defaults.s <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> last</span><br />
resources.router.routes.photos.defaults.t <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> all-period</span><br />
resources.router.routes.photos.reqs.s <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;^(last|most-popular|most-viewed|top-rated|most-commented)$&quot;</span><br />
resources.router.routes.photos.reqs.t <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;^(all-period|today|week|month)$&quot;</span></div></div></div>

<p>Pour obtenir la route par défaut, tout simplement :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mkurl</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'@photos'</span><span style="color: #009900;">&#41;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; title=&quot;Voir toutes les photos&quot;&gt;<br />
&nbsp; &nbsp; Toutes les photos<br />
&lt;/a&gt;</div></div></div>

<p>Avec des paramètres :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mkurl</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'@photos?s=most-popular&amp;t=today'</span><span style="color: #009900;">&#41;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; title=&quot;Voir les photos les plus populaires aujourd'hui&quot;&gt;<br />
&nbsp; &nbsp; Les plus populaires - aujourd'hui<br />
&lt;/a&gt;</div></div></div>

<p>Il est possible aussi (heureusement) de pouvoir redéfinir les module/action/contrôleur :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mkurl</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'@photos?action=mon-action&amp;s=most-popular&amp;t=today'</span><span style="color: #009900;">&#41;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; title=&quot;Voir les photos les plus populaires aujourd'hui&quot;&gt;<br />
&nbsp; &nbsp; Les plus populaires - aujourd'hui<br />
&lt;/a&gt;</div></div></div>
<div class="shr-publisher-52"></div><img src="http://feeds.feedburner.com/~r/anonymation-blog-developpement-architecture-web/~4/b0LyPCV8kxg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code.anonymation.com/zend-framework/aide-de-vue-mkurl-simplifier-lassemblage-des-urls/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code.anonymation.com/zend-framework/aide-de-vue-mkurl-simplifier-lassemblage-des-urls/</feedburner:origLink></item>
		<item>
		<title>Les aides d’action (helpers), factorisation, avoir le réflexe</title>
		<link>http://feedproxy.google.com/~r/anonymation-blog-developpement-architecture-web/~3/2OG9xRQ5Jh4/</link>
		<comments>http://code.anonymation.com/zend-framework/les-aides-daction-helpers-factorisation-avoir-le-reflexe/#comments</comments>
		<pubDate>Fri, 22 Oct 2010 13:06:24 +0000</pubDate>
		<dc:creator>Benjamin Dulau</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[action helpers]]></category>
		<category><![CDATA[aides d'action]]></category>
		<category><![CDATA[helpers]]></category>

		<guid isPermaLink="false">http://code.anonymation.com/?p=18</guid>
		<description><![CDATA[S&#8217;il y a une chose agaçante en programmation, c&#8217;est bien de répéter des dizaines de fois le même morceau de code, la même condition dans chaque méthode, qui ne le fait pas ?

Le modèle de conception MVC impose une certaine granularité des différentes &#171;&#160;actions&#160;&#187; assurées par l&#8217;application. Chaque contrôleur possèdent un certain nombre d&#8217;actions possédant chacune un rôle bien défini (le plus souvent un cas d&#8217;utilisation).

Plus le nombre d&#8217;actions se multiplie, plus la redondance de code devient inévitable.

Le premier réflexe [...]]]></description>
			<content:encoded><![CDATA[<p>S&#8217;il y a une chose agaçante en programmation, c&#8217;est bien de répéter des dizaines de fois le même morceau de code, la même condition dans chaque méthode, qui ne le fait pas ?</p>

<p>Le modèle de conception MVC impose une certaine granularité des différentes &laquo;&nbsp;actions&nbsp;&raquo; assurées par l&#8217;application. Chaque contrôleur possèdent un certain nombre d&#8217;actions possédant chacune un rôle bien défini (le plus souvent un cas d&#8217;utilisation).</p>

<p>Plus le nombre d&#8217;actions se multiplie, plus la redondance de code devient inévitable.</p>

<p>Le premier réflexe pour un bon développeur orienté objets qui se respecte, sera de créer des super-classes de contrôleur et d&#8217;user de l&#8217;héritage pour factoriser le code. Mais l&#8217;héritage ne répond pas à tous les problèmes.</p>

<p>Ce n&#8217;est parfois pas très flexible dans le sens où chaque contrôleur n&#8217;a pas forcément besoin des mêmes fonctionnalités, alors que tous possèdent un pan commun. Dans ce cas là, vous vous retrouvez à créer plusieurs super-classes pour chaque groupe de fonctionnalités mais dans lesquelles vous répétez finalement du code commun à chaque super-classe.</p>

<p>Que faire alors ? Créer encore une super-classe et se retrouver avec un nivelage d&#8217;héritage important qui complexifie la compréhension du code et devient difficile à maintenir ? Non <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<h2>Les aides d&#8217;action ou helpers, mangez-en !</h2>

<p>Les aides d&#8217;action répondent exactement à cette problématique. Ce sont des plugins (ne pas confondre avec les plugins de contrôleurs !) qui permettent d&#8217;ajouter des fonctionnalités aux contrôleurs d&#8217;actions sans avoir à étendre de classe. Ils peuvent soit être injectés automatiquement, soit à la demande du développeur, dixit la documentation du ZF : <a href="http://framework.zend.com/manual/fr/zend.controller.actionhelpers.html" title="">Aides d&#8217;actions (Helper)</a>.</p>

<p>Mais lorsqu&#8217;on débute dans l&#8217;utilisation d&#8217;un framework tel que Zend Framework, l&#8217;utilisation de tels mécanismes n&#8217;est pas innée, loin de là. Et pourtant, le ZF regorge de fonctionnalités variées qui facilitent le développement et l&#8217;organisation du code, ce serait dommage de s&#8217;en priver. Je vous encourage donc à vous forcer à utiliser les aides d&#8217;actions jusqu&#8217;à ce que ça devienne un réflexe.</p>

<h2>Automatiser l&#8217;exécution d&#8217;un helper (hooks)</h2>

<p>Les aides d&#8217;actions peuvent soit être invoquées à la demande, soit intervenir automatiquement à des moments clés du processus de dispatch des contrôleurs d&#8217;action.</p>

<p>Pour ça, il existe trois méthodes (hooks) :</p>

<ul>
<li><em><strong>init()</strong></em> : invoquée automatiquement au moment de l&#8217;initialisation du contrôleur d&#8217;actions.</li>
<li><em><strong>preDispatch()</strong></em> : invoquée juste avant la routine preDispatch() du contrôleur d&#8217;actions.</li>
<li><em><strong>postDispath()</strong></em> : invoquée juste après le postDispatch() du contrôleur.</li>
</ul>

<p>Ces trois méthodes sont invoquées automatiquement pour chaque aide d&#8217;action enregistrée, il est donc important de bien choisir à quel moment un helper doit intervenir dans le processus.</p>

<h2>Exemple (simple): Restreindre les actions à un verbe HTTP</h2>

<p>Le champ d&#8217;application des aides d&#8217;action est très varié, il peut s&#8217;agir aussi bien d&#8217;une fonctionnalité basique ne nécessitant que quelques lignes de code que de l&#8217;implémentation d&#8217;une logique complexe. Je ne vais donc pas m&#8217;enfoncer dans un exemple trop compliqué et plutôt vous montrer un cas typique d&#8217;utilisation qui peut vous faciliter la vie, à vous et votre imagination de faire le reste <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p>Qui n&#8217;a jamais utilisé cette ligne de code dans une action de contrôleur ?</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isPost</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><br />
&nbsp; &nbsp; <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Controller_Action_Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Bad request method'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">405</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
<span style="color: #009900;">&#125;</span></div></div></div>

<p>Dans de gros projets, c&#8217;est typiquement un morceau de code qui sera répété des dizaines de fois, parfois plusieurs fois dans le même contrôleur. Pourquoi ne pas utiliser une aide d&#8217;action similaire au <a href="http://framework.zend.com/manual/fr/zend.controller.actionhelpers.html#zend.controller.actionhelpers.contextswitch" title="">context switcher</a> qui permettrait de déclarer un simple attribut dans le contrôleur, exemple :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$httpContexts</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><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'mon-action'</span> <span style="color: #339933;">=&gt;</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;">'post'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'autre-action'</span> <span style="color: #339933;">=&gt;</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;">'get'</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div></div>

<p>Voilà le code du helper, dans lequel vous remarquerez, que fainéant comme je suis, j&#8217;ai copié/collé pas mal de code d&#8217;un helper déjà existant dans le ZF <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
<span style="color: #009933; font-style: italic;">/**<br />
&nbsp;* Simplify http verb verification<br />
&nbsp;*<br />
&nbsp;* @uses &nbsp; &nbsp; &nbsp; Zend_Controller_Action_Helper_Abstract<br />
&nbsp;* @category &nbsp; Tight<br />
&nbsp;* @package &nbsp; &nbsp;Tight_Controller<br />
&nbsp;*/</span><br />
<span style="color: #000000; font-weight: bold;">class</span> Tight_Controller_Action_Helper_HttpContext <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Action_Helper_Abstract<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #009933; font-style: italic;">/**<br />
&nbsp; &nbsp; &nbsp;* Supported contexts<br />
&nbsp; &nbsp; &nbsp;* @var array<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$_httpContexts</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><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #009933; font-style: italic;">/**<br />
&nbsp; &nbsp; &nbsp;* Controller property key to utilize for context<br />
&nbsp; &nbsp; &nbsp;* @var string<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$_httpContextKey</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'httpContexts'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #009933; font-style: italic;">/**<br />
&nbsp; &nbsp; &nbsp;* Initialize context detection<br />
&nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp;* @throws Zend_Controller_Action_Exception<br />
&nbsp; &nbsp; &nbsp;* @return void<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> preDispatch<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$controller</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getActionController</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$request</span> &nbsp; &nbsp;<span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$action</span> &nbsp; &nbsp; <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getActionName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Return if no context are defined</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$httpContexts</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getActionHttpContexts</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$action</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/empty"><span style="color: #990000;">empty</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$httpContexts</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$currentContext</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMethod</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Check if http context allowed by action controller</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasActionHttpContext</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$action</span><span style="color: #339933;">,</span> <span style="color: #000088;">$currentContext</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Controller_Action_Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Bad request method'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">405</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #009933; font-style: italic;">/**<br />
&nbsp; &nbsp; &nbsp;* Does a particular controller action have the given context(s)?<br />
&nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp;* @param &nbsp;string &nbsp; &nbsp; &nbsp; $action<br />
&nbsp; &nbsp; &nbsp;* @param &nbsp;string|array $context<br />
&nbsp; &nbsp; &nbsp;* @throws Zend_Controller_Action_Exception<br />
&nbsp; &nbsp; &nbsp;* @return boolean<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> hasActionHttpContext<span style="color: #009900;">&#40;</span><span style="color: #000088;">$action</span><span style="color: #339933;">,</span> <span style="color: #000088;">$httpContext</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$controller</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getActionController</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$action</span> &nbsp; &nbsp; <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>string<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$action</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$httpContextKey</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_httpContextKey<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$allContexts</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$controller</span><span style="color: #339933;">-&gt;</span><span style="color: #009900;">&#123;</span><span style="color: #000088;">$httpContextKey</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</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;">$allContexts</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$action</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$contexts</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$allContexts</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$action</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/in_array"><span style="color: #990000;">in_array</span></a><span style="color: #009900;">&#40;</span><a href="http://www.php.net/mb_strtolower"><span style="color: #990000;">mb_strtolower</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$httpContext</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$contexts</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #009933; font-style: italic;">/**<br />
&nbsp; &nbsp; &nbsp;* Get contexts for a given action or all actions in the controller<br />
&nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp;* @param &nbsp;string $action<br />
&nbsp; &nbsp; &nbsp;* @return array<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getActionHttpContexts<span style="color: #009900;">&#40;</span><span style="color: #000088;">$action</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$controller</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getActionController</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">null</span> <span style="color: #339933;">===</span> <span style="color: #000088;">$controller</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</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><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$action</span> &nbsp; &nbsp; <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>string<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$action</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$contextKey</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_httpContextKey<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</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;">$controller</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$contextKey</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</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><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">null</span> <span style="color: #339933;">!==</span> <span style="color: #000088;">$action</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <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;">$controller</span><span style="color: #339933;">-&gt;</span><span style="color: #009900;">&#123;</span><span style="color: #000088;">$contextKey</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$action</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$controller</span><span style="color: #339933;">-&gt;</span><span style="color: #009900;">&#123;</span><span style="color: #000088;">$contextKey</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$action</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</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><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$controller</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$contextKey</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div></div>

<p>Ici j&#8217;utilise le &laquo;&nbsp;hook&nbsp;&raquo; <em>preDispatch()</em> qui sera systématiquement invoqué pour chaque contrôleur d&#8217;action juste avant de dispatcher l&#8217;action. Attention de bien enregistrer l&#8217;aide dans le broker d&#8217;actions dans ce cas là.</p>

<p>Dans le bootstrap (par exemple) :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> _initHelpers<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; Zend_Controller_Action_HelperBroker<span style="color: #339933;">::</span><span style="color: #004000;">addHelper</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Tight_Controller_Action_Helper_HttpContext<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div></div>

<p>Avec ça, vous n&#8217;avez plus qu&#8217;à déclarer votre propriété <em><strong>$httpContexts</strong></em> dans le contrôleur et le tour est joué.</p>

<p>C&#8217;est un exemple tout bête, mais qui donne une bonne idée de l&#8217;utilité du mécanisme.</p>

<h2>Pattern Strategy</h2>

<p>Les aides d&#8217;actions dans le Zend Framework implémentent le pattern <a href="http://fr.wikipedia.org/wiki/Strat%C3%A9gie_(patron_de_conception)" title="">Strategy</a> sur le helper broker (gestionnaire d&#8217;aides d&#8217;action) qui permet ici d&#8217;invoquer directement une aide d&#8217;action comme s&#8217;il s&#8217;agissait d&#8217;une méthode du broker.</p>

<p>Il s&#8217;agit en fait d&#8217;utiliser la méthode clé <em><strong>direct()</strong></em> comme un proxy vers une méthode du helper. Ce mécanisme est utile dans le cas des aides d&#8217;action invoquées à la demande et permet de simplifier le code. Exemple avec l&#8217;aide d&#8217;action &laquo;&nbsp;redirector&nbsp;&raquo; inclue dans le ZF :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_helper<span style="color: #339933;">-&gt;</span><span style="color: #004000;">redirector</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'mon-action'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'mon-controller'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'mon-module'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// équivalent à</span><br />
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_helper<span style="color: #339933;">-&gt;</span><span style="color: #004000;">getHelper</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Redirector'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">gotoSimple</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'mon-action'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'mon-controller'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'mon-module'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div></div>

<p>Si nous jettons un coup d&#8217;oeil à la source du helper :</p>

<div class="codecolorer-master">    <div class="view-trigger"><a class="toggle" href="#" onclick="return false;"></a></div>    <div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #009933; font-style: italic;">/**<br />
&nbsp; &nbsp; &nbsp;* direct(): Perform helper when called as<br />
&nbsp; &nbsp; &nbsp;* $this-&gt;_helper-&gt;redirector($action, $controller, $module, $params)<br />
&nbsp; &nbsp; &nbsp;*<br />
&nbsp; &nbsp; &nbsp;* @param &nbsp;string $action<br />
&nbsp; &nbsp; &nbsp;* @param &nbsp;string $controller<br />
&nbsp; &nbsp; &nbsp;* @param &nbsp;string $module<br />
&nbsp; &nbsp; &nbsp;* @param &nbsp;array &nbsp;$params<br />
&nbsp; &nbsp; &nbsp;* @return void<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> direct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$action</span><span style="color: #339933;">,</span> <span style="color: #000088;">$controller</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$module</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a> <span style="color: #000088;">$params</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><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">gotoSimple</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$action</span><span style="color: #339933;">,</span> <span style="color: #000088;">$controller</span><span style="color: #339933;">,</span> <span style="color: #000088;">$module</span><span style="color: #339933;">,</span> <span style="color: #000088;">$params</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div></div>

<h2>D&#8217;autres exemples</h2>

<p>Voici quelques exemples courant d&#8217;aides d&#8217;action :</p>

<ul>
<li><a href="http://julien-pauli.developpez.com/tutoriels/zend-framework/atelier/aclmvc/#LV" title="">Automatiser le contrôle des ACL</a> &#8211; <em>Julien Pauli</em></li>
<li>Historique de navigation (session)</li>
<li>Vérifier qu&#8217;un utilisateur est authentifié</li>
<li>j&#8217;ai rien d&#8217;autre qui me vient, mais tout ce vous sera utile et qui justifie l&#8217;utilisation d&#8217;un helper.</li>
</ul>

<p>Et bien entendu tous les helpers inclus dans le framework que les développeurs oublient souvent d&#8217;utiliser <img src='http://code.anonymation.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<h2>Limitations &amp; Conclusion</h2>

<p>Comme toujours, un composant ne vient pas sans son lot de critiques que ce soit dans le design, l&#8217;implémentation du concept ou son utilisation.</p>

<p>Pour ma part, je trouve l&#8217;outil très utile et je serais idiot de m&#8217;en passer pour des considérations purement philosophiques. Le seul point, et pas des moindre, qui me limite dans son utilisation, sera la difficulté pour y injecter quoi que ce soit. Le chargement étant assuré par un gestionnaire (le broker) utilisé de manière statique, il est très difficile de pratiquer l&#8217;injection de dépendances dans les helpers. Le ZF n&#8217;est pas prévu pour fonctionner avec un conteneur de dépendances, ou du moins n&#8217;est pas toujours adapté pour ça.</p>

<p>Néanmoins, les aides d&#8217;actions restent utiles tant qu&#8217;elles ne nécessitent pas de dépendances. Je pense que les développeurs du ZF sont conscients de cette problématique et nous proposerons une implémentation plus flexible dans la version 2 du framework.</p>
<div class="shr-publisher-18"></div><img src="http://feeds.feedburner.com/~r/anonymation-blog-developpement-architecture-web/~4/2OG9xRQ5Jh4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code.anonymation.com/zend-framework/les-aides-daction-helpers-factorisation-avoir-le-reflexe/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code.anonymation.com/zend-framework/les-aides-daction-helpers-factorisation-avoir-le-reflexe/</feedburner:origLink></item>
	</channel>
</rss>

