<?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 Symfony - Lexik Montpellier &#187; Symfony</title>
	<atom:link href="http://www.lexik.fr/blog/symfony/tag/symfony/feed" rel="self" type="application/rss+xml" />
	<link>http://www.lexik.fr/blog/symfony</link>
	<description>Blog sur le développement Web PHP</description>
	<lastBuildDate>Tue, 20 Jul 2010 08:35:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Force-download avec Symfony</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/force-download-avec-symfony-1237</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/force-download-avec-symfony-1237#comments</comments>
		<pubDate>Tue, 20 Jul 2010 08:35:36 +0000</pubDate>
		<dc:creator>tsyr</dc:creator>
				<category><![CDATA[1.4.x]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[download]]></category>
		<category><![CDATA[force-download]]></category>
		<category><![CDATA[session]]></category>
		<category><![CDATA[téléchargement]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1237</guid>
		<description><![CDATA[Aujourd&#8217;hui, nous allons aborder quelque chose de simple et répandu sur la plupart des sites Internet de nos jours : le téléchargement de fichiers. Bien sûr, il ne s&#8217;agit pas de permettre aux utilisateurs de télécharger votre dernier rush de photos nocturnes sous forme d&#8217;archive zip, ou encore les rapports de la dernière assemblée générale [...]]]></description>
			<content:encoded><![CDATA[<p>Aujourd&#8217;hui, nous allons aborder quelque chose de simple et répandu sur la plupart des sites Internet de nos jours : le téléchargement de fichiers.</p>
<p>Bien sûr, il ne s&#8217;agit pas de permettre aux utilisateurs de télécharger votre dernier rush de photos nocturnes sous forme d&#8217;archive zip, ou encore les rapports de la dernière assemblée générale de votre association en PDF; car ceci ne nécessite en rien l&#8217;intervention de symfony.</p>
<p>Par contre, dès qu&#8217;une action doit être entreprise pour vérifier l&#8217;authenticité de l&#8217;utilisateur, ou ne serait-ce qu&#8217;une table de log pour savoir qui a téléchargé quel fichier, on va avoir besoin de symfony (à moins d&#8217;avoir envie de réinventer la roue).<br />
<span id="more-1237"></span><br />
Pour commencer, une action simple, qui affiche selon votre convenance une liste de fichiers ou le détail d&#8217;un fichier en particulier, mais surtout, un lien de téléchargement. Pour mon exemple, j&#8217;ai déjà fais l&#8217;installation du projet, et du plugin sfDoctrineGuardPlugin (avec les fixtures par défaut du plugin).</p>
<p>Mon schéma de base de données ressemble à ça:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1237code12'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p123712"><td class="code" id="p1237code12"><pre class="yml" style="font-family:monospace;">Software:
  columns:
    name: string
    path: string
    size: integer
&nbsp;
Download:
  options:
    symfony:          { form: false, filter: false }
  actAs:
    Timestampable:
      updated:        { disabled: true }
  columns:
    user_id:          { type: integer(4), notnull: true }
    software_id:      { type: integer(4), notnull: true }
  relations:
    Software:
      local:          software_id
      foreign:        id
      foreignAlias:   Downloads
    User:
      class:          sfGuardUser
      local:          user_id
      foreign:        id
      foreignAlias:   Downloads</pre></td></tr></table></div>

<p>Mes fixtures, à ça:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1237code13'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p123713"><td class="code" id="p1237code13"><pre class="yml" style="font-family:monospace;">Software:
  test:
    name:     symfony latest
    path:     &lt;?php echo sfConfig::get('sf_data_dir') ?&gt;/symfony-1.4.6.tgz
    size:     3233168</pre></td></tr></table></div>

<p>Une fois ceci chargé en base de données, on va pouvoir se lancer dans le développement, et plus particulièrement le téléchargement. Pour me simplifier la tâche lors de cet exemple, un unique fichier pourra être télécharger, ainsi, la route pour lancer le &laquo;&nbsp;download&nbsp;&raquo; du fichier est aussi simple que:</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('p1237code14'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p123714"><td class="code" id="p1237code14"><pre class="yml" style="font-family:monospace;">download:
  class:      sfDoctrineRoute
  url:        /download/:id
  options:
    model:    Software
    type:     object
  param:
    module:   file
    action:   download</pre></td></tr></table></div>

<p>De ce fait, pour télécharger notre fichier d&#8217;exemple, il suffit sur n&#8217;importe quelle page, d&#8217;inclure un lien vers celui-ci, de cette façon:</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('p1237code15'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p123715"><td class="code" id="p1237code15"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>p<span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #990000;">echo</span> link_to<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Télécharger'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'@download'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>p<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>Tout le code sera centralisé dans l&#8217;action, mais je le répète, ce n&#8217;est qu&#8217;à titre d&#8217;exemple, il serait bien plus approprié de faire un lien de ce type:</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('p1237code16'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p123716"><td class="code" id="p1237code16"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>p<span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #990000;">echo</span> link_to<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Télécharger '</span><span style="color: #339933;">.</span><span style="color: #000088;">$file</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'download'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>p<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>Regardons maintenant plus en détail le contenu de notre action «download» du module «file» (cf. la route ci-dessus)</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('p1237code17'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p123717"><td class="code" id="p1237code17"><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> executeDownload<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;">forward404Unless</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAuthenticated</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$file</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: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">forward404Unless</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">file_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Fichier introuvable'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clearHttpHeaders</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;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setContentType</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'application/force-download'</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;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHttpHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-Disposition'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'attachment; filename=&quot;'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">basename</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</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;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHttpHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-Transfer-Encoding'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'binary'</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;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHttpHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-Length'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$file</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSize</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHttpHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Connection'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'close'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setContent</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">send</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>A ce niveau, deux problèmes majeurs se posent:</p>
<ul>
<li>file_get_contents est dépendant du paramètre memory_limit de php</li>
<li>la web_debug_toolbar va venir s&#8217;immiscer dans chaque download</li>
</ul>
<p>Le problème de la web_debug_toolbar peut vite être résolu en la désactivant dans l&#8217;action avec sfConfig::set(&#8216;sf_web_debug_false&#8217;, false) mais il reste le problème du téléchargement de fichiers dont la taille dépasse notre memory_limit. Ce paramètre étant généralement bas en production (128 Mo par défaut), ça peut vite être génant. La solution est d&#8217;utiliser la fonction php <a href="http://fr.php.net/manual/fr/function.readfile.php">readfile()</a> qui elle, envoit directement des blocs de 8 Ko sur la sortie, et donc n&#8217;est pas soumis à la limite d&#8217;utilisation de mémoire PHP.</p>
<p>On remplace donc:</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('p1237code18'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p123718"><td class="code" id="p1237code18"><pre class="php" style="font-family:monospace;">    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setContent</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">send</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>par</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('p1237code19'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p123719"><td class="code" id="p1237code19"><pre class="php" style="font-family:monospace;">    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sendHttpHeaders</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #339933;">@</span><span style="color: #990000;">readfile</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    throw <span style="color: #000000; font-weight: bold;">new</span> sfStopException<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>L&#8217;exception sfStopException() est une manière un peu «crade» de mettre un terme à l&#8217;exécution du script, mais c&#8217;est moins pire qu&#8217;un &laquo;&nbsp;die&nbsp;&raquo; et du coup, ça permet dans un deuxième temps de ne pas être embêté par la web_debug_toolbar.<br />
Il arrive souvent aussi que les headers ne soient pas envoyés, c&#8217;est dû au fait que la sortie est bufferisée, ce problème se résoud avec l&#8217;utilisation des fonctions <a href="http://fr.php.net/manual/fr/function.flush.php">flush()</a> et/ou <a href="http://fr.php.net/manual/fr/function.ob-end-clean.php">ob_end_clean()</a> juste avant le readfile.</p>
<p>Maintenant, on avait pour but de passer par symfony pour enregistrer des logs sur les téléchargements. Rien de plus simple, un exemple pourrait être le code suivant à rajouter après la vérification de l&#8217;existence du fichier (file_exists()) :</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('p1237code20'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p123720"><td class="code" id="p1237code20"><pre class="php" style="font-family:monospace;">    <span style="color: #000088;">$dl</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Download<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$dl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setSoftware</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$dl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setUser</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getGuardUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// other stuff</span>
    <span style="color: #000088;">$dl</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></pre></td></tr></table></div>

<p>A ce stade, tout pourrait sembler correct. C&#8217;était sans compter une fourberie de PHP, qui va bloquer toute autre action sur votre site pendant un téléchargement. En effet, les sessions fonctionnent avec un &laquo;&nbsp;LOCK&nbsp;&raquo; et vu que les sessions sont en auto_start avec symfony, le téléchargement se fait pendant une session, et aucune autre action de la part de l&#8217;utilisateur ne sera accepté pendant un téléchargement, car sa session étant identifiée comme &laquo;&nbsp;en cours d&#8217;écriture&nbsp;&raquo; (le principe de lock).<br />
Une personne ayant déjà rencontré ce problème pourrait se dire qu&#8217;en fermant la session à l&#8217;aide de</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('p1237code21'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p123721"><td class="code" id="p1237code21"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">shutdown</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>dans l&#8217;action résoudrait le problème, et ce n&#8217;est pas le cas, même si en effet, la fonction shutdown() va libérer la session grâce à la fonction <a href="http://fr.php.net/manual/fr/function.session-write-close.php">session_write_close()</a>, elle ne sera exécuté qu&#8217;à la fin du script, donc dans notre cas, ça n&#8217;a aucun intêret, il faut faire le session_write_close() directement dans notre action.</p>
<p>Pour finir, voici le code complet de notre 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('p1237code22'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p123722"><td class="code" id="p1237code22"><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> executeDownload<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;">forward404Unless</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAuthenticated</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$file</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: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">forward404Unless</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">file_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Fichier introuvable'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$dl</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Download<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$dl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setSoftware</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$dl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setUser</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getGuardUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// other stuff</span>
    <span style="color: #000088;">$dl</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>
&nbsp;
    <span style="color: #990000;">session_write_close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clearHttpHeaders</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;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setContentType</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'application/force-download'</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;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHttpHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-Disposition'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'attachment; filename=&quot;'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">basename</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</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;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHttpHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-Transfer-Encoding'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'binary'</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;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHttpHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-Length'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$file</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSize</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setHttpHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Connection'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'close'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sendHttpHeaders</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;">//    @ob_end_clean();</span>
<span style="color: #666666; font-style: italic;">//    flush();</span>
&nbsp;
    <span style="color: #339933;">@</span><span style="color: #990000;">readfile</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    throw <span style="color: #000000; font-weight: bold;">new</span> sfStopException<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>J&#8217;espère que ceci vous aidera dans vos développements actuels et futurs,<br />
@ bientôt.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/force-download-avec-symfony-1237/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Validation d&#8217;un numéro siret : sfValidatorSiret</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/1-4-x/validation-dun-numero-siret-sfvalidatorsiret-1159</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/1-4-x/validation-dun-numero-siret-sfvalidatorsiret-1159#comments</comments>
		<pubDate>Tue, 25 May 2010 06:30:00 +0000</pubDate>
		<dc:creator>thomas</dc:creator>
				<category><![CDATA[1.4.x]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[siret]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[validator]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1159</guid>
		<description><![CDATA[Bonjour, comme vous avez pu le voir avec les récents posts, nous avons eu pas mal de gestion de facturation: conversion de devises, validation d&#8217;un numéro de tva intracommunautaire. Pour continuer sur la lancée, nous allons faire un petit validator sur les numéros siret. Un numéro siret correspond à un petit algorithme assez simple expliqué [...]]]></description>
			<content:encoded><![CDATA[<p>Bonjour,</p>
<p>comme vous avez pu le voir avec les récents posts, nous avons eu pas mal de gestion de facturation: <a title="conversion de devises" href="http://www.lexik.fr/blog/symfony/symfony/tips-conversions-de-devises-1137" target="_blank">conversion de devises</a>, <a title="tva intracommunautaire" href="http://www.lexik.fr/blog/symfony/symfony/un-validator-tva-bien-pratique-1123" target="_blank">validation d&#8217;un numéro de tva intracommunautaire</a>.</p>
<p>Pour continuer sur la lancée, nous allons faire un petit validator sur les numéros siret.</p>
<p><span id="more-1159"></span>Un numéro siret correspond à un petit algorithme assez simple <a title="algorithme numéro siret" href="http://fr.wikipedia.org/wiki/Syst%C3%A8me_d%E2%80%99identification_du_r%C3%A9pertoire_des_%C3%A9tablissements#Calcul_et_validit.C3.A9_d.27un_num.C3.A9ro_SIRET" target="_blank">expliqué ici</a> (<a title="Luhn" href="http://fr.wikipedia.org/wiki/Luhn" target="_blank">algorithme de Luhn</a>)<br />
Le principe est le suivant : on multiplie les chiffres de rang impair à partir de la droite par 1, ceux de rang pair par 2 ; la somme des chiffres obtenus doit être congrue au modulo 10, c&#8217;est-à-dire qu&#8217;elle doit être multiple de 10.<br />
Un numéro siret comporte 14 chiffre.</p>
<p>Voici le code du validator: sfValidatorSiret.class.php</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p1159code24'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p115924"><td class="code" id="p1159code24"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> sfValidatorSiret <span style="color: #000000; font-weight: bold;">extends</span> sfValidatorBase 
<span style="color: #009900;">&#123;</span>
  protected <span style="color: #000000; font-weight: bold;">function</span> doClean<span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$siret</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$siret</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$siret</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #cc66cc;">14</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      throw <span style="color: #000000; font-weight: bold;">new</span> sfValidatorError<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Le numéro siret est invalide'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000088;">$sum</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</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;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">&lt;</span><span style="color: #cc66cc;">14</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: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span><span style="color: #339933;">%</span><span style="color:#800080;">2</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$tmp</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$siret</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: #cc66cc;">2</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$tmp</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$tmp</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">9</span> ? <span style="color: #000088;">$tmp</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">9</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$tmp</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
      <span style="color: #b1b100;">else</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$tmp</span><span style="color: #339933;">=</span> <span style="color: #000088;">$siret</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: #009900;">&#125;</span>
      <span style="color: #000088;">$sum</span> <span style="color: #339933;">+=</span> <span style="color: #000088;">$tmp</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sum</span><span style="color: #339933;">%</span><span style="color:#800080;">10</span> <span style="color: #339933;">!==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      throw <span style="color: #000000; font-weight: bold;">new</span> sfValidatorError<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Le numéro siret est invalide'</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;">$siret</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Pour expliquer rapidement:<br />
1. si la valeur est vide ou de longueur différente de 14 on retourne une exception.<br />
2. on parcours les 14 chiffres, si le chiffre est paire alors on le multiplie par 2 et si ce résultat est supérieur à  9 alors on retranche 9.<br />
ex: 7 =&gt; 7&#215;2 = 14 =&gt; 14 &#8211; 9 = 5.<br />
faire 14 -9  reviens à additionner les 2 chiffres: 1 + 4 = 5.<br />
3. On additionne tous les chiffres paires x2 et les chiffres impaires.<br />
4. si le résultat est divisible par 10 alors c&#8217;est un numéro siret.</p>
<p>Attention ceci indique que le numéro fourni peut être un numéro siret, MAIS PAS que ce numéro est réellement un numéro siret inscrit à L&#8217;INSEE, actif et correspond à une société.</p>
<p><a href="http://www.lexik.fr/blog/symfony/wp-content/uploads/2010/05/sfValidatorSiret.tar.gz">Vous pouvez télécharger le validator ici.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/1-4-x/validation-dun-numero-siret-sfvalidatorsiret-1159/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Développeur Web Symfony Montpellier</title>
		<link>http://www.lexik.fr/blog/symfony/non-classe/travailler-chez-lexik-developpeur-web-symfony-1069</link>
		<comments>http://www.lexik.fr/blog/symfony/non-classe/travailler-chez-lexik-developpeur-web-symfony-1069#comments</comments>
		<pubDate>Fri, 26 Feb 2010 10:41:35 +0000</pubDate>
		<dc:creator>Samuel Breton</dc:creator>
				<category><![CDATA[Non classé]]></category>
		<category><![CDATA[developpeur]]></category>
		<category><![CDATA[montpellier]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=1069</guid>
		<description><![CDATA[Lexik est une société spécialisée dans le développement Symfony et la conception de solutions orientées web. Sous la responsabilité d&#8217;un chef de projet technique, au sein d&#8217;une équipe de développeurs, vous aurez à charge de concevoir et de développer des solutions Intranet / Internet. De formation initiale informatique (de bac à +5), vous êtes un [...]]]></description>
			<content:encoded><![CDATA[<p>Lexik est une société spécialisée dans le développement Symfony et la conception de solutions orientées web.<br />
Sous la responsabilité d&#8217;un chef de projet technique, au sein d&#8217;une équipe de développeurs, vous aurez à charge de concevoir et de développer des solutions Intranet / Internet.</p>
<p>De formation initiale informatique (de bac à +5), vous êtes un développeur confirmé en PHP/MySQL (environnement LAMP et WAMP) avec une expérience d&#8217;au moins 1 ans au sein d&#8217;une SSII ou d&#8217;une web agency.</p>
<p>Compétences requises :<br />
- Framework PHP Symfony<br />
- bonnes connaissances des environnements WAMP (Windows) et LAMP<br />
- MySQL et SQL<br />
- PHP (programmation objet)<br />
- (X)HTML, DHTML , JavaScript, CSS.<br />
- AJAX<br />
- Javascript, jQuery<br />
- standards du web (W3C)<br />
- Connaissance de subversion</p>
<p>Qualités recherchées :<br />
- curiosité<br />
- force de proposition<br />
- sens du travail en équipe</p>
<p>Disponibilité :<br />
- ASAP</p>
<p>Poste à Montpellier 34000</p>
<p>Contactez Samuel Breton, Tél : 04 67 99 63 19<br />
Email : contact@lexik.fr<br />
CV + LM </p>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/non-classe/travailler-chez-lexik-developpeur-web-symfony-1069/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Snippet sfValidatorEmailList</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/12x/snippet-sfvalidatoremaillist-979</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/12x/snippet-sfvalidatoremaillist-979#comments</comments>
		<pubDate>Wed, 14 Oct 2009 07:55:38 +0000</pubDate>
		<dc:creator>yoye</dc:creator>
				<category><![CDATA[1.2.x]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[sfMailer]]></category>
		<category><![CDATA[sfValidator]]></category>
		<category><![CDATA[sfValidatorEmail]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Symfony 1.3]]></category>
		<category><![CDATA[validator]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/blog/symfony/?p=979</guid>
		<description><![CDATA[La version de Symfony 1.3 vient de passer en ALPHA2. Etant en cours de développement d&#8217;un projet sur cette version j&#8217;en profite pour tester les nouvelles fonctionnalités. Parmi celles-ci, il y a le sfMailer. Je ne vais pas m&#8217;étendre sur le sujet car on peut déjà trouver pas mal de posts sur internet concernant cette [...]]]></description>
			<content:encoded><![CDATA[<p>La version de Symfony 1.3 vient de passer en ALPHA2. Etant en cours de développement d&#8217;un projet sur cette version j&#8217;en profite pour tester les nouvelles fonctionnalités. Parmi celles-ci, il y a le sfMailer. Je ne vais pas m&#8217;étendre sur le sujet car on peut déjà trouver pas mal de posts sur internet concernant cette classe notamment dans les jobeet : <a href="http://www.symfony-project.org/jobeet/1_3/Doctrine/en/16">Day 16 The Mailer</a> .</p>
<p>Je me suis par contre amusé à coder un petit validator, qui il me semble, se couple bien avec le sfMailer : sfValidatorEmailList. Son nom est assez explicite mais pourquoi tester des listes de mails ? Tout simplement parceque sfMailer permet d&#8217;envoyer des mails groupés !<br />
  <span id="more-979"></span>
</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('p979code28'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p97928"><td class="code" id="p979code28"><pre class="php" style="font-family:monospace;">  <span style="color: #009933; font-style: italic;">/**
   * Creates a new message.
   *
   * @param string|array $from    The from address
   * @param string|array $to      The recipient(s)
   * @param string       $subject The subject
   * @param string       $body    The body
   *
   * @return Swift_Message A Swift_Message instance
   */</span></pre></td></tr></table></div>

<p>Dans les commentaires de la fonction compose() on peut voir que l&#8217;on a la possibilité de passer un string ou un tableau. sfValidatorEmailList va ainsi nous permettre de valider une liste de mails séparés par un caractère quelconque.</p>
<p>Tout d&#8217;abord je vais créer un formulaire classique qui me permettra de saisir les adresses emails, le sujet et le corps de mon email.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p979code29'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p97929"><td class="code" id="p979code29"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> lkInvitationForm <span style="color: #000000; font-weight: bold;">extends</span> sfForm
<span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setup<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'mailer'</span><span style="color: #009900;">&#41;</span> instanceof sfMailer <span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            throw <span style="color: #000000; font-weight: bold;">new</span> RuntimeException<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'A valid mailer option is required to send an email from this form'</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;">setWidgets</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'email'</span>         <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormInputText<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Adresse(s) email'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'title'</span>         <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormInputText<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'titre du mail'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'body'</span>          <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormTextarea<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Corps du mail'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setValidators</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'email'</span>   <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorEmailList<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'required'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'invalid'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'&quot;%value%&quot; invalide'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'title'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorString<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'required'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'invalid'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'&quot;%value%&quot; invalide'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'body'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorString<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'required'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'invalid'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'&quot;%value%&quot; invalide'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">widgetSchema</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setNameFormat</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'invitation[%s]'</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;">errorSchema</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorErrorSchema<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Bind form and send mail
     *
     * @param sfWebRequest $request
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> bindAndSend<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span> <span style="color: #000088;">$taintedValues</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$taintedValues</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</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;">isValid</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$mailer</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'mailer'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #000088;">$mailer</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">composeAndSend</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'contact@lexik.fr'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'email'</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;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'title'</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;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'body'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>J&#8217;utilise donc pour mon email le sfValidatorEmailList dont voici le 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('p979code30'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p97930"><td class="code" id="p979code30"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> sfValidatorEmailList <span style="color: #000000; font-weight: bold;">extends</span> sfValidatorEmail
<span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * @see sfValidatorEmail
   */</span>
    protected <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> <span style="color: #990000;">array</span><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> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        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>
&nbsp;
        <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;">'separator'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">','</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * @see sfValidatorString
   */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> doClean<span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$retVal</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$valueError</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$mails</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><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;">'separator'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</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;">$mails</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$mail</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            try
            <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$retVal</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">doClean</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mail</span><span style="color: #009900;">&#41;</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: #000088;">$valueError</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$e</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">empty</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$valueError</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            throw <span style="color: #000000; font-weight: bold;">new</span> sfValidatorError<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'invalid'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'value'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">', '</span><span style="color: #339933;">,</span> <span style="color: #000088;">$valueError</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>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$retVal</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h4>Quelques explications :</h4>
<p>Au niveau de la configuration on peut indiquer quel sera le caractère de séparation. Ensuite, la fonction doClean() qui se charge de tester la validité d&#8217;une valeur va transformer le string que l&#8217;on récupère en tableau et va appeler le doClean de sfEmailValidator. Afin de permettre un rendu plus propre du message d&#8217;erreur, j&#8217;utilise un try-catch qui me permet de lister tous les emails invalides. Une fois la boucle terminée, je n&#8217;ai plus qu&#8217;a créer mon exception avec toutes les valeurs catchées.<br />
Je peux par la suite passer le $this->getValue(&#8216;email&#8217;) à ma fonction composeAndSend() puisque le validator me retourne un tableau.</p>
<h4>Exemple d&#8217;une erreur dans un seul email</h4>
<p><img class="alignnone size-full wp-image-982" title="simple_erreur" src="http://www.lexik.fr/blog/symfony/wp-content/uploads/2009/10/simple_erreur.png" alt="simple_erreur" width="323" height="75" /></p>
<h4>Exemple d&#8217;une erreur dans plusieurs emails</h4>
<p><img class="alignnone size-full wp-image-981" title="double_erreur" src="http://www.lexik.fr/blog/symfony/wp-content/uploads/2009/10/double_erreur.png" alt="double_erreur" width="311" height="79" /></p>
<p>Maintenant lorsque j&#8217;affiche mon formulaire, les utilisateurs pourront saisir des adresses emails séparées d&#8217;une virgule pour envoyer à plusieurs contacts.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/12x/snippet-sfvalidatoremaillist-979/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Réflexions sur l&#8217;élaboration d&#8217;un bon backend</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/12x/reflexions-sur-lelaboration-dun-bon-backend-958</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/12x/reflexions-sur-lelaboration-dun-bon-backend-958#comments</comments>
		<pubDate>Wed, 30 Sep 2009 08:00:20 +0000</pubDate>
		<dc:creator>Calu</dc:creator>
				<category><![CDATA[1.2.x]]></category>
		<category><![CDATA[Admingenerator 1.2.x]]></category>
		<category><![CDATA[Méthodologie]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[methode]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/sfblog/?p=958</guid>
		<description><![CDATA[Lors de la réalisation de vos projets, l&#8217;étape de la construction du backend est devenue un passage obligatoire. Que cela soit un souhait initial du client ou une envie de pouvoir proposer une prise en main du site via une interface, le backoffice justifie pleinement sa présence et son importance. Cette philosophie est très largement [...]]]></description>
			<content:encoded><![CDATA[<p>Lors de la réalisation de vos projets, l&#8217;étape de la construction du backend est devenue un passage obligatoire. Que cela soit un souhait initial du client ou une envie de  pouvoir proposer une prise en main du site via une interface, le backoffice justifie pleinement sa présence et son importance. Cette philosophie est très largement soutenue par Symfony avec son générateur CRUD d&#8217;admin, ses filters, l&#8217;extensibilité de ses templates, l&#8217;internationalisation&#8230;</p>
<p>Le but de cet article est de chercher plus loin dans les fonctionnalités de base proposées par Symfony pour l&#8217;élaboration de notre backend.</p>
<h3><span id="more-958"></span>La Homepage</h3>
<p>Proposer à l&#8217;administrateur l&#8217;affichage d&#8217;une page de listing d&#8217;un modèle, dès le login effectué,  est bien sûr une mauvaise idée. Une page d&#8217;accueil doit être présente et peut présenter les différentes informations pertinentes et vitales pour l&#8217;administrateur :</p>
<div id="attachment_960" class="wp-caption alignnone" style="width: 310px"><a href="http://www.lexik.fr/blog/symfony/wp-content/uploads/2009/09/Capture-1.png"><img class="size-medium wp-image-960" title="Accueil" src="http://www.lexik.fr/blog/symfony/wp-content/uploads/2009/09/Capture-1-300x91.png" alt="Accueil du backoffice : Statistiques et accés" width="300" height="91" /></a><p class="wp-caption-text">Accueil du backoffice : Statistiques et accés</p></div>
<p>Dans cette capture, l&#8217;accueil permet dès l&#8217;authentification, de connaitre les différentes statistiques du site et d&#8217;avoir un accés direct aux actions redondantes mais nécessaires : Utilisateurs en attente de validation, Visualisation de messages suspects etc&#8230;</p>
<p>Pour aller plus loin, vous pouvez afficher certaines indications propres à la fréquentation sur votre site. Si vous possédez un compte <a title="Google Analytics" href="www.Google.com/Analytics">Google Analytics</a>, c&#8217;est l&#8217;occasion d&#8217;en profiter ! En effet, une API pour accéder à ses statistiques est disponible depuis peu, et devinez quoi ? Il existe un plugin Symfony pour l&#8217;utiliser : <a title="sfGoogleAnalyticsPlugin : Un plugin Symfony pour Google Analytics" href="http://www.symfony-project.org/plugins/sfGoogleAnalyticsPlugin">sfGoogleAnalyticsPlugin</a>. Alors plus d&#8217;excuses pour ne plus proposer une page d&#8217;accueil efficace à votre client.</p>
<h3>Un listing précis et concis</h3>
<p>Par défault, Symfony propose un listing complet des différents champs de votre modèle. Cela est souvent beaucoup trop confus et non adapté pour les besoins d&#8217;un client :</p>
<p><a href="http://www.lexik.fr/blog/symfony/wp-content/uploads/2009/09/mauvais-listing.png"><img class="alignnone size-medium wp-image-963" title="Mauvais listing" src="http://www.lexik.fr/blog/symfony/wp-content/uploads/2009/09/mauvais-listing-300x19.png" alt="Mauvais listing" width="300" height="19" /></a></p>
<p>Il apparait comme  essentiel de sélectionner et de renommer  les différentes colonnes de votre modèle que vous souhaitez afficher. De même, selon la complexité de votre objet, il peut être intéressant de fournir des informations &laquo;&nbsp;associées&nbsp;&raquo; : Pour un objet <em>Article de Blog</em>, il est pertinent d&#8217;afficher le nombre de <em>Commentaire</em>s associés. Dans mon cas, j&#8217;affiche le nombre d&#8217;utilisateurs associés à un projet :</p>
<p><a href="http://www.lexik.fr/blog/symfony/wp-content/uploads/2009/09/listing.png"><img class="alignnone size-medium wp-image-967" title="listing" src="http://www.lexik.fr/blog/symfony/wp-content/uploads/2009/09/listing-300x54.png" alt="listing" width="300" height="54" /></a></p>
<p>Concernant les valeurs, il est déconseillé d&#8217;utiliser des IDs. Ils apportent aucune information quantitative ou qualitative pour l&#8217;administrateur. De plus, il est préférable de créer une action pour les tâches répétitives. Cela simplifie grandement l&#8217;administration pour un client et on évite ainsi de l&#8217;envoyer directement sur les pages d&#8217;éditions.</p>
<p>La <a href="http://www.symfony-project.org/book/1_2/14-Generators#chapter_14_generator_configuration">documentation</a> de Symfony étant très complète sur ce sujet, nous allons continuer notre tour d&#8217;horizon avec les filters.</p>
<h3>Les filtres au service de la navigation</h3>
<p>Symfony permet à l&#8217;aide du générateur d&#8217;administration, de trier vos modèles en fonction de filtres spécifiques. Mais comme pour la partie précédente, les problèmes sont similaires : Trop de champs renseignables, souvent complexes et non traduits. Outre la documentation de Symfony qui vient encore une fois à notre aide, il faudra faire un tour sur <a href="http://www.zen-in-progress.com/post/symfony-traduction-des-filtres-de-l-admin-generateur" target="_blank">cet article</a> pour compléter la traduction des filtres sur le backend.</p>
<p>Mais la véritable force des filtres, c&#8217;est leur utilisation de manière transparente par le client. En effet, si on reprend l&#8217;exemple de notre page d&#8217;accueil, on propose un lien &laquo;&nbsp;<em>3 projets en attente&nbsp;&raquo;</em> sensé rediriger sur les projets concernés.</p>
<h4>Comment cela est-il possible ?</h4>
<p>Tout simplement en créant le filtre qui nous permet de trier nos projets, dès le chargement de la page. La manière la plus simple est de passer nos filtres dans l&#8217;URL.</p>
<h4>Mise en place</h4>
<p>Il faut d&#8217;abord surcharger notre action index du module concerné :</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('p958code38'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p95838"><td class="code" id="p958code38"><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>sfWebRequest <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getParameter<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'filter'</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;">-&amp;</span>gt<span style="color: #339933;">;</span>setFilters<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getParameter<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'filter'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        parent<span style="color: #339933;">::</span><span style="color: #004000;">executeIndex</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>On vérifie si l&#8217;on passe un paramètre &laquo;&nbsp;filter&nbsp;&raquo; lors du chargement de la page. Le cas échéant, on applique les filtres renseignés.</p>
<p>Mon lien permettant de voir seulement les utilisateurs en attente de validation aura le routing :</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('p958code39'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p95839"><td class="code" id="p958code39"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">@</span>user_user?filter<span style="color: #009900;">&#91;</span>is_active<span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span></pre></td></tr></table></div>

<p>Pour mes projets en attente de validation, c&#8217;est la pratiquement la même chose, on indique en plus le type de l&#8217;argument.</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('p958code40'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p95840"><td class="code" id="p958code40"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">@</span>project_project?filter<span style="color: #009900;">&#91;</span>state<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>text<span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #cc66cc;">1</span></pre></td></tr></table></div>

<p>Pensez à bien regarder la structure de vos filtres en cas d&#8217;erreur.</p>
<h4>Allez plus loin</h4>
<p>Maintenant que vous savez filtrer directement à partir d&#8217;un lien, vous allez pouvoir vous servir de cette astuce autre part que sur la page d&#8217;accueil. Revenons sur nos listing. Nous avons vu qu&#8217;il était pratique pour le client d&#8217;afficher par exemple le nombre d&#8217;objet <em>Commentaire</em> associés à un objet <em>Article</em>. Nous sommes maintenant capables de rediriger directement vers les objets associés.</p>
<p>On ajoute une méthode d&#8217;affichage sur notre objet <em>Article</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('p958code41'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p95841"><td class="code" id="p958code41"><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> getCountPositioning<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> link_to<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getComments<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>count<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'@comment_comment?filter[article_id]='</span><span style="color: #339933;">.</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>Id<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>On retourne ainsi le lien contenant le filtre permettant de trier les commentaires en fonction de l&#8217;ID de l&#8217;article. Il suffit de modifer notre action index afin de correctement afficher notre entité HTML :</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('p958code42'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p95842"><td class="code" id="p958code42"><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>sfWebRequest <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_escaping_strategy'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getParameter<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'filter'</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;">-&amp;</span>gt<span style="color: #339933;">;</span>setFilters<span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getParameter<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'filter'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        parent<span style="color: #339933;">::</span><span style="color: #004000;">executeIndex</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</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à pour nos petites idées pour vous aider à parfaire votre back office. N&#8217;hésitez pas à parlez de vos astuces dans les commentaires.</p>
<h3>Mise à jour</h3>
<p lang="php">La désactivation de la stratégie d&#8217;échappement des caractères (<em>sfConfig::set(&#8216;sf_escaping_strategy&#8217;, false)) </em>est utilisée pour éviter l&#8217;affichage des balises &lt;a&gt; obtenues depuis notre modèle. Cette méthode à deux limites : D&#8217;une part, elle est inhérente à certaines failles de sécurité provoquées par une injection de code malicieux (cf commentaire de @Niko) ; D&#8217;autre part, on perd l&#8217;avantage lié à notre MVC en faisant parvenir le lien directement depuis le modèle.</p>
<p>Il est alors conseillé de déclarer dans notre <em>generator.yml </em>l&#8217;utilisation des partials pour afficher nos liens filtrants :</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('p958code43'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p95843"><td class="code" id="p958code43"><pre class="php" style="font-family:monospace;">display<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>_countComments<span style="color: #009900;">&#93;</span></pre></td></tr></table></div>

<p>Il suffit alors de créer notre partial <em>_countComments.php</em> dans le dossier <em>templates</em>/ de notre module :</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('p958code44'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p95844"><td class="code" id="p958code44"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span>?php <span style="color: #990000;">echo</span> link_to<span style="color: #009900;">&#40;</span><span style="color: #000088;">$article</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getComments<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>count<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'@comments_comments?filter[article_id]='</span><span style="color: #339933;">.</span><span style="color: #000088;">$article</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>getId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>?<span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/12x/reflexions-sur-lelaboration-dun-bon-backend-958/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Gestion d&#8217;une galerie photo avec swfUpload dans l&#8217;admin</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/gestion-dune-galerie-photo-avec-swfupload-dans-ladmin-918</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/gestion-dune-galerie-photo-avec-swfupload-dans-ladmin-918#comments</comments>
		<pubDate>Wed, 16 Sep 2009 09:49:18 +0000</pubDate>
		<dc:creator>olivier</dc:creator>
				<category><![CDATA[1.2.x]]></category>
		<category><![CDATA[Admingenerator 1.2.x]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[admin generator]]></category>
		<category><![CDATA[swfUpload]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/sfblog/?p=918</guid>
		<description><![CDATA[Je vous propose de voir une gestion de galerie photo pour l'administration, telle que je l'ai abordée dans un de mes derniers projets.
C'est à dire avec swfUpload et en ajax dans l'admin generator.]]></description>
			<content:encoded><![CDATA[<p>Je vous propose de voir une gestion de galerie photo pour l&#8217;administration, telle que je l&#8217;ai abordée dans un de mes derniers projets.</p>
<p>Pour vous situer, il s&#8217;agit d&#8217;un site de vente en ligne.<br />
Qui dit vente dit produits, et qui dit produits dit photos <img src='http://www.lexik.fr/blog/symfony/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /><br />
<span id="more-918"></span><br />
L&#8217;idée est de gérer les photos d&#8217;un produit directement depuis sa page d&#8217;édition de l&#8217;admin générator.</p>
<p><img src="http://www.lexik.fr/blog/symfony/wp-content/uploads/2009/09/upload1-300x99.png" alt="upload1" title="upload1" width="300" height="99" class="alignnone size-medium wp-image-921" /></p>
<p><img src="http://www.lexik.fr/blog/symfony/wp-content/uploads/2009/09/upload2-300x184.png" alt="upload2" title="upload2" width="300" height="184" class="alignnone size-medium wp-image-922" /></p>
<p><img src="http://www.lexik.fr/blog/symfony/wp-content/uploads/2009/09/upload3-300x178.png" alt="upload3" title="upload3" width="300" height="178" class="alignnone size-medium wp-image-923" /></p>
<p>On a choisi de gérer l&#8217;upload avec swfUpload qui gére un liste d&#8217;attente pour l&#8217;upload de plusieurs fichiers. Et l&#8217;upload en background qui ne gèle pas la page, ca fait plus web2.0 :p<br />
(<a href="http://code.google.com/p/swfupload/" tager="_blank">http://code.google.com/p/swfupload/</a>)</p>
<p>J&#8217;ai téléchargé le <a href="http://swfupload.googlecode.com/files/SWFUpload%20v2.2.0.1%20Samples.zip" target="_blank">SWFUpload v2.2.0.1 Samples.zip</a> et j&#8217;ai utilisé les fichiers du répertoire &laquo;&nbsp;simpledemo&nbsp;&raquo; que j&#8217;ai réparties comme suis.<br />
(Le fichier css d&#8217;origine s&#8217;appelait default.css, je l&#8217;ai renommé pour des raisons évidentes.)</p>
<ul>
<li>/web/swf/swfupload.swf</li>
<li>/web/css/swfUpload.css</li>
<li>/web/js/swfupload.js</li>
<li>/web/js/swfupload.queue.js</li>
<li>/web/js/fileprogress.js</li>
<li>/web/js/handlers.js</li>
<li>/web/images/XPButtonUploadText_61x22.png</li>
</ul>
<p>Un coup d&#8217;oeil rapide à la partie du schema.yml qui nous intéresse. Rien de transcendant, un objet Produit avec quelques champs types et l&#8217;objet ProduitPhoto qui lui est lié. Sur l&#8217;objet ProduitPhoto, un filename et un booléen pour définir l&#8217;image  par défaut du produit.</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('p918code45'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91845"><td class="code" id="p918code45"><pre class="yml" style="font-family:monospace;">...
Produit:
  tableName:        monprojet_produit
  actAs:
    Timestampable:  ~
  columns:
    id:             { type: integer(4), unsigned: true, primary: true, autoincrement: true }
    nom:            { type: string(255), notnull: true }
    description:    { type: clob }
    prix:           { type: decimal, scale: 2 }
&nbsp;
ProduitPhoto:
  tableName:        monprojet_produit_photo
  columns:
    id:             { type: integer(4), unsigned: true, primary: true, autoincrement: true }
    produit_id:     { type: integer(4), unsigned: true }
    filename:       { type: string(255), notnull: true }
    is_default:     { type: boolean, default: false }
  relations:
    Produit:
      local:        produit_id
      foreign:      id
      foreignAlias: Photos
      onDelete:     CASCADE
...</pre></td></tr></table></div>

<p>On génére l&#8217;admin-generator pour l&#8217;objet produit.</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('p918code46'); return false;">View Code</a> CONSOLE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91846"><td class="code" id="p918code46"><pre class="console" style="font-family:monospace;">./symfony doctrine:generate-admin backend Produit</pre></td></tr></table></div>

<p>Et c&#8217;est partie !</p>
<p>Pour rajouter cette gestion des images dans l&#8217;ecran d&#8217;édition des produits il faut rajouter un partial à la vue edit.<br />
(On la rajoute uniquement sur l&#8217;edit, car sur l&#8217;écran create, l&#8217;objet n&#8217;est pas encore persisté en base et donc on ne peut pas lui rattacher des objets ProduitPhoto)</p>
<p>Le fonctionnement est le suivant. Le partial général où est inclus et configuré swfUpload (_photoUpload.php). Un parial _photoListe.php inclus dans _photoUpload.php qui servira pour raffraichir la liste en ajax (avec jQuery). Et un dernier partial _ajaxPhotoDelete.php qui ne sert qu&#8217;a retourner l&#8217;animation à faire lors de la suppression d&#8217;une photo.</p>
<p>On commence par positionner le partial _photoUpload.php dans le generator.yml en contexte edit.</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('p918code47'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91847"><td class="code" id="p918code47"><pre class="yml" style="font-family:monospace;">generator:
  class: sfDoctrineGenerator
  param:
    model_class:           Produit
    theme:                 admin
    non_verbose_templates: true
    with_show:             false
    singular:              ~
    plural:                ~
    route_prefix:          produit_produit
    with_doctrine_route:     1
&nbsp;
    config:
      actions: ~
      fields:
        created_at:        { label: Date de création, date_format: dd/MM/yyyy }
        updated_at:        { label: Date de modification, date_format: dd/MM/yyyy }
        nom:               { label: Nom }
        description:       { label: Déscription }
      list:
        title:             Liste des produits
        display:           [=id, =nom]
      filter: ~
      form: ~
      edit:
        title:             Modifier un produit
        display:
          &quot;Produit&quot;:       [id, nom, description]
          &quot;Photos&quot;:        [_photoUpload]
          &quot;Dates&quot;:         [created_at, updated_at]
      new:
        title:             Ajouter un produit
        display:
          &quot;Produit&quot;:       [id, nom, description]
          &quot;Dates&quot;:         [created_at, updated_at]</pre></td></tr></table></div>

<p>Et on va se pencher plus en détail sur ce partial _photoUpload.php.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p918code48'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91848"><td class="code" id="p918code48"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> use_stylesheet<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'swfUpload.css'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> use_javascript<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'jquery.js'</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> use_javascript<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'jquery-ui.js'</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> use_javascript<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'swfupload.js'</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> use_javascript<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'swfupload.queue.js'</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> use_javascript<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'fileprogress.js'</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> use_javascript<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'handlers.js'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
<span style="color: #339933;">&lt;</span>div id<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;pictures_list&quot;</span> <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;sf_admin_form_row&quot;</span><span style="color: #339933;">&gt;</span>
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> include_partial<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'produit/photoListe'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'photos'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$form</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;">-&gt;</span><span style="color: #004000;">getPhotos</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
&nbsp;
<span style="color: #339933;">&lt;</span>div id<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;picture_upload&quot;</span> <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;sf_admin_form_row&quot;</span><span style="color: #339933;">&gt;</span>
  <span style="color: #339933;">&lt;</span>div <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;fieldset flash&quot;</span> id<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;fsUploadProgress&quot;</span><span style="color: #339933;">&gt;&lt;</span>span <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;legend&quot;</span><span style="color: #339933;">&gt;</span>File d<span style="color: #0000ff;">'attente.&lt;/span&gt;&lt;/div&gt;
  &lt;div id=&quot;divStatus&quot;&gt;0 fichier uploadé.&lt;/div&gt;
  &lt;div&gt;
    &lt;span id=&quot;spanButtonPlaceHolder&quot;&gt;&lt;/span&gt;
    &lt;input id=&quot;btnCancel&quot; type=&quot;button&quot; value=&quot;Cancel All Uploads&quot; onclick=&quot;$.swfUpload.cancelQueue();&quot; disabled=&quot;disabled&quot; style=&quot;margin-left: 2px; font-size: 8pt; height: 29px;&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;
&nbsp;
&lt;script type=&quot;text/javascript&quot;&gt;
&nbsp;
(function($) {
&nbsp;
  $('</span>div<span style="color: #339933;">.</span>actions a<span style="color: #339933;">.</span><span style="color: #000000; font-weight: bold;">default</span><span style="color: #0000ff;">').live('</span>click<span style="color: #0000ff;">', function(event) {
    event.preventDefault();
    $.post(
      $(this).attr('</span>href<span style="color: #0000ff;">'),
      { },
      function(data) {
        $('</span><span style="color: #666666; font-style: italic;">#pictures_list').html(data);</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>
&nbsp;
  $<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'div.actions a.delete'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>live<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'click'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    event<span style="color: #339933;">.</span>preventDefault<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>confirm<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Etes vous sur de vouloir supprimer cette photo ?'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      $<span style="color: #339933;">.</span>post<span style="color: #009900;">&#40;</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;">'href'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
        <span style="color: #009900;">&#123;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        <span style="color: #000000; 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: #990000;">eval</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;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  myQueueComplete <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>numFilesUploaded<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">var</span> status <span style="color: #339933;">=</span> document<span style="color: #339933;">.</span>getElementById<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;divStatus&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    status<span style="color: #339933;">.</span>innerHTML <span style="color: #339933;">=</span> numFilesUploaded <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot; fichier&quot;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>numFilesUploaded <span style="color: #339933;">===</span> <span style="color: #cc66cc;">1</span> ? <span style="color: #0000ff;">&quot;&quot;</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;s&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot; uploadé&quot;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>numFilesUploaded <span style="color: #339933;">===</span> <span style="color: #cc66cc;">1</span> ? <span style="color: #0000ff;">&quot;&quot;</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;s&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;.&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    $<span style="color: #339933;">.</span>post<span style="color: #009900;">&#40;</span>
      <span style="color: #0000ff;">'&lt;?php echo url_for('</span>produit_ajax_photo_liste<span style="color: #0000ff;">', $form-&gt;getObject()) ?&gt;'</span><span style="color: #339933;">,</span>
      <span style="color: #009900;">&#123;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
      <span style="color: #000000; 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: #0000ff;">'#pictures_list'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>html<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: #339933;">;</span>
&nbsp;
  jQuery<span style="color: #339933;">.</span>swfUpload <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SWFUpload<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
    flash_url<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;/swf/swfupload.swf&quot;</span><span style="color: #339933;">,</span>
    upload_url<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;&lt;?php echo url_for('produit_photo', <span style="color: #006699; font-weight: bold;">$form-&gt;getObject</span>()) ?&gt;&quot;</span><span style="color: #339933;">,</span>
    post_params<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><span style="color: #0000ff;">&quot;&lt;?php echo ini_get('session.name') ?&gt;&quot;</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;&lt;?php echo session_id(); ?&gt;&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    file_size_limit<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;100 MB&quot;</span><span style="color: #339933;">,</span>
    file_types<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;*.jpg;*.gif;*.png&quot;</span><span style="color: #339933;">,</span>
    file_types_description<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;Fichiers image&quot;</span><span style="color: #339933;">,</span>
    file_upload_limit<span style="color: #339933;">:</span> <span style="color: #cc66cc;">10</span><span style="color: #339933;">,</span>
    file_queue_limit<span style="color: #339933;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span>
    file_post_name<span style="color: #339933;">:</span> <span style="color: #0000ff;">'photo'</span><span style="color: #339933;">,</span>
    custom_settings<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
      progressTarget<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;fsUploadProgress&quot;</span><span style="color: #339933;">,</span>
      cancelButtonId<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;btnCancel&quot;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    debug<span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #339933;">,</span>
    <span style="color: #666666; font-style: italic;">// Button settings</span>
    button_image_url<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;/images/XPButtonUploadText_61x22.png&quot;</span><span style="color: #339933;">,</span>
    button_width<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;61&quot;</span><span style="color: #339933;">,</span>
    button_height<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;22&quot;</span><span style="color: #339933;">,</span>
    button_placeholder_id<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;spanButtonPlaceHolder&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #666666; font-style: italic;">// The event handler functions are defined in handlers.js</span>
    file_queued_handler<span style="color: #339933;">:</span> fileQueued<span style="color: #339933;">,</span>
    file_queue_error_handler<span style="color: #339933;">:</span> fileQueueError<span style="color: #339933;">,</span>
    file_dialog_complete_handler<span style="color: #339933;">:</span> fileDialogComplete<span style="color: #339933;">,</span>
    upload_start_handler<span style="color: #339933;">:</span> uploadStart<span style="color: #339933;">,</span>
    upload_progress_handler<span style="color: #339933;">:</span> uploadProgress<span style="color: #339933;">,</span>
    upload_error_handler<span style="color: #339933;">:</span> uploadError<span style="color: #339933;">,</span>
    upload_success_handler<span style="color: #339933;">:</span> uploadSuccess<span style="color: #339933;">,</span>
    upload_complete_handler<span style="color: #339933;">:</span> uploadComplete<span style="color: #339933;">,</span>
    queue_complete_handler<span style="color: #339933;">:</span> myQueueComplete
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>jQuery<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span></pre></td></tr></table></div>

<p>Il faut penser à inclure les différents éléments nécessaires le css et les tout les js. Je les ai inclus ici pour bien les mettre en évidence.<br />
Après il suffit de positionner les différents éléments html nécessaires au fonctionnement de swfUpload.<br />
Et enfin le javascript pour initialiser swfUpload. J&#8217;utilise jQuery pour gérer l&#8217;ajax, j&#8217;ai donc adapté l&#8217;initialisation de swfUpload pour la rendre &laquo;&nbsp;jQuery friendly&nbsp;&raquo; :p</p>
<p>L&#8217;initialisation de swfUpload est assez standard, avec toute une tripoté de paramètres pour définir : le type de fichier accepté, configurer l&#8217;apparence du bouton et configurer tous les retour d&#8217;événements qu&#8217;il est possible d&#8217;utiliser.<br />
J&#8217;ai laissé les gestionnaires d&#8217;événements par défaut à l&#8217;exception de l&#8217;événement de fin d&#8217;upload (myQueueComplete) que j&#8217;ai redéfini pour faire un appel ajax et recharger le partial _photoListe.php.<br />
J&#8217;attire votre attention sur le parametre post_params auquel on passe le session name et le session_id, on verra un peu plus bas le pourquoi du comment <img src='http://www.lexik.fr/blog/symfony/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Le partial _photoListe.php, rien de spécial. Un listing des photos du produit avec 2 liens pour supprimer ou définir comme image par défaut, les 2 faisant appel à une action en ajax.<br />
(NB: On retrouve <a href="http://www.lexik.fr/blog/symfony/symfony/generer-des-thumbs-lors-de-laffichage-dune-image-781" target="_blank">le Helper Thumb de thomas</a> pour les miniatures des photos)</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('p918code49'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91849"><td class="code" id="p918code49"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> use_helper<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Thumb'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$photos</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$photos</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$photo</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #339933;">&lt;</span>div id<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;photo-&lt;?php echo <span style="color: #006699; font-weight: bold;">$photo-&gt;getId</span>()?&gt;&quot;</span> <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;picture&quot;</span><span style="color: #339933;">&gt;</span>
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #990000;">echo</span> showThumb<span style="color: #009900;">&#40;</span>
  <span style="color: #000088;">$photo</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFilename</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
  <span style="color: #0000ff;">'produits'</span><span style="color: #339933;">,</span>
  <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'height'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">120</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'width'</span>  <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">120</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'alt'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$photo</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getProduit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</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: #339933;">,</span>
    <span style="color: #0000ff;">'title'</span>  <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$photo</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getProduit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</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: #339933;">,</span>
    <span style="color: #0000ff;">'border'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">0</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
  <span style="color: #0000ff;">'center'</span><span style="color: #339933;">,</span>
  <span style="color: #0000ff;">'produit-defaut.jpg'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  <span style="color: #339933;">&lt;</span>div <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;actions&quot;</span><span style="color: #339933;">&gt;</span>
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$photo</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    <span style="color: #339933;">&lt;</span>strong<span style="color: #339933;">&gt;&lt;</span>img src<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;/images/backend/star.png&quot;</span> align<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;left&quot;</span> <span style="color: #339933;">/&gt;</span> Par défaut<span style="color: #339933;">&lt;/</span>strong<span style="color: #339933;">&gt;</span>
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">else</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    <span style="color: #339933;">&lt;</span>ul<span style="color: #339933;">&gt;</span>
      <span style="color: #339933;">&lt;</span>li<span style="color: #339933;">&gt;&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&lt;?php echo url_for('produit_photo_ajax_default', <span style="color: #006699; font-weight: bold;">$photo</span>) ?&gt;&quot;</span> <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;default&quot;</span><span style="color: #339933;">&gt;&lt;</span>img src<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;/images/backend/star.png&quot;</span> align<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;left&quot;</span> <span style="color: #339933;">/&gt;</span> Par défaut<span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;&lt;/</span>li<span style="color: #339933;">&gt;</span>
      <span style="color: #339933;">&lt;</span>li<span style="color: #339933;">&gt;&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&lt;?php echo url_for('produit_photo_ajax_delete', <span style="color: #006699; font-weight: bold;">$photo</span>) ?&gt;&quot;</span> <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;delete&quot;</span><span style="color: #339933;">&gt;&lt;</span>img src<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;/images/backend/cross.png&quot;</span> align<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;left&quot;</span> <span style="color: #339933;">/&gt;</span> Supprimer<span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;&lt;/</span>li<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;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #339933;">&lt;</span>div <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;clear&quot;</span><span style="color: #339933;">&gt;&lt;/</span>div<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">else</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #339933;">&lt;</span>p<span style="color: #339933;">&gt;</span>Aucune photo pour l<span style="color: #0000ff;">'instant.&lt;/p&gt;
&lt;?php endif; ?&gt;</span></pre></td></tr></table></div>

<p>Le partial _ajaxPhotoDelete.php, c&#8217;est juste l&#8217;effet jQuery-ui pour faire disparaitre la div de la photo qui viens d&#8217;être supprimée.</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('p918code50'); return false;">View Code</a> JAVASCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91850"><td class="code" id="p918code50"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#photo-&lt;?php echo $photo_id ?&gt;'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">effect</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'drop'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Un petit tour sur le routing.yml pour défnir les différentes routes utilisées.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p918code51'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91851"><td class="code" id="p918code51"><pre class="yml" style="font-family:monospace;">...
produit_photo:
  url:     /produit/:id/upload
  class:   sfDoctrineRoute
  options: { model: Produit, type: object }
  param:   { module: produit, action: upload }
  requirements:
    sf_method: [get, post]
&nbsp;
produit_photo_ajax_default:
  url:     /produit_photo/:id/default
  class:   sfDoctrineRoute
  options: { model: ProduitPhoto, type: object }
  param:   { module: produit, action: ajaxPhotoDefault }
  requirements:
    sf_method: [post]
&nbsp;
produit_photo_ajax_delete:
  url:     /produit_photo/:id/delete
  class:   sfDoctrineRoute
  options: { model: ProduitPhoto, type: object }
  param:   { module: produit, action: ajaxPhotoDelete }
  requirements:
    sf_method: [post]
&nbsp;
produit_ajax_photo_liste:
  url:     /produit_photo/:id/list
  class:   sfDoctrineRoute
  options: { model: Produit, type: object }
  param:   { module: produit, action: ajaxPhotoListe }
  requirements:
    sf_method: [post]
...</pre></td></tr></table></div>

<p>On utilise la classe formulaire qui va gérer l&#8217;upload.<br />
Il faut désactiver le csrf car l&#8217;envoie n&#8217;est pas effectué par le formulaire mais par l&#8217;animation flash.</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('p918code52'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91852"><td class="code" id="p918code52"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> ProduitPhotoForm <span style="color: #000000; font-weight: bold;">extends</span> BaseProduitPhotoForm
<span style="color: #009900;">&#123;</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: #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;">'produit_id'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormInputHidden<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;">widgetSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'is_default'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormInputHidden<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;">widgetSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'filename'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormInputFile<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'filename'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorFile<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
      <span style="color: #0000ff;">'required'</span>   <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">'path'</span>       <span style="color: #339933;">=&gt;</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_upload_dir'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/produits/source'</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">'mime_types'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'web_images'</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">'max_size'</span>   <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">10485760</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
      <span style="color: #0000ff;">'max_size'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Fichier trop gros (10Mo maximum).'</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">disableCSRFProtection</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Et enfin l&#8217;action.class.php qui orchestre tout ca.<br />
Au niveau de l&#8217;action executeUpload il faut créer &laquo;&nbsp;à la main&nbsp;&raquo; le tableau des paramètres à passer au bind.</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('p918code53'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91853"><td class="code" id="p918code53"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #b1b100;">require_once</span> <span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/../lib/produitGeneratorConfiguration.class.php'</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/../lib/produitGeneratorHelper.class.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * produit actions.
 *
 * @package    
 * @subpackage produit
 * @author     
 * @version    SVN: $Id: actions.class.php 12474 2008-10-31 10:41:27Z fabien $
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> produitActions <span style="color: #000000; font-weight: bold;">extends</span> autoProduitActions
<span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeUpload<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;">produit</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;">forward404unless</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">produit</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ProduitPhotoForm<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$values</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
      <span style="color: #0000ff;">'produit_id'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">produit</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">'is_default'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">produit</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPhotos</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000000; font-weight: bold;">false</span> <span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">'filename'</span>   <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFiles</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'photo'</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #339933;">,</span> <span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isValid</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$photo</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;">-&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>
&nbsp;
      <span style="color: #000088;">$return</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'ok'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$return</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'ko'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderText</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$return</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * ajax pour definir une photo par defaut
   *
   * @param sfWebRequest $request
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeAjaxPhotoDefault<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: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isXmlHttpRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$photo</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;">$produit</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$photo</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getProduit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #000088;">$old_default</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$produit</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPhotoDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #000088;">$produit</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setPhotoDefaut</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$photo</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderPartial</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'produit/photoListe'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'photos'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$produit</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPhotos</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">redirect404</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * ajax pour effacer une photo
   *
   * @param sfWebRequest $request
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeAjaxPhotoDelete<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: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isXmlHttpRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$photo</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;">$photo_id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$photo</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$photo</span><span style="color: #339933;">-&gt;</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;">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;">'produit/ajaxPhotoDelete'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'photo_id'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$photo_id</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;">else</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">redirect404</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * ajax pour avoir la liste des photos
   *
   * @param sfWebRequest $request
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeAjaxPhotoListe<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: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isXmlHttpRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$produit</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: #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;">'produit/photoListe'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'photos'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$produit</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPhotos</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">redirect404</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Produit.class.php</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p918code54'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91854"><td class="code" id="p918code54"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Produit <span style="color: #000000; font-weight: bold;">extends</span> BaseProduit
<span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setPhotoDefaut<span style="color: #009900;">&#40;</span><span style="color: #000088;">$photoId</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</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;">update</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ProduitPhoto p'</span><span style="color: #009900;">&#41;</span>
    <span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'p.is_default'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'?'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">false</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;">'p.produit_id = ?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</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;
    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;">update</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ProduitPhoto p'</span><span style="color: #009900;">&#41;</span>
    <span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'p.is_default'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'?'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span>
    <span style="color: #339933;">-&gt;</span><span style="color: #004000;">andWhere</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'p.id = ?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$photoId</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: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getPhotoDefault<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ProduitPhoto'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDefault</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>ProduitPhotoTable.class.php</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p918code55'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91855"><td class="code" id="p918code55"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> ProduitPhotoTable <span style="color: #000000; font-weight: bold;">extends</span> Doctrine_Table
<span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getDefault<span style="color: #009900;">&#40;</span><span style="color: #000088;">$produit_id</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createQuery</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'c'</span><span style="color: #009900;">&#41;</span>
      <span style="color: #339933;">-&gt;</span><span style="color: #004000;">andWhere</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'c.produit_id = ?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$produit_id</span><span style="color: #009900;">&#41;</span>
      <span style="color: #339933;">-&gt;</span><span style="color: #004000;">andWhere</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'c.is_default = ?'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span>
      <span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetchOne</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: #009900;">&#125;</span></pre></td></tr></table></div>

<p>ProduitPhoto.class.php</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p918code56'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91856"><td class="code" id="p918code56"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> ProduitPhoto <span style="color: #000000; font-weight: bold;">extends</span> BaseProduitPhoto
<span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> isDefault<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>bool<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getIsDefault</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: #009900;">&#125;</span></pre></td></tr></table></div>

<h2>Le problème !</h2>
<p>A ce stade, tout est fini et en place pour que ca marche. Hors ca ne marche pas&#8230; Pourquoi ? Je rapelle le contexte, on est dans l&#8217;admin donc on est identifié et c&#8217;est là le problème. En effet swfUpload est une animation flash contenu dans le page mais qui va initialiser des requêtes http parallèles à celle utilisée par le navigateur. Et donc lorsque swfUpload se pointe à l&#8217;url &laquo;&nbsp;produit_photo&nbsp;&raquo; pour initialisé son upload, il se prend une belle erreur 403&#8230;</p>
<p>Le problème est connu des concepteurs de swfUpload et la solutions qu&#8217;ils préconisent est de forcé l&#8217;identifiant de session dans le script d&#8217;upload en faisant un session_id($session_id). C&#8217;est pourquoi on le fait passer dans la variable &laquo;&nbsp;post_params&nbsp;&raquo; à l&#8217;initialisation de swfUpload.</p>
<p>Pour faire la même chose dans symfony on ne peut pas le faire dans une action, car la session est déjà initialisée à ce niveau. On est obligé d&#8217;aller modifié le factories.yml et la calsse la classe sfSessionStorage pour aller forcer l&#8217;identifiant de session dans le cas ou on fait appel à l&#8217;action upload.</p>
<p>C&#8217;est un tip que j&#8217;ai trouvé sur le <a href="http://forum.symfony-project.org/index.php/m/42999/" target="_blank">forum symfony</a> qui était pour la version 1.0, et qui fonctionne toujours à la différence que le contexte n&#8217;est plus passé en paramètre dans la 1.2 et donc il faut aller le charger.</p>
<p>factories.yml</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p918code57'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91857"><td class="code" id="p918code57"><pre class="yml" style="font-family:monospace;">...
all:
...
  storage:
    class: mySessionStorage
    param:
      session_name: weezobackend
...</pre></td></tr></table></div>

<p>mySessionStorage.calss.php</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p918code58'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p91858"><td class="code" id="p918code58"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> mySessionStorage <span style="color: #000000; font-weight: bold;">extends</span> sfSessionStorage
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> initialize<span style="color: #009900;">&#40;</span><span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> sfContext<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//Shitty work-around for swfuploader</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getActionName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">&quot;upload&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$sessionName</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$parameters</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;session_name&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sessionName</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #990000;">session_name</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sessionName</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #990000;">session_id</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</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;
    parent<span style="color: #339933;">::</span><span style="color: #004000;">initialize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$options</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>Ça y est, cette fois ça marche !<br />
Et vous avez une gestion d&#8217;images directement dans la fiche du produit qui est assez user-friendly <img src='http://www.lexik.fr/blog/symfony/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Merci d&#8217;avoir lu jusqu&#8217;au bout :p<br />
Je reste à votre disposition pour toute questions ou suggestions <img src='http://www.lexik.fr/blog/symfony/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /><br />
@bientôt !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/gestion-dune-galerie-photo-avec-swfupload-dans-ladmin-918/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Utilisation de sfSessionStorage dans Symfony</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/utilisation-de-sfsessionstorage-dans-symfony-901</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/utilisation-de-sfsessionstorage-dans-symfony-901#comments</comments>
		<pubDate>Mon, 24 Aug 2009 07:10:29 +0000</pubDate>
		<dc:creator>yoye</dc:creator>
				<category><![CDATA[1.2.x]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[environnement]]></category>
		<category><![CDATA[factories]]></category>
		<category><![CDATA[sfSessionStorage]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/sfblog/?p=901</guid>
		<description><![CDATA[sfSessionStorage fait partie des fonctionnalités du Framework qui restent un brin obscures lorsqu&#8217;on commence avec Symfony. Mais il s&#8217;avère par la suite très utile, que ce soit dans le cadre de la production ou même du développement. A quoi ça sert ? Tout simplement à la gestion des cookies de session. pourquoi l&#8217;utiliser ? Récemment [...]]]></description>
			<content:encoded><![CDATA[<p>sfSessionStorage fait partie des fonctionnalités du Framework qui restent un brin obscures lorsqu&#8217;on commence avec Symfony. Mais il s&#8217;avère par la suite très utile, que ce soit dans le cadre de la production ou même du développement.<br />
<span id="more-901"></span></p>
<h4>A quoi ça sert ?</h4>
<p>Tout simplement à la gestion des cookies de session.</p>
<h4>pourquoi l&#8217;utiliser ?</h4>
<p>Récemment j&#8217;ai du développer un projet qui contenait plusieurs applications, 3 pour commencer et elles peuvent se multiplier par la suite. Cela n&#8217;a rien de choquant tous les projets on généralement un minimum de 2 applications, un backend et un frontend.<br />
Ce qui peut s&#8217;avérer très vite ennuyeux, en effet pour peu que l&#8217;on souhaite être connecté en tant qu&#8217;admin sur notre backend et en tant qu&#8217;utilisateur lamda sur notre frontend, il va falloir se déconnecter assez souvent, ce qui a la longue devient fastidieux.</p>
<p><strong>C&#8217;est là qu&#8217;intervient notre sfSessionStorage.</strong></p>
<h4>Comment le configurer ?</h4>
<p>Ce qui est intéressant dans l&#8217;utilisation des cookies de session c&#8217;est leur simplicité d&#8217;utilisation grâce au framework. Pour cela il va falloir modifier le fichier factories.yml.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p901code62'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p90162"><td class="code" id="p901code62"><pre class="yml" style="font-family:monospace;"># apps/frontend/config/factories.yml
&nbsp;
all:
#début de ma config
  storage:
    class: sfSessionStorage
    param:
      session_name: frontend
&nbsp;
# apps/backend/config/factories.yml
&nbsp;
all:
#début de ma config
  storage:
    class: sfSessionStorage
    param:
      session_name: backend</pre></td></tr></table></div>

<p>Je me retrouve désormais avec des cookies différents pour chaque application ce qui va me permettre de me connecter sur chacune de mes applications avec des utilisateurs différents.</p>
<h4>Autres cas pratiques</h4>
<p>On peut bien évidemment étendre cette solution sur les environnements. En effet on peut avoir besoin d&#8217;être connecté sur une même application avec deux types d&#8217;utilisateurs. Imaginons que j&#8217;ai besoin de tester sur mon frontend les différents crédentials que j&#8217;ai ajouté à mon application. Je peux me créer des environnements pour chacun de ces crédentials comme par ex : rédacteur et administrateur.<br />
Je vais de nouveau modifier mon fichier factories.yml et le champs d&#8217;application ne va plus se faire sur toute l&#8217;application mais sur un environnement.</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('p901code63'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p90163"><td class="code" id="p901code63"><pre class="yml" style="font-family:monospace;">redac:
  storage:
    class: sfSessionStorage
    param:
      session_name: redacteur
admin:
  storage:
    class: sfSessionStorage
    param:
      session_name: administrateur</pre></td></tr></table></div>

<p>Dans un soucis de simplicité j&#8217;ai raccourci le nom des environnements. Il me faut pour terminer créer mes deux environnements. Je vais pour cela créer les fichiers frontend_redac.php et frontend_admin.php dans le dossier web qui contiendront :</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('p901code64'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p90164"><td class="code" id="p901code64"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// environnement redac</span>
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/../config/ProjectConfiguration.class.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$configuration</span> <span style="color: #339933;">=</span> ProjectConfiguration<span style="color: #339933;">::</span><span style="color: #004000;">getApplicationConfiguration</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'frontend'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'redac'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
sfContext<span style="color: #339933;">::</span><span style="color: #004000;">createInstance</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$configuration</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>dispatch<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;">// environnement admin</span>
<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/../config/ProjectConfiguration.class.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$configuration</span> <span style="color: #339933;">=</span> ProjectConfiguration<span style="color: #339933;">::</span><span style="color: #004000;">getApplicationConfiguration</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'frontend'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'admin'</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
sfContext<span style="color: #339933;">::</span><span style="color: #004000;">createInstance</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$configuration</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>dispatch<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Je pourrai maintenant être connecté sur mon application avec 2 comptes différents.</p>
<p>L&#8217;utilisation de la classe sfSessionStorage peut donc s&#8217;avérer très utile comme je l&#8217;ai dis plus tôt dans un cadre de développement pour faciliter la navigation entre les différentes configuration que l&#8217;on peut retrouver sur notre application quant à son utilisation en production chacun fera en fonction de ses besoins bien évidemment.</p>
<p>Mais quand on voit la simplicité de la mise en place il serait dommage de s&#8217;en passer.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/utilisation-de-sfsessionstorage-dans-symfony-901/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Déployer un projet Symfony avec Rsync</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/deployer-un-projet-symfony-avec-rsync-840</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/deployer-un-projet-symfony-avec-rsync-840#comments</comments>
		<pubDate>Fri, 07 Aug 2009 14:01:29 +0000</pubDate>
		<dc:creator>Calu</dc:creator>
				<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[rsync]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/sfblog/?p=840</guid>
		<description><![CDATA[Le développement de votre projet Symfony arrive à son terme, vous confrontant ainsi à l&#8217;étape de la mise en ligne. Si vous vous apprêtez à lancer votre client FTP pour le dépôt de vos fichiers, alors cet article est fait pour vous. Nous allons voir la configuration et l&#8217;utilisation d&#8217;un petit utilitaire de synchronisation : [...]]]></description>
			<content:encoded><![CDATA[<p>Le développement de votre projet Symfony arrive à son terme, vous confrontant ainsi à l&#8217;étape de la mise en ligne. Si vous vous apprêtez à lancer votre client FTP pour le dépôt de vos fichiers, alors <span style="text-decoration: underline;">cet article est fait pour vous</span>. Nous allons voir la configuration et l&#8217;utilisation d&#8217;un petit utilitaire de synchronisation : <strong>RSync</strong>.</p>
<p><span id="more-840"></span></p>
<h3>Pourquoi utiliser RSync ?</h3>
<p>A l&#8217;instart du FTP, <strong>rsync</strong> permet d&#8217;effectuer une synchronisation distante basée sur des sauvegardes incrémentales. En clair, à l&#8217;aide d&#8217;une seule commande, vous pouvez mettre à jour sur votre serveur, <span style="text-decoration: underline;">seulement l&#8217;ensemble des fichiers modifiés</span> depuis votre dernière synchonisation.</p>
<p><strong>Rsync </strong>utilise le protocole SSH permettant  une communication sécurisée lors du transfert des fichiers. Un autre avantage indéniable par rapport au protocole FTP beaucoup trop bavard sur le réseau, lors de la transmission de vos paramètres d&#8217;authentification.</p>
<p>Outre le confort et la rapidité du déploiement par <strong>rsync</strong>, il ne faut pas oublier son <span style="text-decoration: underline;">support natif</span> par Symfony.</p>
<h3>Configuration RSync</h3>
<p>Avant de voir les différents paramètres de configuration, nous allons rapidement installer ce petit utilitaire via notre gestionnaire de packet sur notre<strong> </strong> Debian-Like :</p>
<pre>apt-get install rsync</pre>
<p>Pour les paramètres de connection, il faut  créer/modifier le fichier <em>config/properties.ini </em>:<em><br />
</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('p840code67'); return false;">View Code</a> INI</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p84067"><td class="code" id="p840code67"><pre class="ini" style="font-family:monospace;"><span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>maconfig<span style="">&#93;</span></span>
<span style="color: #000099;">name</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">MonSite</span>
<span style="color: #000099;">author</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">Lexik.fr</span>
<span style="color: #000099;">host</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">66.249.64.0                               #IP du serveur</span>
<span style="color: #000099;">port</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"><span style="">22</span>                                        #Port par default pour ssh</span>
<span style="color: #000099;">user</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">votre-login                               #Utilisateur qui se connectera au serveur de destination</span>
<span style="color: #000099;">dir</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">/home/lexik/domains/lexik.fr/public_html   #Dossier qui recevera le projet symfony sur le serveur de destination</span>
<span style="color: #000099;">type</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">rsync                                     #Type de deploiement</span></pre></td></tr></table></div>

<p>Symfony permet de spécifier les dossiers à exclure lors de la synchronisation. Créer/Modifier le fichier <em>config/rsync_exclude.txt</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('p840code68'); return false;">View Code</a> TXT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p84068"><td class="code" id="p840code68"><pre class="txt" style="font-family:monospace;">.svn
/web/uploads/*
/web/*_dev.php
/cache/*
/log/*
.DS_Store
.cache
.project
.settings</pre></td></tr></table></div>

<p>Nous allons ensuite tester nos paramètres de configuration. Cette commande est utile pour effectuer une simulation du transfert. Cela signifie que rien ne sera synchronisé :<strong> </strong></p>
<pre>php symfony project:deploy <span>maconfig</span></pre>
<p>Nous y voila, effectuez votre <strong>rsynchronisation</strong> :</p>
<pre>php symfony project:deploy <span>maconfig</span> --go</pre>
<p><span style="text-decoration: underline;">Et voila </span>!</p>
<h3>Déploiement sans spécifier le mot de passe</h3>
<p>Dans un souci d&#8217;automatisation de synchronisation, il peut être embêtant de se faire demander le mot de passe serveur à chaque déploiement par <strong>rsync</strong> (ou même lorsque l&#8217;on souhaite se connecter au serveur directement par SSH).</p>
<p>Dans cette logique, on peut utiliser une encryption asymétrique (clé publique, clé privée) afin de rester &laquo;&nbsp;connu&nbsp;&raquo; par le serveur:<br />
On génère le couple de clé en local avec la commande :</p>
<pre>ssh-keygen -t rsa</pre>
<p>On garde le chemin par défault pour la sauvegarde des clés, et nous n&#8217;aurons pas besoin dans notre cas de passphrase, en vue d&#8217;une possible automatisation des synchronisations.</p>
<p>Les 2 clés sont donc générées dans ~/.ssh/</p>
<p>Il suffit alors de copier la clé publique sur le serveur, dans le répertoire courant de l&#8217;utilisateur avec lequel on se connecte.</p>
<p>Voici une procédure possible avec <strong>scp</strong> (<strong>man scp </strong>pour plus d&#8217;information) :</p>
<pre>scp /home/moi/.ssh/id_rsa.pub monlogin@ip-du-server:.ssh/authorized_keys</pre>
<p>(Il faudra peut être créer le dossier .ssh à la racine du dossier personnel de l&#8217;utilisateur).</p>
<h3><span style="text-decoration: underline;">Bugs courant :</span></h3>
<pre>Agent admitted failure to sign using the key.</pre>
<p>Peut se produire alors que la clé publique a bien été transmise au serveur (le bug semblerait provenir du client SSH natif d&#8217;ubuntu: <a href="http://www.google.com/url?q=https%3A%2F%2Fbugs.launchpad.net%2Fubuntu%2F%2Bsource%2Fopenssh%2F%2Bbug%2F201786&amp;sa=D&amp;sntz=1&amp;usg=AFrqEzdjX5r1Ryyi2TdvRa4CL8jIlXk7ew">https://bugs.launchpad.net/ubuntu/+source/openssh/+bug/201786</a>).</p>
<p>Voici la commande salvatrice :</p>
<pre>export SSH_AUTH_SOCK=0</pre>
<h3>En savoir plus</h3>
<ul>
<li><a href="http://fr.wikipedia.org/wiki/Cryptographie_asym%C3%A9trique" target="_blank">Cryptographie asymétrique</a></li>
<li><a title="Pratical symfony - Day 23 : The deployment " href="http://www.symfony-project.org/jobeet/1_2/Doctrine/en/23#chapter_23_deploying" target="_blank">Pratical symfony : Day 23</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/deployer-un-projet-symfony-avec-rsync-840/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Symfony : Utilisation de la classe sfFilter</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/symfony-utilisation-de-la-classe-sffilter-792</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/symfony-utilisation-de-la-classe-sffilter-792#comments</comments>
		<pubDate>Thu, 16 Jul 2009 09:48:23 +0000</pubDate>
		<dc:creator>yoye</dc:creator>
				<category><![CDATA[1.2.x]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[sfFilter]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/sfblog/?p=792</guid>
		<description><![CDATA[Nous allons voir l&#8217;utilisation de la classe sfFilter. Attention à ne pas confondre sfFilter et les classes auto-générés lors du build de l&#8217;application qui sont des classes principalement utilisées dans le backend pour faire le tri sur les colonnes. Mais concentrons nous d&#8217;abord sur sfFilter. Comme on peut le voir en parcourant rapidement le code [...]]]></description>
			<content:encoded><![CDATA[<p>Nous allons voir l&#8217;utilisation de la classe sfFilter. Attention à ne pas confondre sfFilter et les classes auto-générés lors du build de l&#8217;application qui sont des classes principalement utilisées dans le backend pour faire le tri sur les colonnes.</p>
<p>Mais concentrons nous d&#8217;abord sur <a href="http://www.symfony-project.org/api/1_2/sfFilter">sfFilter</a>. Comme on peut le voir en parcourant rapidement le code c&#8217;est une classe abstraite on ne pourra donc l&#8217;utiliser que part héritage.<br />
Les filters sont en fait une couche du Framework qui permet d&#8217;effectuer des actions avant ou après l&#8217;affichage d&#8217;une page, ce qui peut s&#8217;avérer très pratique.<br />
<span id="more-792"></span><br />
On va donc partir d&#8217;un exemple simple :<br />
Imaginons deux sites internet, un site A qui va faire une redirection vers mon site B. Sur mon site B les utilisateurs peuvent s&#8217;inscrire et j&#8217;ai besoin de stocker le site de provenance, ce qui va se faire à l&#8217;aide d&#8217;un cookie.<br />
Une méthode primaire pourrait consister à faire une page qui va poser le cookie et faire la redirection. Seulement le jour ou je souhaite que mon site A redirige vers une page précise de mon site B il va falloir que je vienne changer le code.<br />
<strong>Heureusement sfFilter est là !</strong></p>
<p>Grâce à cette couche du framework je vais pouvoir créer une classe que je vais appeler TrackerFilter et qui va me faire tout le traitement nécessaire. Voici le 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('p792code73'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p79273"><td class="code" id="p792code73"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> TrackerFilter <span style="color: #000000; font-weight: bold;">extends</span> sfFilter <span style="color: #009900;">&#123;</span>
     <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> execute<span style="color: #009900;">&#40;</span><span style="color: #000088;">$filterChain</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$request</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <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;">isFirstCall</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</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;">'r'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCookie</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'reservation'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$time</span> <span style="color: #339933;">=</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">60</span><span style="color: #339933;">*</span><span style="color: #cc66cc;">60</span><span style="color: #339933;">*</span><span style="color: #cc66cc;">24</span><span style="color: #339933;">*</span><span style="color: #cc66cc;">7</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$context</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setCookie</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'reservation'</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;">'r'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$time</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000088;">$filterChain</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>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<dl>
<dt>Que se passe t&#8217;il dans ces quelques lignes de code ?</dt>
<dd>Notre classe va hériter de sfFilter (obligatoire)</dd>
<dd>On va créer une function execute avec en paramètre $filterchain qui va nous permettre d&#8217;exécuter le code souhaité (obligatoire)</dd>
<dd>On récupère le &laquo;&nbsp;context&nbsp;&raquo; et le &laquo;&nbsp;request&nbsp;&raquo; ce qui va nous permettre de vérifier si le cookie existe déjà et de le poser dans le cas contraire</dd>
<dd>On exécute le filter (obligatoire)</dd>
</dl>
<p>Quelques précisions supplémentaires :<br />
La fonction isFirstCall() permet de vérifier si c&#8217;est la première exécution du filter.<br />
Le placement de la ligne</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('p792code74'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p79274"><td class="code" id="p792code74"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$filterChain</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></pre></td></tr></table></div>

<p>a son importance puisqu&#8217;elle permet de signifier si l&#8217;on souhaite que le filter s&#8217;exécute avant ou après l&#8217;action.</p>
<p>Maintenant il ne nous reste plus qu&#8217;à configurer notre filter, pour cela il faut modifier le fichier apps/APPLICATION/config/filters.yml qui d&#8217;origine contient :</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('p792code75'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p79275"><td class="code" id="p792code75"><pre class="yml" style="font-family:monospace;">rendering: ~
security:  ~
&nbsp;
# insert your own filters here
&nbsp;
cache:     ~
common:    ~
execution: ~</pre></td></tr></table></div>

<p>Ce qui semble assez explicite pour savoir ou écrire notre configuration. On va donc compléter ce fichier comme suit :</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('p792code76'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p79276"><td class="code" id="p792code76"><pre class="yml" style="font-family:monospace;">rendering: ~
security:  ~
&nbsp;
TrackerFilter:
  class:  TrackerFilter
&nbsp;
cache:     ~
common:    ~
execution: ~</pre></td></tr></table></div>

<p>Nous avons donc vu comment utiliser les filters avec un cas pratique simple mais qui est un cas qu&#8217;un développeur web va rencontrer souvent. Cette façon de faire laisse donc une certaine flexibilité et permet une fois de plus d&#8217;avoir un code simple, clair et factorisé.<br />
On trouve là tout la puissance de Symfony.</p>
<p>Pour ceux qui sont intéressés par d&#8217;autres cas d&#8217;utilisation de sfFilter vous pouvez bien sûr vous reportez sur le <a href="http://www.symfony-project.org/book/1_2/06-Inside-the-Controller-Layer#chapter_06_filters">livre</a>. Vous y verrez qu&#8217;il est possible grâce aux filters de faire des redirection, ou encore d&#8217;ajouter du code sur notre page.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/symfony-utilisation-de-la-classe-sffilter-792/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Du Javascript dynamique dans une vue en utilisant sf_format</title>
		<link>http://www.lexik.fr/blog/symfony/symfony/du-javascript-dynamique-dans-une-vue-en-utilisant-sf_format-746</link>
		<comments>http://www.lexik.fr/blog/symfony/symfony/du-javascript-dynamique-dans-une-vue-en-utilisant-sf_format-746#comments</comments>
		<pubDate>Wed, 08 Jul 2009 08:13:32 +0000</pubDate>
		<dc:creator>olivier</dc:creator>
				<category><![CDATA[1.2.x]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[sf_format]]></category>
		<category><![CDATA[vue]]></category>

		<guid isPermaLink="false">http://www.lexik.fr/sfblog/?p=746</guid>
		<description><![CDATA[Il arrive que l&#8217;on ai besoin d&#8217;utiliser un script javascript spécifique dans une vue. Un script dynamique qui nécessite d&#8217;être renseigné par des informations de php (utiliser des variables ou des méthodes de nos objets). Dans mon précédent post j&#8217;évoquais les différentes possibilités d&#8217;inclure le javascript dans les vues. Mettre des balises &#60;script&#62; directement au [...]]]></description>
			<content:encoded><![CDATA[<p>Il arrive que l&#8217;on ai besoin d&#8217;utiliser un script javascript spécifique dans une vue. Un script dynamique qui nécessite d&#8217;être renseigné par des informations de php (utiliser des variables ou des méthodes de nos objets).</p>
<p>Dans mon précédent post j&#8217;évoquais les différentes possibilités d&#8217;inclure le javascript dans les vues.</p>
<ul>
<li>Mettre des balises &lt;script&gt; directement au milieu du html (un peu crade mais efficace)</li>
<li>Faire un fichier .js &laquo;&nbsp;en dur&nbsp;&raquo; dans le dossier /web/js (mais là on perd la possibilité d&#8217;utiliser du php)</li>
<li>Utiliser un slot dans le &lt;head&gt; du template</li>
<li>Utiliser une vue</li>
</ul>
<p>C&#8217;est ce dernier point que je vous propose de voir aujourd&#8217;hui.</p>
<p><span id="more-746"></span></p>
<p>Pour se dessiner un petit background on va prendre l&#8217;exemple d&#8217;une vue index dans un module d&#8217;actualités.<br />
Dans cette vue on veut faire un appel ajax sur un lien et on veut utiliser le routing pour définir l&#8217;url du script à appeler.</p>
<p>On va donc utiliser une action et deux vues, une pour la page html et une pour le javascript qui sera inclus dans la vue html. On utilise des sf_format différents.
<p>On créé la route qui servira pour les deux vues (/app/frontend/config/routing.yml).</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p746code84'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p74684"><td class="code" id="p746code84"><pre class="yml" style="font-family:monospace;">...
actu_index:
  url:   /actualites/index.:sf_format
  param: { module: actu, action: index, sf_format: html }
...</pre></td></tr></table></div>

<p>Dans notre action on récupère juste les dernières actualités à afficher dans la page html (/app/frontend/modules/actu/actions/actions.class.php).</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p746code85'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p74685"><td class="code" id="p746code85"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> actuActions <span style="color: #000000; font-weight: bold;">extends</span> sfActions
<span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeIndex<span style="color: #009900;">&#40;</span>sfWebRequest <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">actus</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;">'Actu'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLast</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: #009900;">&#125;</span></pre></td></tr></table></div>

<p>La vue Html. C&#8217;est la que ca se passe ! On fais un use_javascript() auquel on passe le url_for() de la même vue en spécifiant juste le sf_format à &#8216;js&#8217; (/app/frontend/modules/actu/templates/indexSuccess.php).</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p746code86'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p74686"><td class="code" id="p746code86"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> use_javascript<span style="color: #009900;">&#40;</span>url_for<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'@actu_index?sf_format=js'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #339933;">&lt;</span>div <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;liste_actus&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;">$actus</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$actu</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    <span style="color: #339933;">&lt;</span>div <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;actu&quot;</span><span style="color: #339933;">&gt;</span>
      <span style="color: #339933;">&lt;</span>h3<span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #990000;">echo</span> <span style="color: #000088;">$actu</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTitre</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>h3<span style="color: #339933;">&gt;</span>
      <span style="color: #339933;">&lt;</span>p<span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #990000;">echo</span> <span style="color: #000088;">$actu</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTexteCourt</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>p<span style="color: #339933;">&gt;</span>
      <span style="color: #339933;">&lt;</span>div <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;action&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;?</span>php <span style="color: #990000;">echo</span> link_to<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Lire la suite'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'@actu_detail'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;</span>div<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>Et donc la vue js sera inclue par la vue html qui rajoute dans le head l&#8217;appel au fichier.</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('p746code87'); return false;">View Code</a> HTML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p74687"><td class="code" id="p746code87"><pre class="html" style="font-family:monospace;">&lt;script type=&quot;text/javascript&quot; src=&quot;/actualites/index.js&quot;&gt;&lt;/script&gt;</pre></td></tr></table></div>

<p>Il ne reste plus qu&#8217;a faire la script javascript dans la vue /app/frontend/modules/actu/templates/indexSuccess.js.php ou on peut avoir accès  à tous les éléments de symfony que l&#8217;on désire.</p>
<p>Par exemple là un peut appel ajax en jQuery ou je récupère l&#8217;url du script appelé grâce au routing.</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('p746code88'); return false;">View Code</a> JAVASCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p74688"><td class="code" id="p746code88"><pre class="javascript" style="font-family:monospace;">jQuery<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>
&nbsp;
  $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'div.action a'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    event.<span style="color: #660066;">preventDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    $.<span style="color: #660066;">post</span><span style="color: #009900;">&#40;</span>
      <span style="color: #3366CC;">'&lt;?php echo url_for('</span><span style="color: #339933;">@</span>actu_detail<span style="color: #3366CC;">') ?&gt;'</span><span style="color: #339933;">,</span>
      <span style="color: #009900;">&#123;</span> url<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;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'href'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
      <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
      <span style="color: #3366CC;">'script'</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: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Il se peut que dans la vue javascript on n&#8217;ait pas besoin d&#8217;exécuter toute l&#8217;action.<br />
Par exemple ici, dans ma vue javascript, je n&#8217;ai pas besoin des dernières actualités, il est donc possible de filtrer pour alléger l&#8217;action grâce au sf_format.</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('p746code89'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p74689"><td class="code" id="p746code89"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> actuActions <span style="color: #000000; font-weight: bold;">extends</span> sfActions
<span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeIndex<span style="color: #009900;">&#40;</span>sfWebRequest <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</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;">'sf_format'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">'js'</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;">actus</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;">'Actu'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLast</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Après, libre a chacun de voir si on doit utiliser la même action que la vue html ou si la vue javascript nécessite sa propre action.</p>
<p>En utilisant une action séparée pour la vue javascript on peut s&#8217;amuser à pousser le vice du camouflage en utilisant un routing qui fasse croire que l&#8217;on appelle un fichier .js (Attention si jamais un fichier avec le même nom existe réellement dans le répertoire /web/js c&#8217;est ce dernier qui sera inclus).</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('p746code90'); return false;">View Code</a> YML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table width="100%" ><tr id="p74690"><td class="code" id="p746code90"><pre class="yml" style="font-family:monospace;">...
actu_index_js:
  url:   /js/actu.:sf_format
  param: { module: actu, action: index, sf_format: js }
...</pre></td></tr></table></div>

<p><b>Avantage de cette technique :</b></p>
<ul>
<li>Un code source html super &laquo;&nbsp;clean&nbsp;&raquo;</li>
</ul>
<p><b>Inconvéniant :</b></p>
<ul>
<li>Pour une page html, on fait deux appels à symfony.<br />
A utiliser avec parcimonie et bien optimiser les actions pour ne pas faire des requêtes inutiles sur la base de donnée.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.lexik.fr/blog/symfony/symfony/du-javascript-dynamique-dans-une-vue-en-utilisant-sf_format-746/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
