<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Blog Symfony2 - Lexik Montpellier &#187; jQuery</title>
	<atom:link href="http://www.lexik.fr/blog/symfony/tag/jquery/feed" rel="self" type="application/rss+xml" />
	<link>http://www.lexik.fr/blog/symfony</link>
	<description>Blog sur le développement Web PHP avec Symfony 2</description>
	<lastBuildDate>Thu, 02 Feb 2012 14:00:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Astuces de développement javascript avec symfony</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/astuces-de-developpement-javascript-avec-symfony-1382</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/astuces-de-developpement-javascript-avec-symfony-1382#comments</comments>
		<pubDate>Mon, 17 Jan 2011 15:06:09 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[jQuery]]></category>

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

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

<p>Vous pourrez ainsi éditer votre code javascript depuis votre template PHP, bénéficier par exemple de valeurs dynamiques de PHP et pour autant que le code soit bien inclus en bas de page. Toutefois je vous recommande d&#8217;écrire du javascript là où il doit se trouver, à savoir dans un fichier JS&#8230;</p>
<p>De plus l&#8217;inconvénient majeur du slot est qu&#8217;il ne peut contenir qu&#8217;une valeur, il est écrasé à chaque utilisation. La technique fonctionne mais est très limitée. Pour ces besoins nous avons écrit chez Lexik un petit plugin &laquo;&nbsp;lxJavascript&nbsp;&raquo;, très similaire à l&#8217;utilisation d&#8217;un slot mais optimisé pour l&#8217;inclusion de javascripts. Il gère donc le multiple ajout, supprime les éventuelles multiples balises script pour en conserver qu&#8217;une seule, etc. Vous en saurez plus demain, le plugin sort en OpenSource sur le <a href="https://github.com/lexik" target="_blank">Github de Lexik</a>.</p>
<h4>2. Compression</h4>
<p>La compression des javascripts (c&#8217;est valable aussi pour les CSS) est une des tâches d&#8217;optimisations les plus importantes et également une des plus simples, du moins via les plugins symfony. Cette technique consiste à compresser tous vos fichiers javascript en 1 seul et surtout d&#8217;y appliquer un numéro de version (un timestamp le plus souvent) afin de prévenir des problèmes de cache dans vos mises à jour.</p>
<p>Les principaux plugins :</p>
<ul>
<li><a href="http://www.symfony-project.org/plugins/sfCombinePlugin" target="_blank">sfCombinePlugin</a>
<li><a href="http://www.symfony-project.org/plugins/npAssetsOptimizerPlugin" target="_blank">npAssetsOptimizerPlugin</a></li>
<li><a href="http://www.symfony-project.org/plugins/swCombinePlugin" target="_blank">swCombinePlugin</a></li>
</ul>
<p>Chez Lexik, nous utilisons <a href="http://www.symfony-project.org/plugins/npAssetsOptimizerPlugin" target="_blank">npAssetsOptimizerPlugin</a>, un plugin de <a href="http://www.akei.com/" target="_blank">Nicolas Perriault</a>, extrêmement simple à installer et paramétrer. Sur votre environnement de production, vous obtiendrez ainsi un fichier javascript compressé <code>/js/optimized.js?1294759429</code> qui contient un timestamp permettant à chaque modifications des fichiers d&#8217;être prises en compte sans problème de cache.</p>
<p>Nous n&#8217;appliquons pas la compression pour les librairies externes telles que jQuery que nous déléguons aux <a href="http://code.google.com/apis/libraries/devguide.html" target="_blank">serveurs CDN de Google</a>, cela apporte ces avantages notables :</p>
<ul>
<li>l&#8217;avantage du <abbr title="Content Delivery Network">CDN</abbr>, à savoir de proposer des données statiques via un réseau de multiples serveurs dans de multiples points géographiques, afin de permettre un accès très court ;</li>
<li>les navigateurs sont limités sur le nombre de connexions HTTP simultanées sur un même domaine, le téléchargement d&#8217;un javascript sur les serveurs de Google se fera en parallèle ;</li>
<li>les librairies du CDN ont les bonnes en-têtes de cache, par exemple la version 1.4.4 de jQuery restera en cache pendant 1 an sur le client, cela signifie également qu&#8217;un internaute peut bénéficier du cache téléchargé depuis un autre site, pas forcément sur le votre.</li>
</ul>
<h4>3. Accéder à certaines données dynamiques depuis javascript</h4>
<p>Il peut parfois être très utile depuis javascript d&#8217;accéder à certaines données dynamiques telles que la culture de l&#8217;utilisateur, du routing pour des appels Ajax ou encore de l&#8217;i18n. Il suffit de s&#8217;appuyer sur un simple fichier de configuration via un tableau de données JSON généré depuis une action symfony. J&#8217;ai écrit sur mon blog personnel un article détaillé sur le sujet <a href="http://blog.jeremybarthe.com/post/1465024153/configurations-javascript-dynamiques-en-symfony" target="_blank">Configurations Javascript dynamiques en Symfony</a>.</p>
<h4>4. Javascript depuis les widget</h4>
<p>Maintenant que vos inclusions de javascripts se trouvent en bas de page, jQuery par exemple, que faire de nos chers widgets jQuery Autocompleter <code>sfWidgetFormJQueryAutocompleter</code> et autre Datepicker <code>sfWidgetFormJQueryDate</code> qui retournent des champs de formulaire et le javascript d’initialisation du composant ? Eh bien, ne plus les utiliser&#8230; Simplement car ils seront inclus avant jQuery et vous aurez donc droit à l’erreur &laquo;&nbsp;jQuery is not defined&nbsp;&raquo;. Sans être aussi extrême, vous pouvez charger jQuery en haut de page (via les CDN de Google) et votre script compressé en bas de page, les widgets de formulaire seront alors à nouveau fonctionnels.</p>
<p>Cela fait déjà quelques temps que chez Lexik nous avons fait le choix d&#8217;enlever tous ces widgets pour les ré-écrire et les adapter à nos besoins. Les javascripts des widgets passent par notre plugin lxJavascript ce qui permet de les inclure là où on le souhaite. Egalement, le javascript retourné par ces widgets correspond à une utilisation basique du composant, dans un cas concrêt il est souvent nécessaire d&#8217;en ré-écrire une bonne part. Il peut être pratique par contre que le widget retourne seulement la sémantique HTML adaptée, par exemple dans le cas d&#8217;un Autocomplete un champ hidden pour stocker la valeur et un champ texte pour l&#8217;autocomplete, aussi nos widgets ont une option pour retourner ou non le code javascript.</p>
<h4>5. Optimisation frontend</h4>
<p>Presque aussi important que la compression, la configuration d&#8217;apache pour mettre en cache certains de vos fichiers statiques. Typiquement, maintenant que vos fichiers javascripts et CSS sont compressés en 1 seul et possèdent un timestamp unique par version, il serait dommage de les recharger à chaque chargement de page&#8230; Vous devez donc configurer le module Expires d&#8217;apache via le fichier de config du vhost ou via le .htaccess, en voici un exemple :</p>
<pre>
<IfModule mod_expires.c>
  ExpiresActive on
  ExpiresByType text/css "access plus 1 year"
  ExpiresByType text/javascript "access plus 1 year"
</IfModule>
</pre>
<p>Vos fichiers javascript et CSS seront ainsi en cache pendant 1 an, attention du coup à ne pas avoir de fichier sans numéro de version, car ils resteraient en cache et vos internautes ne bénéficieraient pas de vos mises à jour&#8230;</p>
<p>&nbsp;</p>
<p>Dernière chose, si ce n&#8217;est pas encore fait, installez et testez <a href="http://developer.yahoo.com/yslow/" target="_blank">Yslow</a> pour trouver des pistes d&#8217;optimisations de performance de vos sites.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/astuces-de-developpement-javascript-avec-symfony-1382/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Liste d&#8217;objets ordonnable via AJAX partie 1</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/liste-dobjets-ordonnable-via-ajax-partie-1-870</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/liste-dobjets-ordonnable-via-ajax-partie-1-870#comments</comments>
		<pubDate>Wed, 12 Aug 2009 13:07:48 +0000</pubDate>
		<dc:creator>Nikaw</dc:creator>
				<category><![CDATA[1.2.x]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[liste]]></category>
		<category><![CDATA[sortable]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/sfblog/?p=870</guid>
		<description><![CDATA[Aujourd&#8217;hui, voyons les fonctions sortables permettant de changer la position d&#8217;objet, de les ordonner et de sauvegarder l&#8217;ordre. C&#8217;est toujours pratique pour organiser une galerie photo, ou des éléments dans votre site internet. Toutes les informations sur l&#8217;objet que nous &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony/liste-dobjets-ordonnable-via-ajax-partie-1-870">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Aujourd&#8217;hui, voyons les fonctions sortables permettant de changer la position d&#8217;objet, de les ordonner et de sauvegarder l&#8217;ordre. C&#8217;est toujours pratique pour organiser une galerie photo, ou des éléments dans votre site internet.</p>
<p>Toutes les informations sur l&#8217;objet que nous souhaitons ordonner et/ou classer seront stockées en base :<br />
<em>schema.yml</em></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p870code13'); return false;">View Code</a> YAML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p87013"><td class="code" id="p870code13"><pre class="yaml" style="font-family:monospace;">Item:
  columns:
    name:
      type: string(255)
    rank:
      type: integer
      notnull: true
      unique: true</pre></td></tr></table></div>

<p><span id="more-870"></span><br />
L&#8217;attribut &#8216;rank&#8217; étant notnull, il faut forcément qu&#8217;il soit définit lors du save(), et étant unique on ne peut pas le définir par défaut.<br />
Il faut donc surcharger la méthode save() :<br />
<em>Item.class.php</em></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p870code14'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p87014"><td class="code" id="p870code14"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> save<span style="color: #009900;">&#40;</span>Doctrine_Connection <span style="color: #000088;">$con</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
   <span style="color: #666666; font-style: italic;">// les nouveaux enregistrements seront ajoutés à la suite, donc avec un rang élévé de 1 par rapport au rang max</span>
   <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isNew</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
   <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setRank</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMaxRank</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
   <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$con</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Il faut aussi surchager la méthode delete() pour redescendre tous les éléments de rang supérieur lors de la suppression :<br />
<em>Item.class.php</em></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p870code15'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p87015"><td class="code" id="p870code15"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> delete<span style="color: #009900;">&#40;</span>Doctrine_Connection <span style="color: #000088;">$con</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
   <span style="color: #666666; font-style: italic;">//tous les enregistrements au dessus descendent d'une place</span>
  <span style="color: #000088;">$items</span> <span style="color: #339933;">=</span> Doctrine_Query<span style="color: #339933;">-&gt;</span><span style="color: #004000;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Item'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">where</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'rank &gt; ?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRank</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
   <span style="color: #666666; font-style: italic;">// delete the item</span>
   <span style="color: #000088;">$ret</span> <span style="color: #339933;">=</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$items</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setRank</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRank</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #000088;">$ret</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Nous avons donc besoin d&#8217;une méthode permettant de récupérer le rang max :<br />
<em>ItemTable.class.php</em></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p870code16'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p87016"><td class="code" id="p870code16"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//permet de récupérer le rang le plus haut</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getMaxRank<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$query</span> <span style="color: #339933;">=</span> Doctrine_Query<span style="color: #339933;">::</span><span style="color: #004000;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">-&gt;</span><span style="color: #004000;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MAX(rank)'</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Item i'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$tmp</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">HYDRATE_NONE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$tmp</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</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: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Ici on passe en paramètre Doctrine::HYDRATE_NONE pour que la méthode ne retourne pas une collection. Le retour est un tableau à 2 entrées, mais la requête ne retournant qu&#8217;un résultat, il est disponible en [0][0].</p>
<p><strong>Passons maintenant à la vue.</strong><br />
Il s&#8217;agit d&#8217;afficher la liste des items, tout simplement.<br />
Mais pour les afficher, il faut les charger, voyons donc d&#8217;abord l&#8217;action :<br />
<em>actions.class.php</em></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p870code17'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p87017"><td class="code" id="p870code17"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeIndex<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">items</span> <span style="color: #339933;">=</span> Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Item'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAllOrderedByRank</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Un coup d&#8217;oeil tout de suite sur la méthode getAllOrderedByRank() :<br />
<em>ItemTable.class.php</em></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p870code18'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p87018"><td class="code" id="p870code18"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getAllOrderedByRank<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$query</span> <span style="color: #339933;">=</span> Doctrine_Query<span style="color: #339933;">::</span><span style="color: #004000;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Item'</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">-&gt;</span><span style="color: #004000;">orderBy</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'rank ASC'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Maintenant voyons la vue :<br />
<em>indexSuccess.php</em></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p870code19'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p87019"><td class="code" id="p870code19"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>h1<span style="color: #339933;">&gt;</span>Ordered <a href="http://www.php.net/list"><span style="color: #990000;">list</span></a> of items<span style="color: #339933;">&lt;/</span>h1<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>ul<span style="color: #339933;">&gt;</span>
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$items</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  <span style="color: #339933;">&lt;</span>li id<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&lt;?php echo <span style="color: #006699; font-weight: bold;">$item-&gt;getId</span>() ?&gt;&quot;</span><span style="color: #339933;">&gt;</span>
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  <span style="color: #339933;">&lt;/</span>li<span style="color: #339933;">&gt;</span>
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #339933;">&lt;/</span>ul<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>Passons maintenant aux choses sérieuses.<br />
Le framework Javascript JQuery comporte des fonctions permettant de créer des liste dont les éléments sont &laquo;&nbsp;drag n&#8217; droppables&nbsp;&raquo;, ici c&#8217;est celles ci que l&#8217;on va utiliser.<br />
Pour cela, il faut modifier la vue, afin de rajouter le script jquery, et de spécifier une id à la liste, id que le script jquery utilisera pour cibler la liste à ordonner :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p870code20'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p87020"><td class="code" id="p870code20"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>ul id<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;order&quot;</span><span style="color: #339933;">&gt;</span>
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$items</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  <span style="color: #339933;">&lt;</span>li id<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&lt;?php echo <span style="color: #006699; font-weight: bold;">$item-&gt;getId</span>() ?&gt;&quot;</span><span style="color: #339933;">&gt;</span>
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  <span style="color: #339933;">&lt;/</span>li<span style="color: #339933;">&gt;</span>
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #339933;">&lt;/</span>ul<span style="color: #339933;">&gt;</span>
&nbsp;
<span style="color: #339933;">&lt;</span>input type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;button&quot;</span> value<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;Enregistrer&quot;</span> onClick<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;submitOrder()&quot;</span><span style="color: #339933;">/&gt;</span>
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
  $<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//on spécifie la liste</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;#order&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>sortable<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;#order&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>disableSelection<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">function</span> submitOrder<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//initialisation de la chaine contenant les id des items</span>
    <span style="color: #000000; font-weight: bold;">var</span> elements <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//parcours de la liste d'items</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ul#order li'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><a href="http://www.php.net/each"><span style="color: #990000;">each</span></a><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">//pour chaque item, on concatene l'id dans la chaine</span>
      elements <span style="color: #339933;">+=</span> $<span style="color: #009900;">&#40;</span>this<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>attr<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #0000ff;">&quot;,&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #666666; font-style: italic;">//on execute l'action, a laquelle on envoie en param la liste des id</span>
  $<span style="color: #339933;">.</span>post<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'&lt;?php echo url_for('</span><span style="color: #339933;">@</span>order<span style="color: #0000ff;">') ?&gt;'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> elements<span style="color: #339933;">:</span> elements<span style="color: #339933;">.</span><a href="http://www.php.net/substr"><span style="color: #990000;">substr</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> elements<span style="color: #339933;">.</span>length<span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span></pre></td></tr></table></div>

<p>Vous aurez noté l&#8217;ajout du bouton submit. C&#8217;est en cliquant sur celui-ci que l&#8217;on déclenche l&#8217;action qui sauvegarde le nouvel ordre des items.<br />
Pour enregistrer l&#8217;ordre des items, chaque
<li> a pour id l&#8217;id de l&#8217;item en question.<br />
Lors du click on exécute un script qui récupère toutes les id dans l&#8217;ordre et qui les concatène dans une chaîne de caractères en les séparant par des &laquo;&nbsp;,&nbsp;&raquo;. Cette chaîne est envoyée en paramètre à l&#8217;action.<br />
Routing :<br />
<em>routing.yml</em></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p870code21'); return false;">View Code</a> YAML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p87021"><td class="code" id="p870code21"><pre class="yaml" style="font-family:monospace;">order:
  url:      /order-item
  params:  { module: item, action: order }</pre></td></tr></table></div>

<p>L&#8217;action :<br />
<em>actions.class.php</em></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p870code22'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p87022"><td class="code" id="p870code22"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeOrder<span style="color: #009900;">&#40;</span>sfWebRequest <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//on récupère les id, que l'on place dans un tableau pour un parcours plus aisé</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">elements</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;">&quot;,&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'elements'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//on parcours les id, on récupère l'item correspondant, et on met son rang à jour</span>
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">elements</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$element_id</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$item</span> <span style="color: #339933;">=</span> Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Item'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$element_id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setRank</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">items</span> <span style="color: #339933;">=</span> Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Item'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAllByRank</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//on affiche à nouveau la liste des items, mis à jour</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTemplate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'index'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Voilà, vous aurez noté que les nouveaux rangs sont tout simplement la position dans la liste, partant de 0.</p>
<p>Dans la prochaine partie, nous verront comment implanter cette fonctionnalité dans votre backend avec l&#8217;admin generator</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/liste-dobjets-ordonnable-via-ajax-partie-1-870/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Listes déroulantes mises à jours en Ajax avec jQuery</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/listes-deroulantes-mises-a-jours-en-ajax-avec-jquery-704</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/listes-deroulantes-mises-a-jours-en-ajax-avec-jquery-704#comments</comments>
		<pubDate>Wed, 17 Jun 2009 07:49:39 +0000</pubDate>
		<dc:creator>Samuel Breton</dc:creator>
				<category><![CDATA[1.2.x]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Liste déroulante]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/sfblog/?p=704</guid>
		<description><![CDATA[Un petit TIPS pour faire des listes déroulantes liées qui s&#8217;enrichissent en fonction de la valeur choisie sur l&#8217;une d&#8217;entre elles. (J&#8217;ai l&#8217;impression que la phrase est très compliqué pour pas grand chose ^^) Le tout en Ajax en utilisant &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony/listes-deroulantes-mises-a-jours-en-ajax-avec-jquery-704">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Un petit TIPS pour faire des listes déroulantes liées qui s&#8217;enrichissent en fonction de la valeur choisie sur l&#8217;une d&#8217;entre elles.<br />
(J&#8217;ai l&#8217;impression que la phrase est très compliqué pour pas grand chose ^^)<br />
Le tout en Ajax en utilisant jQuery.<br />
<span id="more-704"></span><br />
Dans mon exemple, ça sera tout simplement un formulaire Lambda avec des listes déroulante pour les Régions et les Départements.<br />
Le fonctionnement est le suivant. Par défaut les listes déroulantes sont initialisées avec toutes les valeurs. Dés que l&#8217;on choisi une valeur pour la région, la liste déroulante des département affine sa liste pour ne proposer que les départements de la région saisie.</p>
<p>Vite fait, le schéma utilisé :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p704code28'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p70428"><td class="code" id="p704code28"><pre class="yml" style="font-family:monospace;">...
Region:
  tableName:  region
  actAs:
    Sluggable:
      unique: true
      fields: [nom]
  columns:
    id:       { type: integer(4), unsigned: true, primary: true, autoincrement: true }
    nom:      { type: string(255), notnull: true }
&nbsp;
Departement:
  tableName: departement
  actAs:
    Sluggable:
      unique: true
      fields: [nom]
  columns:
    id:        { type: integer(4), unsigned: true, primary: true, autoincrement: true }
    nom:       { type: string(255), notnull: true }
    region_id: { type: integer(4), unsigned: true }
  relations:
    Region:
      local:        region_id
      foreign:      id
      foreignAlias: Departements
      onDelete:     CASCADE
...</pre></td></tr></table></div>

<p>Juste pour mettre en évidence la relation entre le Département et la Région, avec le très important le foreignAlias que j&#8217;aime tant <img src='http://www.lexik.fr/blog/symfony/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Pour faire fonctionner tout ça on va avoir besoin de :<br />
 &#8211; 1 route<br />
 &#8211; 1 action minuscule<br />
 &#8211; 1 partial de 4 lignes<br />
 &#8211; 1 tout petit bout de javascript</p>
<p>La route :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p704code29'); return false;">View Code</a> JAVASCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p70429"><td class="code" id="p704code29"><pre class="javascript" style="font-family:monospace;"># routing.<span style="color: #660066;">yml</span>
...
<span style="color: #660066;">ajax_departement</span><span style="color: #339933;">:</span>
  url<span style="color: #339933;">:</span>   <span style="color: #339933;">/</span>ajax<span style="color: #339933;">/</span>departement
  param<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span> module<span style="color: #339933;">:</span> lambda<span style="color: #339933;">,</span> action<span style="color: #339933;">:</span> ajaxDepartement <span style="color: #009900;">&#125;</span>
...</pre></td></tr></table></div>

<p>L&#8217;action :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p704code30'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p70430"><td class="code" id="p704code30"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// actions.class.php</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * requete ajax pour avoir la liste des déparements de la région
   *
   * @param sfWebRequest $request
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeAjaxDepartement<span style="color: #009900;">&#40;</span>sfWebRequest <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$region</span> <span style="color: #339933;">=</span> Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Region'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">findOneById</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'region'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderPartial</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'lambda/selectDepartement'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'region'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$region</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Le partial :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p704code31'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p70431"><td class="code" id="p704code31"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// _selectDepartement.php</span>
<span style="color: #339933;">&lt;</span>option value<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">&gt;&lt;/</span>option<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$region</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDepartements</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$departement</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #339933;">&lt;</span>option value<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&lt;?php echo <span style="color: #006699; font-weight: bold;">$departement-&gt;getId</span>() ?&gt;&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$departement</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getNom</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>option<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Et enfin le petit bout de code jQuery à rajouter au formulaire :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p704code32'); return false;">View Code</a> JAVASCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p70432"><td class="code" id="p704code32"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>script language<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;javascript&quot;</span><span style="color: #339933;">&gt;</span>
$<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#mon_formulaire_lambda_region_id&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">change</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    $.<span style="color: #660066;">post</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;/ajax/departement&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> region<span style="color: #339933;">:</span> $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
      $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#mon_formulaire_lambda_departement_id&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>Pour le javascript plusieurs solutions. Soit l&#8217;inclure directement dans la vue avec les balises <script></script> comme je l&#8217;ai fait ici.<br />
Soit faire un fichier .js que l&#8217;on met dans /web/js/mon_fichier.js (bien mais pas top <img src='http://www.lexik.fr/blog/symfony/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ).</p>
<p>Le plus &laquo;&nbsp;propre&nbsp;&raquo; est de faire une vue et d&#8217;utiliser le sf_format et d&#8217;inclure le fichier via une route.<br />
On verra ça lors d&#8217;un prochain post <img src='http://www.lexik.fr/blog/symfony/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>@bientôt !</p>
<p>NB : Bien entendu il faut que jQuery soi inclus :<br />
 &#8211; Soit il est inclus dans le view.yml<br />
 &#8211; Soit directement dans la vue avec un use_javascript(&#8216;jQuery.js&#8217;)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/listes-deroulantes-mises-a-jours-en-ajax-avec-jquery-704/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Petit système de vote en AJAX</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/petit-systeme-de-vote-en-ajax-590</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/petit-systeme-de-vote-en-ajax-590#comments</comments>
		<pubDate>Tue, 21 Apr 2009 07:59:48 +0000</pubDate>
		<dc:creator>Nikaw</dc:creator>
				<category><![CDATA[1.2.x]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[votes]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/sfblog/?p=590</guid>
		<description><![CDATA[sytème de vote type "j'aime" / "j'aime pas" avec JQuery sur Symfony avec limitation de vote par utilisateur et par message pour un temps donné<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony/petit-systeme-de-vote-en-ajax-590">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Le système que je vous propose est assez simpliste : il s&#8217;agit d&#8217;un vote type &laquo;&nbsp;j&#8217;aime / j&#8217;aime pas&nbsp;&raquo;.</p>
<p>On dispose d&#8217;un ensemble d&#8217;éléments (ici des messages) que l&#8217;on nous propose de noter.</p>
<p>Dans une première étape, le principe est de créer le système de vote, dans une deuxième étape on limitera les votes : un visiteur ne peut voter sur un élément qu&#8217;une fois par jour.<br />
(Attention, ne pas pas oublier d&#8217;ajouter les include et use_javascript dans le layout de votre appli)<br />
<span id="more-590"></span><br />
<strong>Etape 1 :</strong></p>
<p><strong>Schéma :</strong></p>
<pre>
Message:
  columns:
    text:
      type: string(255)
    relations:
      Ratings:
        type: many
        class: Rating
        local: id
        foreign: message_id

Rating:
  actAs: { Timestampable: ~ } //permet d'avoir les champs "created_at" et "updated_at", pour limiter le nombre de vote à 1 par jour
  columns:
    value:
      type: boolean
    message_id:
      type: integer
  relations:
    Message:
      onDelete: CASCADE
      local: message_id
      foreign: id
</pre>
<p>On a donc une table contenant nos messages (ici on n&#8217;a besoin que du texte) et une table contenant les votes : un vote est donc décrit par une id, et un message, donc à chaque click un nouveau vote est inséré dans la base de données.</p>
<p>Pour éviter de se retrouver avec une BDD sur-remplie, on pourra rajouter une 3° étape qui consiste à créer une tâche qui compile chaque vote sur un message pour en faire un résumé (qui fait la somme par exemple) et qui ensuite supprime les votes compilés.</p>
<p>Bref, les fonctionnalités utiles maintenant sont : afficher la note du message, afficher le nombre de votes (pour pouvoir faire la différence entre un message qui a une bonne note mais 3 votes et un message qui a une bonne note mais 1000 votes, par exemple), et afficher les liens permettant de voter, tout ça à coté du message en question, bien évidemment.</p>
<p><strong>Voici donc le code de l&#8217;index des message</strong> (apps/*votre appli*/modules/message/templates/indexSuccess.php)</p>
<pre>
<h1>Message List</h1>

<!-- div ou l'on affiche la note et le nombre de votes du message, c'est cette div qui sera actualiser en AJAX -->
&lt;div id ="ratinggetId() ?&gt;"&gt;
  <!-- l'id de la div contien l'id du message, pour spécifier au moment du vote quelle div précise il faut actualiser -->
   $message)) ?&gt;
</div>

<!-- div ou l'on affiche les liens du vote, + et - -->
<div class="rating_links">
   'rating'.$message-&gt;getId(),
                          'url'      =&gt; '@message_vote_plus?id='.$message-&gt;getId()
    )); ?&gt;
   'rating'.$message-&gt;getId(),
                  'url'      =&gt; '@message_vote_moins?id='.$message-&gt;getId()
    )); ?&gt;
</div>

<!-- div du texte du message -->
<div class="text" style=" margin-bottom: 15px;">
  gettext() ?&gt;
</div>
</pre>
<p><strong>Partial message/rating</strong> (apps/*votre appli*/module/template/_rating.php) :</p>
<pre>
Note : getGlobalRating(); ?&gt;/,
Nombre de votes : getRatingsCount() ?&gt;
</pre>
<p>La syntaxe utilisée ici pour les fonction link_to_remote est :<br />
link_to_remote(&#8216;texte à afficher pour le lien&#8217;, tableau des options(&#8216;update&#8217; =&gt; id de la div a update, &#8216;url&#8217; =&gt; adresse de l&#8217;action))</p>
<p>Vous noterez aussi que les url des link_to_remote utilisent des routes,<strong> voici les routes utilisées</strong>(apps/*votre appli*/config/routes.yml) :</p>
<pre>
message_vote_plus:
  url:      /message-vote-plus/:id
  param:    { module: message, action: votePlus }

message_vote_moins:
  url:      /message-vote-moins/:id
  param:    { module: message, action: voteMoins }
</pre>
<p>Un click sur un lien va donc engendrer l&#8217;action votePlus ou voteMoins de l&#8217;objet message en question, spécifié par l&#8217;id.<br />
<strong>Voici les actions</strong> (apps/*votre appli*/modules/message/actions.class.php) :</p>
<pre>
  //execute le vote "j'aime"
  public function executeVotePlus(sfWebRequest $request)
  {
    //on récupère le message courant
    $this-&gt;message = Doctrine::getTable('Message')-&gt;find($request-&gt;getParameter('id'));
    //on effectue le vote positif
    $this-&gt;message-&gt;votePlus();
    //on génère le partial du message, c'est ce résultat qui sera utilisé par le link_to_remote pour mettre à jour la div spécifiée, cela évite également le passage par le template votePlusSuccess.php (qui donc n'est pas à créer)
    return $this-&gt;renderPartial('message/rating',array('message' =&gt; $this-&gt;message));
  }

  //execute le vote "j'aime pas"
  public function executeVoteMoins(sfWebRequest $request)
  {
    //on récupère le message courant
    $this-&gt;message = Doctrine::getTable('Message')-&gt;find($request-&gt;getParameter('id'));
    //on effectue le vote négatif
    $this-&gt;message-&gt;voteMoins();
    //on génère le partial du message, c'est ce résultat qui sera utilisé par le link_to_remote pour mettre à jour la div spécifiée, cela évite également le passage par le template voteMoinsSuccess.php (qui donc n'est pas à créer)
    return $this-&gt;renderPartial('message/rating',array('message' =&gt; $this-&gt;message));
  }
</pre>
<p>L&#8217;action utilise donc naturellement des méthodes du controlleur (lib/model/doctrine/Message.class.php) :<br />
<strong>-récupération du nombres de vote sur 1 message :</strong></p>
<pre>
  //retourne le nombre de votes sur ce message
  public function getRatingsCount()
  {
    return Doctrine::getTable('Rating')-&gt;getMessageRatingsQuery($this-&gt;getId())-&gt;count();
  }
</pre>
<p><strong>-récupération de la note d&#8217;un message :</strong></p>
<pre>
  //retourne la note globale du message courant
  public function getGlobalRating()
  {
    //on récupère tous les votes sur ce message
    $ratings = Doctrine::getTable('Rating')-&gt;getMessageRatingsQuery($this-&gt;getId())-&gt;execute();
    //on initialise la note a 0
    $note = 0;
    //pour chaque vote positif on incrémente la note (rappel : la note est stockée sous forme de boolean dans la base)
    foreach ($ratings as $rating)
    {
      if ($rating-&gt;getValue())
      {
        $note++;
      }
    }
    //on récupère le nombre de votes, pour calculer la moyenne
    $nbvotes = $this-&gt;getRatingsCount();
    //si il n'y pas encore eu de vote sur ce message, on est obligé de donner la valeur 1 à nbvotes, pour éviter une division par 0
    if($nbvotes == 0){ $nbvotes = 1; }

    //on retourne la moyenne : (note/nb_votes)*"valeur sur laquelle on rapporte la note" et on arrondi (round)
    //la valeur sur laqelle on rapporte la note est stockée dans la config (app.yml), ainsi que le nombre de chiffres apres la virgule
    return round(($note/$nbvotes)*sfConfig::get('app_moyenne_sur'), sfConfig::get('app_round'));
  }
</pre>
<p><strong>-votes :</strong></p>
<pre>
  //ajoute un vote positif relatif à ce message
  public function votePlus()
  {
    return $this-&gt;vote('1');
  }

  //ajoute un vote négatif relatif à ce message
  public function voteMoins()
  {
    return $this-&gt;vote('0');
  }

  //effectur le vote
  public function vote($value)
  {
    $rating = new Rating(); //nouveau vote
    //on set ses champs
    $rating-&gt;setMessageId($this-&gt;getId()); //message_id
    $rating-&gt;setValue($value); //value
    $rating-&gt;save(); //on l'enregistre dans la base
  }
</pre>
<p>Voilà pour la première étape, le système de votes est opérationnel, reste plus qu&#8217;à limiter les votes.</p>
<p><strong>Etape 2</strong><br />
De quoi a-t-on besoin pour la suite ?<br />
1) Modifier le schéma pour ajouter l&#8217;attribut ip_user, correspondant à l&#8217;adresse ip de l&#8217;utilisateur<br />
2) De vérifier au moment du vote dans le modèle, s&#8217;il existe déjà un vote récent pour ce message et pour cette adresse ip<br />
3) Donc, on a aussi besoin d&#8217;une méthode dans la classe RatingTable.class.php qui récupère les votes récents<br />
4) On ajoutera également un message à l&#8217;utilisateur pour le remercier de son vote ou lui indiquer qu&#8217;il n&#8217;a plus le droit de voter.</p>
<p><strong>Mise à jour de la table Rating dans le schéma : </strong></p>
<pre>
Rating:
  actAs: { Timestampable: ~ }
  columns:
    value:
      type: boolean
    message_id:
      type: integer
    user_ip:
      type: string(12)
      notnull: true
  relations:
    Message:
      onDelete: CASCADE
      local: message_id
      foreign: id
</pre>
<p><strong>1) Modification de la méthode vote()</strong></p>
<pre>
public function vote(sfWebRequest $request, $value)
  {
    //on récupère l'adresse ip du visiteur/utilisateur
    $user_ip = $request-&gt;getRemoteAddress();
    //on récupère les votes effectués par cet utilisateur sur ce message
    $recent_rating = Doctrine::getTable('Rating')-&gt;getRecentRating(array('user_ip' =&gt; $user_ip, 'message_id' =&gt; $this-&gt;getId()));
    //si il n'existe pas de vote trop récent
    if(!($recent_rating-&gt;count() &gt; 0))
    {
      $rating = new Rating(); //nouveau vote
      //on set ses champs
      $rating-&gt;setUserIp($user_ip); //user_ip
      $rating-&gt;setMessageId($this-&gt;getId()); //message_id
      $rating-&gt;setValue($value); //value
      $rating-&gt;save(); //on l'enregistre dans la base et on retourne vrai
      return true;
    }
    else //si le vote est trop récent, pas de vote, on retourne faux
    {
      return false;
    }
  }
</pre>
<p><strong>Ce qui implique évidemment la création de la méthode getRecentRating() (dans lib/model/doctrine/RatingTable.class.php) :</strong></p>
<pre>
  //retourne les votes récents dans la query
  public function getRecentRating($params, Doctrine_Query $query = NULL)
  {
    if(is_null($query)) //si pas de requete, on récupère tous les votes de la base
    {
      $query = $this-&gt;createQuery('c');
    }
    //on récupère tous les votes faits avec cette ip
    $query = $this-&gt;getRatingsByUserIp($params['user_ip'], $query);
    //on récupère tous les votes sur ce message
    $query = $this-&gt;getMessageRatingsQuery($params['message_id'], $query);
    //on sélectionne uniquement les message récents
    $query-&gt;andWhere('c.created_at &gt;= ?', date('Y-m-d h:i:s', time() - 86400 * (sfConfig::get('app_vote_time_limit') / 24)));
    return $query;
  }
</pre>
<p>La valeur de la limite de temps pour le vote et stockée dans la config, de la même manière que round et moyenne_sur dans la première partie</p>
<pre>
All:
  moyenne_sur: 20
  round: 1
  #limite de temps pour le vote (en heures)
  vote_time_limit: 24
</pre>
<p>Vous noterez sûrement la présences des fonctions getRatingsByUserIpQuery() et getMessageRatingsQuery() :</p>
<pre>
  //retourne la requête permettant de récupérer tous les votes sur un message donné, parmis ceux récupérés par la requete $query
  public function getMessageRatingsQuery($message_id, Doctrine_Query $query = NULL)
  {
    if(is_null($query)) //si aucune requête passée, on génère la requête pour récup tous les votes
    {
      $query = $this-&gt;createQuery('c');
    }
    $query-&gt;andWhere('c.message_id = ?', $message_id); //on ajoute le where pour filtrer par message_id

    return $query;
  }

  //retourne la requete permettant de récupérer tous les votes passé par une adresse ip, parmis ceux récupérés par la requete $query
  public function getRatingsByUserIp($user_ip, Doctrine_Query $query = NULL)
  {
    if(is_null($query)) //si aucune requête passée, on génère la requête pour récup tous les votes
    {
      $query = $this-&gt;createQuery('c');
    }
    $query-&gt;andWhere('c.user_ip = ?', $user_ip); //on ajoute le where pour filtrer par user_ip

    return $query;
  }
</pre>
<p>Il ne reste plus qu&#8217;à afficher un petit message à notre utilisateur (dans l&#8217;action) :</p>
<pre>
  //execute le vote "j'aime"
  public function executeVotePlus(sfWebRequest $request)
  {
    //on récupère le message courant
    $this-&gt;message = Doctrine::getTable('Message')-&gt;find($request-&gt;getParameter('id'));
    //on effectue le vote positif
    if($this-&gt;message-&gt;votePlus($request))
    {
      $this-&gt;getUser()-&gt;setFlash('vote', "Merci d'avoir voté", false);
    }
    else
    {
      $this-&gt;getUser()-&gt;setFlash('vote', "vous ne pouvez plus voter", false);
    }
    //on génère le partial du message, c'est ce résultat qui sera utilisé par le link_to_remote pour mettre à jour la div spécifiée
    //cela évite également le passage par le template votePlusSuccess.php (qui donc n'est pas à créer)
    return $this-&gt;renderPartial('message/rating',array('message' =&gt; $this-&gt;message));
  }

  //execute le vote "j'aime pas"
  public function executeVoteMoins(sfWebRequest $request)
  {
    //on récupère le message courant
    $this-&gt;message = Doctrine::getTable('Message')-&gt;find($request-&gt;getParameter('id'));
    //on effectue le vote négatif
    if($this-&gt;message-&gt;voteMoins($request))
    {
      $this-&gt;getUser()-&gt;setFlash('vote', "Merci d'avoir voté", false);
    }
    else
    {
      $this-&gt;getUser()-&gt;setFlash('vote', "vous ne pouvez plus voter", false);
    }
    //on génère le partial du message, c'est ce résultat qui sera utilisé par le link_to_remote pour mettre à jour la div spécifiée, cela évite également le passage par le template voteMoinsSuccess.php (qui donc n'est pas à créer)
    return $this-&gt;renderPartial('message/rating',array('message' =&gt; $this-&gt;message));
  }
</pre>
<p>On utilise la méthode sfUser::setFlash(). Comme la mise à jour de l&#8217;affichage sera le partial rendu, <strong>il faut donc intégrer encore quelques lignes dans le template correspondant (apps/*votre appli*/module/message/template/_rating.php :</strong></p>
<pre>
Note : getGlobalRating(); ?&gt;/,
Nombre de votes : getRatingsCount() ?&gt;
<!-- message -->
hasFlash('vote')): ?&gt;
<span class="flash_notice">getFlash('vote') ?&gt;</span>
</pre>
<p>Et voilà !!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/petit-systeme-de-vote-en-ajax-590/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>JEditable et formulaire Symfony 1.2</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/jeditable-et-formulaire-symfony-12-502</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/jeditable-et-formulaire-symfony-12-502#comments</comments>
		<pubDate>Fri, 17 Apr 2009 07:57:17 +0000</pubDate>
		<dc:creator>Samuel Breton</dc:creator>
				<category><![CDATA[1.2.x]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[formulaire]]></category>
		<category><![CDATA[JEditable]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/sfblog/?p=502</guid>
		<description><![CDATA[Comment intégrer un plugin jQuery dans un projet Symfony 1.2 ? La réponse à cette question ne pouvant pas tenir dans le modeste blog de Lexik.fr, je vais seulement vous expliquer comment intégrer la modification d&#8217;un champ &#171;&#160;INPUT&#160;&#187; en ajax &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony/jeditable-et-formulaire-symfony-12-502">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Comment intégrer un plugin jQuery dans un projet Symfony 1.2 ?</p>
<p>La réponse à cette question ne pouvant pas tenir dans le modeste blog de Lexik.fr, je vais seulement vous expliquer comment intégrer la modification d&#8217;un champ &laquo;&nbsp;INPUT&nbsp;&raquo; en ajax dans un formulaire Symfony 1.2, à l&#8217;aide du plugin jQuery JEditable.</p>
<p>A ce stade, je vous recommande ce lien : <a href="http://www.appelsiini.net/projects/jeditable">JEditable</a><br />
<span id="more-502"></span></p>
<h2>Pré-requis</h2>
<ul>
<li>
Comme d&#8217;habitude, l&#8217;éternel plugin : <a href="http://www.symfony-project.org/plugins/sfFormExtraPlugin">sfFormExtraPlugin</a>
</li>
<li>
Les JS :</p>
<ul>
<li>jquery-1.3.2.min.js</li>
<li>jquery.jeditable.js</li>
</ul>
</li>
</ul>
<h2>Le widget</h2>
<p><b>Chemin : </b><br />
<quote>[votre_projet]/plugins/sfFormExtraPlugin/lib/widget/sfWidgetFormInputEditInPlace.class.php</quote>
</p>
<p><b>Code source :</b></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p502code44'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p50244"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
</pre></td><td class="code" id="p502code44"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> sfWidgetFormInputEditInPlace <span style="color: #000000; font-weight: bold;">extends</span> sfWidgetFormInput
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$object</span><span style="color: #339933;">;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$route</span><span style="color: #339933;">;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$option</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$messages</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$object</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$route</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    parent<span style="color: #339933;">::</span>__construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$option</span><span style="color: #339933;">,</span> <span style="color: #000088;">$messages</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">object</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$object</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$route</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$messages</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    parent<span style="color: #339933;">::</span><span style="color: #004000;">configure</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$options</span><span style="color: #339933;">,</span> <span style="color: #000088;">$messages</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> render<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$attributes</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errors</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>    
    <span style="color: #000088;">$prefix</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">generateId</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>    
    <span style="color: #b1b100;">return</span> <a href="http://www.php.net/sprintf"><span style="color: #990000;">sprintf</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000cc; font-style: italic;">&lt;&lt;&lt;EOF
&lt;b id=&quot;%s&quot;&gt;%s&lt;/b&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
$(function() {
  $(&quot;#%s&quot;).editable(
    &quot;%s&quot;,
    {
      indicator : 'Saving...',      
      type   : &quot;text&quot;,
      submit : &quot;OK&quot;,
      style  : &quot;inherit&quot;,
      id       : 'ajaxfield_id'
  });
});
&lt;/script&gt;
EOF</span>
    <span style="color: #339933;">,</span> <span style="color: #000088;">$prefix</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span><span style="color: #339933;">,</span>
      <span style="color: #000088;">$prefix</span><span style="color: #339933;">,</span>
      url_for<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">object</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'absolute'</span><span style="color: #339933;">=&gt;</span>true<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
   <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

</p>
<p>Pour ce widget, j&#8217;ai créer 2 attributs.</p>
<ul>
<li><b>object</b><br />
Cet attribut contient l&#8217;objet de la route objet Symfony.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p502code45'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p50245"><td class="line_numbers"><pre>4
</pre></td><td class="code" id="p502code45"><pre class="php" style="font-family:monospace;"> <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$object</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

</li>
<li><b>route</b><br />
Cet attribut contient le nom de la route objet Symfony.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p502code46'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p50246"><td class="line_numbers"><pre>5
</pre></td><td class="code" id="p502code46"><pre class="php" style="font-family:monospace;"> <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$route</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

</li>
<p>Ces attributs nous permettent de générer l&#8217;URL de la page qui va valider et éventuellement sauvegarder les données postées par le widget JQuery.
</ul>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p502code47'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p50247"><td class="line_numbers"><pre>36
</pre></td><td class="code" id="p502code47"><pre class="php" style="font-family:monospace;">url_for<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">route</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">object</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'absolute'</span><span style="color: #339933;">=&gt;</span>true<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span></pre></td></tr></table></div>

<p>
Maintenant que l&#8217;outil est créé, utilisons le !<br />
Toute la suite de l&#8217;article n&#8217;est qu&#8217;un exemple d&#8217;utilisation.
</p>
<h2>Schéma</h2>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p502code48'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p50248"><td class="code" id="p502code48"><pre class="yml" style="font-family:monospace;">Person:
  columns:
    firstname:
      type: string(255)
    lastname:
      type: string(255)
    email:
      type: string(255)</pre></td></tr></table></div>

<h2>Routing</h2>
<ul>
<li><b>show_person</b><br />
La route du formulaire.
</li>
<li><b>save_person_eip</b><br />
Route de l&#8217;action &laquo;&nbsp;executeSaveEIP&nbsp;&raquo; qui valide et sauve les champs du modèle &laquo;&nbsp;Person&nbsp;&raquo;
</li>
</ul>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p502code49'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p50249"><td class="code" id="p502code49"><pre class="yml" style="font-family:monospace;"># Route du formulaire
show_person:
  url:     /person/show/:id
  class:   sfDoctrineRoute
  options: { model: Person, type: object }
  param:   { module: person, action: show }
&nbsp;
# Route de la page sauvant les données postées en ajax
save_person_eip:
  url:     /person/saveEIP/:id
  class:   sfDoctrineRoute
  options: { model: Person, type: object }
  param:   { module: person, action: saveEIP }
  requirements:
    id: d+
    sf_method: [post]</pre></td></tr></table></div>

<h2>Actions</h2>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p502code50'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p50250"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
</pre></td><td class="code" id="p502code50"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// L'action pour le formulaire de base</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeShow<span style="color: #009900;">&#40;</span>sfWebRequest <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">person</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRoute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PersonForm<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">person</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// L'action qui traite le post en ajax</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeSaveEIP<span style="color: #009900;">&#40;</span>sfWebRequest <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">// Récupération de l'objet de la route</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">person</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRoute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Récupération des données postées par le widget JQuery</span>
  <span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ajaxfield_id'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">value</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'value'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Récupération du nom du champ</span>
  <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/ereg"><span style="color: #990000;">ereg</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;person_(.*)$&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #339933;">,</span> <span style="color: #000088;">$key</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$champ</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$key</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> 
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Instanciation d'un formulaire lié à notre objet</span>
  <span style="color: #000088;">$form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PersonForm<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Récupération du validateur du champ</span>
  <span style="color: #000088;">$validator</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValidator</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$champ</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// On tente de valider le champ</span>
  try
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$cleaned</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$validator</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clean</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">person</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$champ</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">joueur</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
  catch<span style="color: #009900;">&#40;</span>sfValidatorError <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
     <span style="color: #666666; font-style: italic;">// Erreur lors de la validation du champ </span>
     <span style="color: #666666; font-style: italic;">// La valeur à afficher dans le template doit être la valeur actuelle de l'objet</span>
     <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">value</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">person</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$champ</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h2>Templates</h2>
<ul>
<li><b>showSuccess.php</b>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p502code51'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p50251"><td class="code" id="p502code51"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>h1<span style="color: #339933;">&gt;</span>Edition d<span style="color: #0000ff;">'une personne&lt;/h1&gt;
&lt;?php echo $form['</span>firstname<span style="color: #0000ff;">']-&gt;render();?&gt;&lt;br&gt;
&lt;?php echo $form['</span>lastname<span style="color: #0000ff;">']-&gt;render();?&gt;&lt;br&gt;
&lt;?php echo $form['</span>email<span style="color: #0000ff;">']-&gt;render();?&gt;&lt;br&gt;</span></pre></td></tr></table></div>

</li>
<li><b>saveEIPSuccess.php</b>

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

</li>
</ul>
<h2>Formulaire</h2>
<ul>
<li>
On construit chacun des widgets avec l&#8217;objet et le nom de la route.
</li>
<li>
On définit les validators.
</li>
</ul>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p502code53'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p50253"><td class="code" id="p502code53"><pre class="php" style="font-family:monospace;">  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Widgets</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">widgetSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'firstname'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormEditInPlace<span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'save_joueur_eip'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">widgetSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'lastname'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormEditInPlace<span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'save_joueur_eip'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">widgetSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'email'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormEditInPlace<span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'save_joueur_eip'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Validators</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'firstname'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorString<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'lastname'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorString<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'email'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorEmail<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  
  <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h2>View.yml</h2>

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

]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/jeditable-et-formulaire-symfony-12-502/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Symfony &amp; jQuery DatePicker</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/symfony-jquery-datepicker-491</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/symfony-jquery-datepicker-491#comments</comments>
		<pubDate>Tue, 14 Apr 2009 07:34:36 +0000</pubDate>
		<dc:creator>Samuel Breton</dc:creator>
				<category><![CDATA[1.2.x]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[datePicker]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[I18N]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[widget]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/sfblog/?p=491</guid>
		<description><![CDATA[Je vais vous montrer dans cet article comment mettre en place rapidement un datePicker jQuery dans un formulaire Symfony 1.2 Pré-requis Plugin sfFormExtraPlugin installé : sfFormExtraPlugin Fichiers externes Télécharger jQuery UI (jquery-1.3.2.min.js, jquery-ui-1.7.1.custom.min.js) Vous pouvez télécharger une version &#171;&#160;customizée&#160;&#187; de &#8230;<p class="more aright"><a href="http://www.lexik.fr/blog/symfony/symfony/symfony-jquery-datepicker-491">...</a></p>]]></description>
			<content:encoded><![CDATA[<p>Je vais vous montrer dans cet article comment mettre en place rapidement un datePicker jQuery dans un formulaire Symfony 1.2</p>
<h2>Pré-requis</h2>
<ul>
<li>Plugin sfFormExtraPlugin installé : <a href="http://www.symfony-project.org/plugins/sfFormExtraPlugin">sfFormExtraPlugin</a>
</li>
</ul>
<p><span id="more-491"></span></p>
<h2>Fichiers externes</h2>
<ul>
<li>
<b>Télécharger jQuery UI </b><br />
<em>(jquery-1.3.2.min.js, jquery-ui-1.7.1.custom.min.js)</em></p>
<p>Vous pouvez télécharger une version &laquo;&nbsp;customizée&nbsp;&raquo; de jQuery UI ici :<br />
<a href="http://jqueryui.com/download">Télécharger JQuery UI</a>
</p>
</li>
<li>
<b>Version française</b><br />
<em>(uidatepicker-fr.js)</em></p>
<p>Vous trouverez le patch français de ce plugin ici :</p>
<p><a href="http://www.remy-solnais.com/jquery-et-datepicker/">Datepicker jQuery en français</a>
</li>
<li><b>Intégration dans Symfony</b>
<ol>
<li><b>JS</b><br />
  Copiez les fichiers :<br />
  <b>[jquery UI]/js/jquery-1.3.2.min.js </b><br />
  <b>[jquery UI]/js/jquery-ui-1.7.1.custom.min.js </b><br />
  <b>uidatepicker-fr.js</b><br />
  directement dans <b>[votre_projet]/web/js</b>
  </li>
<li><b>CSS</b>
<ul>
<li>Copiez le fichier :<br />
<b>[jquery UI]/css/jquery-ui-1.7.1.custom.css</b> dans :<br />
<b>[votre_projet]/web/css.</b>
</li>
<li><span style="color: red;">!! Attention !! </span>:<br />
J&#8217;ai dû remplacer toutes les occurrences de :<br />
<b>url(images/</b> par :<br />
<b>url(../images/</b>
</li>
</ul>
</li>
<li><b>Images</b><br />
N&#8217;oubliez pas de copier le contenu de :<br />
<b>[jquery UI]/css/smoothness/images</b> dans :<br />
<b>[votre_projet]/web/images</b>
</li>
</ol>
</li>
</ul>
<h2>View.yml</h2>
<p>N&#8217;oubliez pas de faire référence aux fichiers externes dans le view :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p491code63'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49163"><td class="code" id="p491code63"><pre class="yml" style="font-family:monospace;">default:
  http_metas:
    content-type: text/html
&nbsp;
  metas:
    #title:        symfony project
    #description:  symfony project
    #keywords:     symfony, project
    #language:     en
    #robots:       index, follow
&nbsp;
  stylesheets:    [main.css, jquery-ui-1.7.1.custom.css]
&nbsp;
  javascripts:    [jquery-1.3.2.min.js, uidatepicker-fr.js, jquery-ui-1.7.1.custom.min.js]
&nbsp;
  has_layout:     on
  layout:         layout</pre></td></tr></table></div>

<h2>sfWidgetFormJQueryI18nDate.class.php</h2>
<p>J&#8217;ai modifié la classe sfWidgetFormJQueryDate pour qu&#8217;elle soit compatible avec un format de date français.<br />
De plus, on peut facilement configurer les options  du widget jQuery.</p>
<ul>
<li><b>Code source :</b><br />
<u>Fichier :</u> sfWidgetFormJQueryI18nDate.class.php<br />
<u>Chemin :</u> /plugins/sfFormExtraPlugin/lib/widget/</p>

<div class="wp_codebox_msgheader wp_codebox_hide"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p491code64'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49164"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
</pre></td><td class="code" id="p491code64"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">/*
 * This file is part of the symfony package.
 * (c) Fabien Potencier &lt;fabien.potencier@symfony-project.com&gt;
 * 
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * sfWidgetFormJQueryDate represents a date widget rendered by JQuery UI.
 *
 * This widget needs JQuery and JQuery UI to work.
 *
 * @package    symfony
 * @subpackage widget
 * @author     Fabien Potencier &lt;fabien.potencier@symfony-project.com&gt;
 * @version    SVN: $Id: sfWidgetFormJQueryDate.class.php 12875 2008-11-10 12:22:33Z fabien $
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> sfWidgetFormJQueryI18nDate <span style="color: #000000; font-weight: bold;">extends</span> sfWidgetFormI18nDate
<span style="color: #009900;">&#123;</span>
  <span style="color: #009933; font-style: italic;">/**
   * Configures the current widget.
   *
   * Available options:
   *
   *  * image:   The image path to represent the widget (false by default)
   *  * config:  A JavaScript array that configures the JQuery date widget
   *  * culture: The user culture
   *
   * @param array $options     An array of options
   * @param array $attributes  An array of default HTML attributes
   *
   * @see sfWidgetForm
   */</span>	
&nbsp;
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$attributes</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'image'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'config'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;config&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'culture'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;culture&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'years'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;years&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    parent<span style="color: #339933;">::</span><span style="color: #004000;">configure</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$options</span><span style="color: #339933;">,</span> <span style="color: #000088;">$attributes</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'en'</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'culture'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'culture'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'en'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * @param  string $name        The element name
   * @param  string $value       The date displayed in this widget
   * @param  array  $attributes  An array of HTML attributes to be merged with the default HTML attributes
   * @param  array  $errors      An array of errors for the field
   *
   * @return string An HTML tag string
   *
   * @see sfWidgetForm
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> render<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$attributes</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errors</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$prefix</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">generateId</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$image</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span> <span style="color: #339933;">!==</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'image'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$image</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/sprintf"><span style="color: #990000;">sprintf</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">', buttonImage: %s, buttonImageOnly: true'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'image'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">render</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #000088;">$attributes</span><span style="color: #339933;">,</span> <span style="color: #000088;">$errors</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>
           <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderTag</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'input'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'type'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'hidden'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'size'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">10</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'id'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">generateId</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'_jquery_control'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'disabled'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'disabled'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>
           <a href="http://www.php.net/sprintf"><span style="color: #990000;">sprintf</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000cc; font-style: italic;">&lt;&lt;&lt;EOF
&lt;script type=&quot;text/javascript&quot;&gt;
&nbsp;
  function %s_read_linked()
  {
    \$(&quot;#%s&quot;).val(\$(&quot;#%s&quot;).val() + &quot;/&quot; + \$(&quot;#%s&quot;).val() + &quot;/&quot; + \$(&quot;#%s&quot;).val());
&nbsp;
    return {};
  }
&nbsp;
  function %s_update_linked(date)
  {
    \$(&quot;#%s&quot;).val(date.substring(0, 2));
    \$(&quot;#%s&quot;).val(parseInt(date.substring(3, 5), 10));
    \$(&quot;#%s&quot;).val(date.substring(6, 10));
  }
&nbsp;
  \$(&quot;#%s&quot;).datepicker(\$.extend({}, {
    minDate:    new Date(%s, 1 - 1, 1),
    maxDate:    new Date(%s, 12 - 1, 31),
    onSelect:   %s_update_linked,
    beforeShow: %s_read_linked,    
    %s    
    showOn:     &quot;both&quot;
    %s
  }, \$.datepicker.regional[&quot;%s&quot;]));
&nbsp;
&lt;/script&gt;
EOF</span>
      <span style="color: #339933;">,</span>
      <span style="color: #000088;">$prefix</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #339933;">,</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">generateId</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'[day]'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">generateId</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'[month]'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">generateId</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'[year]'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="color: #000088;">$prefix</span><span style="color: #339933;">,</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">generateId</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'[day]'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">generateId</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'[month]'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">generateId</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'[year]'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="color: #000088;">$id</span><span style="color: #339933;">,</span>
      <a href="http://www.php.net/min"><span style="color: #990000;">min</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'years'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <a href="http://www.php.net/max"><span style="color: #990000;">max</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'years'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="color: #000088;">$prefix</span><span style="color: #339933;">,</span> <span style="color: #000088;">$prefix</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$image</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'culture'</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

</li>
<li><b>Explication des modifications :</b>
<ol>
<li>
<b>Ligne 20 :</b><br />
Notre widget dérive désormais de sfWidgetForm<b>I18n</b>Date</p>

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

</li>
<li><b>Lignes 40, 41 et 42:</b><br />
On ajoute les options &laquo;&nbsp;config&nbsp;&raquo;, &laquo;&nbsp;culture&nbsp;&raquo; et &laquo;&nbsp;years&nbsp;&raquo; avec le paramètre &laquo;&nbsp;options&nbsp;&raquo; de la fonction &laquo;&nbsp;configure&nbsp;&raquo; :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p491code66'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49166"><td class="line_numbers"><pre>40
41
42
</pre></td><td class="code" id="p491code66"><pre class="php" style="font-family:monospace;">  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'config'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;config&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'culture'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;culture&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'years'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;years&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

</li>
<li><b>Lignes 85 et 86</b>
<ul>
<li>Il faut inverser l&#8217;ordre du jour et du mois pour être compatible avec un format français, ce qui revient dans un <a href="http://fr.php.net/sprintf">sprintf</a>, à changer l&#8217;ordre des lignes dans le code.
</li>
<li>Il faut faire un <a href="http://www.w3schools.com/jsref/jsref_parseInt.asp">parseInt</a> sur le mois pour transformer &laquo;&nbsp;01&#8243; en &laquo;&nbsp;1&#8243;, parseInt est la fonction javascript permettant de caster une chaîne de caractères en Integer :<br />
Premier paramètre : la chaîne à caster (ici : date.substring(3, 5) )<br />
Deuxième paramètre : Le système numérique à utiliser (ici décimal : 10)
</li>
</li>
</ul>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p491code67'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49167"><td class="line_numbers"><pre>85
86
</pre></td><td class="code" id="p491code67"><pre class="php" style="font-family:monospace;">    \$<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;#<span style="color: #009933; font-weight: bold;">%s</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span><a href="http://www.php.net/date"><span style="color: #990000;">date</span></a><span style="color: #339933;">.</span>substring<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    \$<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;#<span style="color: #009933; font-weight: bold;">%s</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>val<span style="color: #009900;">&#40;</span>parseInt<span style="color: #009900;">&#40;</span><a href="http://www.php.net/date"><span style="color: #990000;">date</span></a><span style="color: #339933;">.</span>substring<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">5</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

</li>
<li><b>Lignes 95 et 109</b>
<ul>
<li>On passe les options directement dans le premier argument.<br />
Le <b>%s</b> de la ligne 95 correspond au  <b>$this->getOption(&#8216;config&#8217;)</b> de la  ligne 109<br />
Le <b>%s</b> de la ligne 98 correspond au  <b>$this->getOption(&#8216;culture&#8217;)</b> de la  ligne 109
</li>
<li>Ligne 109 : passage des options et da la culture au widget.
</li>
</ul>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p491code68'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49168"><td class="line_numbers"><pre>108
</pre></td><td class="code" id="p491code68"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$prefix</span><span style="color: #339933;">,</span> <span style="color: #000088;">$prefix</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'config'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$image</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'culture'</span><span style="color: #009900;">&#41;</span></pre></td></tr></table></div>

</li>
</ul>
</li>
</ol>
<h2>Exemple d&#8217;utilisation</h2>
<ul>
<li><b>Schéma</b>

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

</li>
<li><b>Formulaire (Instanciation du widget)</b>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p491code70'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49170"><td class="code" id="p491code70"><pre class="php" style="font-family:monospace;">  <span style="color: #009900;">&#91;</span><span style="color: #339933;">...</span><span style="color: #009900;">&#93;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1900</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">&lt;</span><span style="color: #cc66cc;">2010</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$years</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$i</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">widgetSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'birthday'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormJQueryI18nDate<span style="color: #009900;">&#40;</span>
      <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'config'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'yearRange: \'1900:2009\', 
                           changeYear: true, 
                           changeMonth: true,'</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'culture'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'fr'</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'years'</span><span style="color: #339933;">=&gt;</span> <a href="http://www.php.net/array_combine"><span style="color: #990000;">array_combine</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$years</span><span style="color: #339933;">,</span> <span style="color: #000088;">$years</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>   
  <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#91;</span><span style="color: #339933;">...</span><span style="color: #009900;">&#93;</span></pre></td></tr></table></div>

</li>
<li><b>Aperçu</b><br />
<img src="http://img152.imageshack.us/img152/8430/jquerydatepickerfr.jpg" title="jquery datepicker fr" alt="jquery datepicker fr" width="450">
</li>
</ul>
<hr />
<h2>Sources</h2>
<ul>
<li>
<em><a href="http://www.symfony-project.org/forms/1_2/en/08-Internationalisation-and-Localisation">Symfony Internationalisation and Localisation</a></em>
</li>
<li>
<em><a href="http://www.symfony-project.org/forms/1_2/en/A-Widgets">Symfony Widgets</a></em>
</li>
<li>
<em><a href="http://jqueryui.com/">jQuery UI</a></em>
</li>
<li>
<em><a href="http://www.remy-solnais.com/jquery-et-datepicker/">Remy Solnais jquery et datepicker en Français</a></em>
</li>
<li>
<em><a href="http://www.w3schools.com/jsref/jsref_parseInt.asp">W3schools parseInt en Javascript</a></em>
</li>
<li>
<em><a href="http://fr.php.net/sprintf">PHP.net fonction sprintf</a></em>
</li>
<li>
<em><a href="http://imageshack.us/">ImageShack</a></em>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/symfony-jquery-datepicker-491/feed</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
	</channel>
</rss>

