<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
    <title>Blog de Jérémy Barthe</title>
    <description>Blog d&#039;un développeur Web à Montpellier, spécialisé en PHP et dans les frameworks notamment Symfony, adepte du javascript, de la librairie jQuery, d&#039;ajax et des bonnes pratiques d&#039;XHTML / CSS.</description>
    <link>http://jeremybarthe.com</link>
    <pubDate>Tue, 07 Sep 2010 21:52:07 +0200</pubDate>
    <lastBuildDate>Tue, 07 Sep 2010 21:52:07 +0200</lastBuildDate>
    <language>fr</language>
    
        <item>
      <title>[Brève] Nouvelle version, propulsée par Symfony</title>
      <link>http://jeremybarthe.com/2009/03/18/fr/nouvelle-version-propulsee-par-symfony-framework</link>
      <guid>http://jeremybarthe.com/2009/03/18/fr/nouvelle-version-propulsee-par-symfony-framework</guid>
      <comments>http://jeremybarthe.com/2009/03/18/fr/nouvelle-version-propulsee-par-symfony-framework#comments</comments>
            <author>Jérémy Barthe &lt;contact@jeremybarthe.com&gt;</author>
      <pubDate>Wed, 18 Mar 2009 23:29:00 +0100</pubDate>
      <description><![CDATA[<p>Après plusieurs semaines la tête dans le guidon pendant mes fins de soirées ou insomnies, ce blog tourne enfin avec un moteur maison codé en Symfony. Il s'agit de ma première réelle application avec Symfony &amp; Doctrine, je n'avais auparavant que lu la doc et fait des tests sur les tutoriaux Askeet puis Jobeet. Je vais essayer de tirer petit à petit des articles de ce développement, mais si vous avez déjà des interrogations, n'hésitez pas à me les laisser par commentaires.</p>
<p>Bref comme vous vous en doutez ce blog va s'orienter de plus en plus vers Symfony puisque je fais en sorte qu'il prenne place dans ma vie professionnelle.</p>
<p>Côté ligne éditoriale, je veux renforcer le côté articles, ils sont et resteront rares, j'essaie de les détailler suffisamment et ceci me prends beaucoup de temps. D'où le fait que j'ai ajouté un système de brèves qui me permet de sortir du cadre des articles, avec <a href="http://jeremybarthe.com/2009/02/18/fr/meler-css-et-photographies">cette dernière par exemple</a>.</p>
<p>Pour le flux RSS principal, pas de souci, puisque c'est feedburner qui s'en occupe, pour les autres et notamment celui des commentaires, je vous conseille d'aller jeter un oeil en bas de la page <a href="http://jeremybarthe.com/fr/a-propos">à propos</a>.</p>
<p>Côté design, celui-ci est beaucoup plus simple que le précédent, plus épurée, il repose essentiellement sur une mise en avant des contenus, ce qui pêchait auparavant (surtout en terme de largeur pour l'affichage des articles). Dans les originalités on trouve surtout un code couleur par catégorie (bleu pour PHP, rouge pour CSS, vert pour le Javascript et gris foncé pour Webdesign) et on retrouve les titres positionnés à gauche du contenu des articles.</p>
<p>Et côté bonne nouvelle, le précédent design sera prochainement disponible en téléchargement sous la forme d'un template libre ou wordpress.</p>
<p>Avec la récente acquisition d'un Canon 50D et d'un 17-40 j'ai pas mal de photos à trier, retoucher et mettre en ligne sur mon Flickr, et je reviens dès que possible avec des articles !</p>
<p><small>(il se peut que des bugs aient échappés à mon attention, n'hésitez pas à me les signaler en commentaire)</small></p>
]]></description>
    </item>
        <item>
      <title>[Article] sfForm de Symfony en tant que framework</title>
      <link>http://jeremybarthe.com/fr/php/sf-form-de-symfony-en-tant-que-framework</link>
      <guid>http://jeremybarthe.com/fr/php/sf-form-de-symfony-en-tant-que-framework</guid>
      <comments>http://jeremybarthe.com/fr/php/sf-form-de-symfony-en-tant-que-framework#comments</comments>
            <category><![CDATA[PHP]]></category>
            <author>Jérémy Barthe &lt;contact@jeremybarthe.com&gt;</author>
      <pubDate>Wed, 11 Feb 2009 00:00:00 +0100</pubDate>
      <description><![CDATA[<p>Le framework Symfony a l'énorme avantage d'être construit sous la forme d'un ensemble de composants autonomes et cohérents. En d'autres termes il s'agit d'un framework composé de minis frameworks. Chacun de ces composants est utilisable en soi de façon cohérente.</p>
<p>L'objectif de cet article est de vous présenter sfForm en tant que framework sans Symfony, avec ses compagnons de route, à savoir ses widgets et ses validateurs. Evidemment mon but n'est pas de vous conseiller d'utiliser cette technique car vous ne bénéficierez pas de toutes les fonctionnalités liés à Symfony, notamment le lien entre le formulaire et l'ORM. De plus dans cet exemple il y a des appels aux variables supersglobales ce qui n'est pas recommandé, etc. Mais ceci peut être utile si vous travaillez sur un code existant sur lequel vous ne pouvez envisager une refonte totale et sur lequel vous avez une problématique autour des formulaires, sfForm peut y répondre en tant que tel.</p>
<p>Dans un premier temps il nous faut inclure les librairies. J'ai choisi, pour cet exemple relativement simple d'utiliser le système d'autoloading fourni dans Symfony. Cette intégration dépend de votre projet, si vous utilisez déjà l'autoloading, il vous faudra l'adapter à l'inclusion des librairies de sfForm...</p>
<pre class="php">
require_once dirname(__FILE__) . '/lib/symfony/autoload/sfCoreAutoload.class.php';
sfCoreAutoload::register();
</pre>
<p>La classe de définition du formulaire sfForm est identique à celle que l'on pourrait trouver dans un projet Symfony, je laisse donc de côté cette étape, vous pouvez <a href="http://www.symfony-project.org/book/forms/1_2/en/" class="blank">vous référer à la documentation</a>. Vous trouverez cependant la classe dans l'archive attachée à cet article et dans une fenêtre modale ci-dessous :</p>
<pre class="php">
&lt;?php
class ContactForm extends sfForm
{
  protected static $subjects = array('Subject A', 'Subject B', 'Subject C');

  public function configure()
  {
    $this-&gt;setWidgets(array(
      'name'    =&gt; new sfWidgetFormInput(),
      'email'   =&gt; new sfWidgetFormInput(),
      'subject' =&gt; new sfWidgetFormSelect(array('choices' =&gt; self::$subjects)),
      'message' =&gt; new sfWidgetFormTextarea(),
    ));

    $this-&gt;setValidators(array(
      'name'    =&gt; new sfValidatorString(array('required' =&gt; false)),
      'email'   =&gt; new sfValidatorEmail(array(), array('invalid' =&gt; 'Email address is invalid.')),
      'subject' =&gt; new sfValidatorChoice(array('choices' =&gt; array_keys(self::$subjects))),
      'message' =&gt; new sfValidatorString(array('min_length' =&gt; 4), array(
        'required'   =&gt; 'The message field is required',
        'min_length' =&gt; 'The message &quot;%value%&quot; is too short. It must be of %min_length% characters at least.',
      )),
    ));

    $this-&gt;widgetSchema-&gt;setNameFormat('contact[%s]');

    $this-&gt;widgetSchema-&gt;setFormFormatterName('list');
  }
}
</pre>
<p>Quant à la partie de notre code qui va gérer le traitement de la requête entrante, le formulaire et la réponse (notre contrôleur en résumé), nous allons étudier le code habituel d'une action Symfony pour en déceler les éléments indisponibles dans notre application from scratch.<br />
Code habituel de l'action du formulaire avec Symfony :</p>
<pre class="php">
public function executeIndex(sfWebRequest $request)
{
  $this-&gt;form = new ContactForm();

  if ($request-&gt;isMethod('post'))
  {
    $this-&gt;form-&gt;bind($request-&gt;getParameter('poll', array()));

    if ($this-&gt;form-&gt;isValid())
    {
      // traitement base de données ou email

      // redirection vers une page de confirmation
      $this-&gt;redirect('contact/confirmation');
    }
  }
}
</pre>
<p>Ci-dessous une liste de contraintes pour adapter cela sans Symfony :</p>
<ul>
<li><em>$this->form</em> nous permet de passer un objet à la vue, nous n'en avons plus besoin une simple variable <em>$form</em> suffira (attention néanmoins à la visibilité de cette variable et qu'elle ne soit pas écrasée ailleurs dans votre code...) ;</li>
<li>nous n'avons plus l'objet <em>$request</em>, lui qui nous permet de récupérer des informations venant de la requête utilisateur, tels que des paramètres GET ou POST, nous allons le remplacer par un accès direct à la variable superglobale <em>$_POST</em> ;</li>
<li>enfin <em>$this->redirect()</em> pourra être remplacé par un <em>header("Location")</em>.</li>
</ul>
<p>Ce qui nous amène à ce code :</p>
<pre class="php">
$form = new ContactForm();

if (!empty($_POST))
{
  $form-&gt;bind((is_array($_POST['contact'])) ? $_POST['contact'] : array());
  if ($form-&gt;isValid())
  {
    // traitement base de données ou email
    $values = $form-&gt;getValues();

    // redirection vers une page de confirmation
    header(&quot;Location: confirmation.php&quot;);
    exit;
  }
}
</pre>
<p>Forcément c'est moins propre qu'avec Symfony... ;-)<br />
Voici la structure de notre micro-projet :</p>
<ul>
<li>lib/
<ul>
<li>symfony/
<ul>
<li>autoload/</li>
<li>form/</li>
<li>validator</li>
<li>widget</li>
</ul>
</li>
<li>ContactForm.class.php</li>
</ul>
</li>
<li>index.php</li>
</ul>
<p>C'est terminé, notre code est fonctionnel, nous avons apprivoisé sfForm pour l'utiliser dans notre projet avec nos autres librairies. Vous trouverez ci-dessous le code complet du fichier <em>index.php</em> :</p>
<pre class="php">
&lt;?php
/**
 * Symfony autoloading
 */
require_once dirname(__FILE__) . '/lib/symfony/autoload/sfCoreAutoload.class.php';
sfCoreAutoload::register();

/**
 * Contact form example
 */
require_once dirname(__FILE__) . '/lib/ContactForm.class.php';
$form = new ContactForm();

if (!empty($_POST))
{
  $form-&gt;bind((is_array($_POST['contact'])) ? $_POST['contact'] : array());
  if ($form-&gt;isValid())
  {
    // traitement base de données ou email
    $values = $form-&gt;getValues();

    // redirection vers une page de confirmation
    header(&quot;Location: confirmation.php&quot;);
    exit;
  }
}

?&gt;
&lt; !DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
  &lt;head&gt;
    &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
    &lt;title&gt;Contact form example with sfForm&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
&lt;form action=&quot;index.php&quot; method=&quot;post&quot;&gt;
&lt;ul&gt;
        &lt;?php echo $form ?&gt;
&lt;li&gt;
&lt;input type=&quot;submit&quot; value=&quot;Submit&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/form&gt;

  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p><a href="/uploads/blog/2009/02/sfformtest.zip" class="link">Télécharger les sources</a></p>
<p>Pour aller plus loin et notamment pour comprendre la modularité des composants de Symfony, je vous conseille la lecture des slides de la conférence de Fabien Potencier, lors du forum PHP 2008, intitulée "<a href="http://fabien.potencier.org/talk/20/decouple-your-code-for-reusability-php-forum-2008" class="blank">Découpler votre code pour assurer la réutilisabilité et la maintenabilité</a>".</p>
]]></description>
    </item>
        <item>
      <title>[Article] Exercice de formulaire avec Zend_Form et sfForm</title>
      <link>http://jeremybarthe.com/fr/php/exercice-de-formulaire-avec-zend-form-et-sf-form</link>
      <guid>http://jeremybarthe.com/fr/php/exercice-de-formulaire-avec-zend-form-et-sf-form</guid>
      <comments>http://jeremybarthe.com/fr/php/exercice-de-formulaire-avec-zend-form-et-sf-form#comments</comments>
            <category><![CDATA[PHP]]></category>
            <author>Jérémy Barthe &lt;contact@jeremybarthe.com&gt;</author>
      <pubDate>Fri, 26 Dec 2008 00:00:00 +0100</pubDate>
      <description><![CDATA[<p>Bien, on connait maintenant <a href="/2008/11/12/astuces-integration-css-pour-ie/">quelques techniques d'intégration pour nous aider dans nos CSS sous IE 6</a>, voici un article plus technique !</p>
<p>J'avais envie de vous parler de <a href="http://www.symfony-project.org/" class="blank">Symfony</a> et <a href="http://framework.zend.com/" class="blank">Zend Framework</a>, il s'agit de 2 framework PHP apportant un développement pérenne, rapide et agile. Loin de moi l'idée de vous donner la définition d'un framework, ni même son utilité, bien des ressources existent sur Internet, <a href="http://www.biologeek.com/web-frameworks/definition-et-avantages-d-un-framework-web/" class="blank">à commencer par cet article</a>. Je vais plutôt m'attacher à vous présenter leur gestion des formulaires. L'exercice sera donc de créer un formulaire type avec ces 2 frameworks, ce qui nous permettra d'une part de comparer le code, et d'autre part de mesurer le temps qui aura été nécessaire.</p>
<p>Le but étant d'obtenir un <strong>formulaire généré</strong> donc facilement maintenable, un <strong>formulaire évidemment validé</strong> (à la fois pour contrôler les données saisies et pour nous éviter d'éventuelles failles), et enfin un <strong>formulaire internationalisé</strong>.</p>
<p>Petite pub au passage, pour mesurer mon temps j'ai utilisé la très sympathique application <a href="http://twodecember.com/fr/kronos/" class="blank">Kronos</a> édité par une <a href="http://twodecember.com/" class="blank">petite boite Montpellièraine</a>.</p>
<h4>Sommaire</h4>
<ul id="toc">
<li><a href="#form-desc">Descriptif du formulaire</a></li>
<li><a href="#Comparaison">Comparaison de codes</a></li>
<li><a href="#avis-sf-form">Avantages / inconvénients sfForm</a></li>
<li><a href="#avis-zend-form">Avantages / inconvénients Zend_Form</a></li>
<li><a href="#bilan">Bilan</a></li>
<li><a href="#conclusion">Conclusion</a></li>
<li><a href="#download">Téléchargement</a></li>
<li><a href="#ressources">Ressources</a></li>
</ul>
<h3 id="form-desc">Descriptif du formulaire</h3>
<p>Dans le cadre de cet exercice, j'ai défini d'une part les champs du formulaire, et d'autre part certaines contraintes techniques afin de compliquer légèrement la tâche.<br />
Attaquons le vif du sujet, voici <strong>les champs de notre formulaire</strong> :</p>
<table class="tab1 odd">
<tr>
<td>Type de demande</td>
<td>sélecteur / obligatoire</td>
</tr>
<tr>
<td>Nom</td>
<td>champ texte / obligatoire</td>
</tr>
<tr>
<td>Prénom</td>
<td>champ texte / obligatoire</td>
</tr>
<tr>
<td>Email</td>
<td>champ texte / obligatoire / validation de l'email</td>
</tr>
<tr>
<td>Message</td>
<td>zone de texte / obligatoire</td>
</tr>
<tr>
<td>Date de naissance</td>
<td>sélecteurs / validation de date</td>
</tr>
<tr>
<td>Inscription à la newsletter</td>
<td>case à cocher</td>
</tr>
</table>
<p>Les <strong>contraintes techniques</strong> (essentiellement sur la forme) sont les suivantes :</p>
<ul>
<li>le formulaire ne sera pas généré en tableau, mais en liste à puces ;</li>
<li>les "labels" des champs obligatoires seront suivi d'une étoile rouge ;</li>
<li>les champs "prénom" et "nom" doivent être côte à côte (flottants donc) ;</li>
<li>le champ "date de naissance" doit apparaître sous la forme de sélecteurs (on pourra éventuellement y ajouter un datepicker en javascript) ;</li>
<li>la case à cocher de l'inscription à la newsletter doit apparaître avant le "label" ;</li>
<li>la "vue" devra être la plus courte possible pour être flexible autant sur le fond que sur la forme.</li>
</ul>
<p>Et enfin, voici un screenshot du rendu souhaité :</p>
<p align="center"><a href="/uploads/blog/2008/12/form.jpg" rel="shadowbox"><img src="/uploads/blog/2008/12/form-mini.gif" alt="Formulaire" width="400" height="288" class="border" /></a></p>
</p>
<h3 id="Comparaison">Comparaison de codes</h3>
<p>Dans Symfony un formulaire est généré via la classe "sfForm", chaque éléments du formulaire se nommera un "widget", ils proviennent naturellement de la classe "sfWidget".</p>
<p>Dans Zend Framework un formulaire est généré via la classe "Zend_Form", chaque éléments du formulaire se nommera "element", ils proviennent de la classe "Zend_Form_Element".</p>
<p>Passons à la description du code et surtout à la comparaison des 2 écritures :</p>
<h4>Formulaire de contact avec Zend_Form</h4>
<pre class="php">
/**
 * Formulaire de contact avec Zend_Form du Zend Framework
 */
public function init()
{
    $this-&gt;setName('contact-form')
         -&gt;setAttrib('id', 'contact-form');

    $this-&gt;addElement('select', 'subject', array(
        'label' =&gt; 'subject',
        'required' =&gt; true,
        'multiOptions' =&gt; array('' =&gt; '', 1 =&gt; 'commercial', 2 =&gt; 'technical')
    ));

    $this-&gt;addElement('text', 'firstname', array(
        'label' =&gt; 'firstname',
        'required' =&gt; true,
        'validators' =&gt; array('alnum')
    ));

    $this-&gt;addElement('text', 'lastname', array(
        'label' =&gt; 'lastname',
        'required' =&gt; true,
        'validators' =&gt; array('alnum')
    ));

    $this-&gt;addElement('text', 'email', array(
        'label' =&gt; 'email',
        'required' =&gt; true,
        'validators' =&gt; array('EmailAddress')
    ));

    $this-&gt;addElement('textarea', 'message', array(
        'label' =&gt; 'message',
        'rows' =&gt; 5,
        'cols' =&gt; 50,
        'required' =&gt; true
    ));

    $this-&gt;addElement('text', 'birthday', array(
        'label' =&gt; 'birthday',
        'description' =&gt; 'birthdayDescription'
    ));
    // date validator
    $this-&gt;getElement('birthday')-&gt;addValidator(new Zend_Validate_Date(null, Zend_Registry::get('Zend_Translate')-&gt;getLocale()));

    $this-&gt;addElement('checkbox', 'newsletter', array(
        'label' =&gt; 'newsletter'
    ));

    $this-&gt;addElement('submit', 'submit', array(
        'label' =&gt; 'submit'
    ));

    /**
     * Decorators
     */
    $this-&gt;clearDecorators();

    $this-&gt;addDecorator('FormElements')
         -&gt;addDecorator('HtmlTag', array('tag' =&gt; '
&lt;ul&gt;', 'class' =&gt; 'form'))
         -&gt;addDecorator('Form');

    $this-&gt;setElementDecorators($this-&gt;_defaultDecorator);

    $this-&gt;getElement('firstname')-&gt;setDecorators($this-&gt;_floatLeftDecorator);
    $this-&gt;getElement('lastname')-&gt;setDecorators($this-&gt;_floatRightDecorator);
    $this-&gt;getElement('newsletter')-&gt;setDecorators($this-&gt;_inlineDecorator);
    $this-&gt;getElement('submit')-&gt;setDecorators($this-&gt;_submitDecorator);

    return $this;
}
&lt;/ul&gt;
</pre>
<h4>Formulaire de contact avec sfForm</h4>
<pre class="php">
/**
 * Formulaire de contact avec sfForm de Symfony
 */
public function configure()
{
  $subjects = array('' =&gt; '', 1 =&gt; __('commercial'), 2 =&gt; __('technical'));
  $years = range(date('Y') - 10, date('Y') - 100);

  $this-&gt;setWidgets(array(
    'subject'      =&gt; new sfWidgetFormSelect(array('choices' =&gt; $subjects)),
    'firstname'    =&gt; new sfWidgetFormInput(array(), array('maxlength' =&gt; 30)),
    'lastname'     =&gt; new sfWidgetFormInput(),
    'email'        =&gt; new sfWidgetFormInput(),
    'message'      =&gt; new sfWidgetFormTextarea(array(), array('cols' =&gt; 50, 'rows' =&gt; 5)),
    'birthday'     =&gt; new sfWidgetFormDate(array('format' =&gt; '%day%/%month%/%year%', 'years'  =&gt; $years)),
    'newsletter'   =&gt; new sfWidgetFormInputCheckbox(array()),
  ));

  $this-&gt;widgetSchema-&gt;setLabels(array(
    'subject'      =&gt; 'subject',
    'firstname'    =&gt; 'firstname',
    'lastname'     =&gt; 'lastname',
    'email'        =&gt; 'email',
    'message'      =&gt; 'message',
    'birthday'     =&gt; 'birthday',
    'newsletter'   =&gt; 'newsletter',
  ));

  $this-&gt;setValidators(array(
    'subject'      =&gt; new sfValidatorChoice(array('choices' =&gt; array_keys($subjects))),
    'firstname'    =&gt; new sfValidatorString(array('required' =&gt; true)),
    'lastname'     =&gt; new sfValidatorString(array('required' =&gt; true)),
    'email'        =&gt; new sfValidatorEmail(array('required' =&gt; true), array('invalid' =&gt; 'Veuillez indiquer un email valide')),
    'message'      =&gt; new sfValidatorString(array('required' =&gt; true)),
    'birthday'     =&gt; new sfValidatorDate(array('required' =&gt; false, 'date_format' =&gt; '/^[0-9]{2}\-[0-9]{2}\-[0-9]{4}$/', 'with_time' =&gt; false), array()),
    'newsletter'   =&gt; new sfValidatorString(array('required' =&gt; false)),
  ));

  $this-&gt;widgetSchema-&gt;setNameFormat('contact[%s]');

  $this-&gt;widgetSchema-&gt;setFormFormatterName('list');
}
</pre>
</p>
<h4>Contrôleur du Zend Framework</h4>
<pre class="php">
/**
 * Action du contrôleur de traitement du formulaire (Zend Framework)
 */
public function indexAction()
{
    // création d'une instance du formulaire
    $form = new Contact(array(
        'action' =&gt; $this-&gt;view-&gt;url(array('action' =&gt; 'index')),
        'method' =&gt; 'post'
    ));

    // vérification de la validité des données
    if ($this-&gt;_request-&gt;isPost() &amp;&amp; $form-&gt;isValid($this-&gt;_request-&gt;getPost())) {
        // récupération des données
        $values = $form-&gt;getValues();

        // traitement des données...

        // redirection vers la page de remerciements
        $this-&gt;_redirect('index/success');
        exit;
    }

    $this-&gt;view-&gt;form = $form;
}
</pre>
</p>
<h4>Contrôleur de Symfony</h4>
<pre class="php">
/**
 * Action du contrôleur de traitement du formulaire (Symfony)
 */
public function executeIndex($request)
{
  // création d'une instance du formulaire
  $this-&gt;form = new ContactForm();

  if ($request-&gt;isMethod('post'))
  {
    $this-&gt;form-&gt;bind($request-&gt;getParameter('contact'));
    // vérification de la validité des données
    if ($this-&gt;form-&gt;isValid())
    {
      // récupération des données
      $values = $this-&gt;form-&gt;getValues();

      // traitement des données...

      // redirection vers la page de remerciements
      $this-&gt;redirect('form/success');
    }
  }
}
</pre>
</p>
<h4>Vue du Zend Framework</h4>
<pre class="php">
&lt;?php echo $this-&gt;form ?&gt;
</pre>
</p>
<h4>Vue de Symfony</h4>
<pre class="php">
&lt;form name=&quot;form&quot; action=&quot;&lt;?php echo url_for('form/index') ?&gt;&quot; method=&quot;post&quot;&gt;
&lt;ul class=&quot;form&quot;&gt;
    &lt;?php echo $form['subject']-&gt;renderRow() ?&gt;
&lt;li class=&quot;left&quot;&gt;
      &lt;?php echo $form['lastname']-&gt;renderError() ?&gt;
      &lt;?php echo $form['firstname']-&gt;renderLabel() ?&gt;
      &lt;?php echo $form['firstname']-&gt;render() ?&gt;
    &lt;/li&gt;
&lt;li class=&quot;right&quot;&gt;
      &lt;?php echo $form['lastname']-&gt;renderError() ?&gt;
      &lt;?php echo $form['lastname']-&gt;renderLabel() ?&gt;
      &lt;?php echo $form['lastname']-&gt;render() ?&gt;
    &lt;/li&gt;

    &lt;?php echo $form['email']-&gt;renderRow() ?&gt;
    &lt;?php echo $form['message']-&gt;renderRow() ?&gt;
    &lt;?php echo $form['birthday']-&gt;renderRow() ?&gt;
&lt;li&gt;
      &lt;?php echo $form['newsletter']-&gt;render() ?&gt;
      &lt;?php echo $form['newsletter']-&gt;renderLabel(null, array('class' =&gt; 'inline')) ?&gt;
    &lt;/li&gt;
&lt;li&gt;
&lt;input type=&quot;submit&quot; name=&quot;submit&quot; id=&quot;submit&quot; value=&quot;&lt;?php echo __('submit') ?/&gt;&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/form&gt;
</pre>
<h3 id="avis-sf-form">Avantages /<br /> inconvénients<br /> sfForm</h3>
<div class="important">
<p class="title">Avantages :</p>
<ul>
<li>simple d'utilisation ;</li>
<li>souplesse notamment <a href="http://www.symfony-project.org/book/forms/1_2/fr/03-Forms-for-web-Designers" class="blank">au niveau de la vue et de ses nombreuses méthodes</a> ;</li>
<li>nombreux validateurs et fonctionnalités très complètes ;</li>
<li>framework en lui même, donc utilisable sans Symfony ;</li>
</ul>
</div>
<div class="important">
<p class="title">Inconvénients :</p>
<ul>
<li>pas de gestion des fieldset avec legend (aucune possibilité de grouper des widget) ;</li>
<li>pas de génération complète du formulaire (balises form et submit à ajouter manuellement dans la vue, je reviens sur ce point en conclusion) ;</li>
<li>"formatter" plus limitée que les "decorators" de Zend_Form (pas de surcharge d'un "formatter" pour un widget spécifique) ;</li>
<li>recopie inutile des labels pour l'internationalisation ;</li>
</ul>
</div>
<h3 id="avis-zend-form">Avantages /<br /> inconvénients<br /> Zend_Form</h3>
<div class="important">
<p class="title">Avantages :</p>
<ul>
<li>génération totale du formulaire ;</li>
<li>système des "decorators" flexibles et complets ;</li>
</ul>
</div>
<div class="important">
<p class="title">Inconvénients :</p>
<ul>
<li>assez verbeux à écrire (bien qu'il existe <a href="http://framework.zend.com/manual/fr/zend.form.quickstart.html#zend.form.quickstart.elements" class="blank">plusieurs façons d'écrire un formulaire avec Zend_Form</a>) ;</li>
<li>"decorators" complexes à comprendre et à mettre en place (résultats parfois aléatoire) ;</li>
<li>manque certains éléments ou validateurs de base (date).</li>
</ul>
</div>
<h3 id="bilan">Bilan</h3>
<p>Question temps, j'ai mis un peu plus de 4h pour réaliser ce formulaire avec Symfony et pas loin de 5h avec Zend Framework. En sachant que je n'ai pas compté le temps de mise en place du projet, ce temps étant annexe à l'exercice et d'autant plus car la logique de création d'un projet est assez différente entre Symfony et Zend Framework. Symfony est ce que l'on appelle un "full stack framework" (comprendre tu dézippes, tu as toute l'arborescence de ton projet), tandis que Zend Framework laisse libre la structuration de son projet, il donne seulement quelques recommandations.</p>
<p>Ce temps a été découpé en relecture de la documentation, création du formulaire et mise en place d'un layout.<br />
On peut trouver le temps de réalisation un peu long en comparaison d'un formulaire généré "from scratch", pour autant avec ces 2 librairies je dispose de nombreux composants, de nombreux validateurs, d'une bonne sécurité et surtout d'une flexibilité.</p>
<p>Enfin dans les 2 cas, je n'ai pas pleinement rempli les contraintes de départ de mon exercice :</p>
<div class="important">
<p class="title">Concernant Symfony :</p>
<ul>
<li>pas d'étoile rouge après les labels des champs obligatoires (possible à faire dans le "formatter" ?) ;</li>
<li>le fichier de la vue est un peu chargé, vu que les affichages spécifiques ne sont pas gérés via un "formatter" ;</li>
</ul>
</div>
<div class="important">
<p class="title">Concernant Zend Framework :</p>
<ul>
<li>le champ date de naissance n'est pas géré avec des sélecteurs, le composant n'est pas de base implémenté dans le framework ;</li>
<li>le label de l'inscription à la newsletter se trouve avant la case à cocher (je n'ai pas trouvé le moyen de le faire avec les "décorators").</li>
</ul>
</div>
<h3 id="conclusion">Conclusion</h3>
<p>On peut constater que la manière de créer un formulaire avec ces 2 composants est relativement semblable, tout du moins elle l'est sur un exemple aussi simple. Une fois que la logique est comprise, on peut assez facilement passer de l'un à l'autre.</p>
<p>Au delà de l'aspect coeur de réalisation, j'entends par là design pattern mis en oeuvre ou encore logique interne, j'ai surtout le sentiment que ces 2 composants diffèrent sur la forme :</p>
<p>sfForm et Zend_Form se différencient principalement au niveau de la génération de la partie vue :</p>
<ul>
<li>sfForm par le biais des "formatter" propose seulement un gabarit général de présentation du formulaire. Les cas particuliers, les affichages spécifiques seront à votre charge dans la vue, nous allons voir ci-dessous comment ce choix est justifié.</li>
<li>Zend_Form quant à lui donne la possibilité de créer de multiples "decorators" qui décrivent chacun un comportement du formulaire. En résumé, vous pouvez définir un "decorator" par défaut (qui agira au même titre qu'un "formatter") ainsi que des "decorators" spécifiques à chaque rendu graphique.</li>
</ul>
<h4>Génération complète du formulaire</h4>
<p>On peut se demander l'intérêt d'une génération complète du formulaire, voici quelques exemples :</p>
<ul>
<li>pour chaque champ ajouté dans le formulaire, il faudra penser à l'ajouter dans la vue (et gare aux erreurs sur le nom des champs) ;</li>
<li>si je fais une modification générale sur le gabarit, il me sera nécessaire de la répercuter au niveau spécifique du formulaire, par exemple si je ne souhaite plus gérer mon formulaire via des listes à puces mais plutôt avec des div ou des listes de définitions, il me sera nécessaire de modifier le "formatter" du formulaire ainsi que la vue (si j'oublie, j'aurais de belles erreurs xhtml...) ;</li>
<li>plus fréquent, j'ajoute un champ upload, il me faudra penser à ajouter l'entête enctype dans le formulaire... ;</li>
</ul>
<p>Tout ceci manque un peu de modularité en somme, utiliser un outil de génération des formulaires devrait nous permettre de nous décharger de ce genre de "soucis", le framework doit les prendre en charge pour nous.</p>
<h4>Différence entre formatter et decorators</h4>
<p>Les "formatters" de Symfony gèrent le comportement de l'intégralité du formulaire, il n'est pas possible (à ma connaissance) de personnaliser le "formatter" d'un "widget" en particulier. Sous Zend Framework les "decorators" interviennent au niveau général du formulaire et au niveau de chaque "element", je trouve ce système plus modulaire, je m'explique : l'avantage principal que je vois à cette technique, c'est que je peux préparer les comportements spécifiques de mes formulaires (élément à gauche, élément à droite, élément sans label, élément en ligne pour une case à cocher par exemple, etc.) et je les utilise ensuite librement dans mes formulaires, sans avoir à modifier ma vue.</p>
<p>Après quelques recherches et notamment à la lecture de l'article "<a href="http://www.aide-de-camp.org/article/3/fr/les-formulaires-symfony-1-1-et-le-pattern-mvc" class="blank">Les formulaires Symfony 1.1 et le pattern MVC</a>" du <a href="http://www.aide-de-camp.org/">blog de Fabien Potencier</a>, j'apprends que ce choix a été fait dans un respect du pattern MVC, et on peut y lire :</p>
<blockquote class="inline"><p>"Mais il faut garder à l'esprit que echo $form est juste un raccourci sympathique. Il est très pratique pour créer un prototype rapide mais la plupart du temps, vous voudrez avoir un contrôle plus important sur le rendu du formulaire et sur la disposition des différents widgets dans la page. Et c'est là que le nouveau système est vraiment puissant. Le travail des intégrateurs est grandement simplifié."</p></blockquote>
<p>J'en suis venu à me demander si le système des "decorators" du Zend Framework respectait le patten MVC, mais je pense que oui, puisqu'ils décrivent des comportements de rendu graphique (en l'occurence HTML) au même titre que le "formatter" de Symfony... Qu'en pensez vous ?</p>
<p>On continue avec une deuxième justification de ce choix dans la <a href="http://www.symfony-project.org/book/forms/1_2/fr/03-Forms-for-web-Designers#L%27Interaction%20avec%20le%20D%C3%A9veloppeur" class="blank">documentation officielle de sfForm</a>, nous avons là un scénario de travail en équipe, où développeurs et intégrateurs travaillent en parallèle sur le même projet grâce à ce système découpé.</p>
<p>Certes l'analyse est bonne mais sur ce point je trouve Zend_Form intéressant étant donné que je suis à la fois développeur et intégrateur sur mes projets, c'est donc naturellement moi qui définit les différents "décorators", donc les différents comportements possibles de mes formulaires. A l'inverse une équipe qui travaillera sur le modèle défini ci-dessus sera peut être gênée par ce modèle car c'est aux développeurs d'agir sur les "decorators" et non aux intégrateurs...</p>
<h4>Avis perso</h4>
<div class="important">
<p class="title">Dans sfForm, j'ai aimé :</p>
<ul>
<li>la simplicité d'utilisation ;</li>
<li>le nombre de "widgets" et la quantité de validateurs ;</li>
<li>le fait que sfForm soit un framework en lui même donc utilisable sans Symfony ;</li>
<li>la génération de formulaire et l'intégration avec Propel et Doctrine qui va infiniment plus loin que Zend_Form.</li>
</ul>
</div>
<div class="important">
<p class="title">Dans sfForm, j'ai pas aimé :</p>
<ul>
<li>la gestion des "formatter" ;</li>
<li>l'obligation de coder dans la vue dans les cas spécifiques ;</li>
</ul>
</div>
<div class="important">
<p class="title">Dans Zend_Form, j'ai aimé :</p>
<ul>
<li>génération complète du formulaire au moyen des "decorators" ;</li>
</ul>
</div>
<div class="important">
<p class="title">Dans Zend_Form, j'ai pas aimé :</p>
<ul>
<li>le réel manque d'éléments et de validateurs (il n'y a même pas un validateur pour vérifier l'égalité entre 2 champs...) ;</li>
<li>trop d'écritures alternatives d'un formulaire : il existe 4 ou 5 façon différentes d'écrire un formulaire avec Zend_Form. C'est bien de laisser de la liberté aux développeurs mais un framework est censé apporter des normes et une cohésion.</li>
</ul>
</div>
<h3 id="download">Téléchargement</h3>
<p><a href="/uploads/blog/2008/12/form-sf.zip" class="link">Télécharger l'exercice avec Symfony</a></p>
<p><a href="/uploads/blog/2008/12/form-zf.zip" class="link">Télécharger l'exercice avec Zend Framework</a></p>
<p><small>(par simplicité je n'ai pas configuré ces 2 projets pour fonctionner avec un virtual host, ils sont tous 2 gérés avec des adresses relatives)</small></p>
<h3 id="ressources">Ressources</h3>
<div class="important">
<p class="title">sfForm de Symfony :</p>
<ul>
<li><a href="http://www.symfony-project.org/book/forms/1_1/fr/" class="blank">La documentation officielle de sfForm</a> ;</li>
<li>Aller plus loin avec la <a href="http://www.symfony-project.org/book/forms/1_1/fr/04-Propel-Integration#La%20G%C3%A9n%C3%A9ration%20des%20Formulaires" class="blank">génération des formulaires avec Propel</a> ou <a href="http://www.symfony-project.org/book/forms/1_1/fr/11-Doctrine-Integration#G%C3%A9n%C3%A9rer%20les%20classes%20de%20formulaires" class="blank">Doctrine</a> ;</li>
<li><a href="http://www.aide-de-camp.org/article/3/fr/les-formulaires-symfony-1-1-et-le-pattern-mvc" class="blank">Les formulaires Symfony 1.1 et le pattern MVC</a></li>
</ul>
</div>
<div class="important">
<p class="title">Zend_Form du Zend Framework :</p>
<ul>
<li><a href="http://framework.zend.com/manual/fr/zend.form.html" class="blank">La documentation officielle de Zend_Form</a> ;</li>
<li><a href="http://blog.developpez.com/julienpauli?title=utilisation_toute_simple_de_zend_form" class="blank">Utilisation toute simple de Zend_Form par Julien Pauli</a></li>
<li><a href="http://devzone.zend.com/article/3450-Decorators-with-Zend_Form" class="blank">En savoir plus sur les "decorators" du Zend_Form</a></li>
</ul>
</div>
<p>Voilà pour cet article, beaucoup risquent de trouver que je survole de très haut les fonctionnalités de ces 2 composants, le but n'était pas de donner un tutoriel avancé, mais plutôt de se donner un exercice (avec ses facilités et ses contraintes) et de tenter de s'approcher au maximum du résultat escompté avec ces 2 composants. Le but final est plutôt de donner envie aux développeurs qui ne connaissent ni <a href="http://www.symfony-project.org/" class="blank">Symfony</a>, ni <a href="http://framework.zend.com/" class="blank">Zend Framework</a> de tenter l'expérience, car l'un comme l'autre, ces frameworks donnent lieu à un développement beaucoup plus agréable !</p>
<div class="information">Si vous relevez des coquilles ou améliorations à apporter à cet article, n'hésitez pas, le formulaire de commentaire ci-dessous est là pour ça.</div>
]]></description>
    </item>
        
  </channel>
</rss>
