<?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:00:31 +0200</pubDate>
    <lastBuildDate>Tue, 07 Sep 2010 21:00:31 +0200</lastBuildDate>
    <language>fr</language>
    
        <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>
        <item>
      <title>[Article] Gestion d&#039;erreurs PHP au niveau du SGBD</title>
      <link>http://jeremybarthe.com/fr/php/gestion-des-erreurs-php-au-niveau-du-sgbd</link>
      <guid>http://jeremybarthe.com/fr/php/gestion-des-erreurs-php-au-niveau-du-sgbd</guid>
      <comments>http://jeremybarthe.com/fr/php/gestion-des-erreurs-php-au-niveau-du-sgbd#comments</comments>
            <category><![CDATA[PHP]]></category>
            <author>Jérémy Barthe &lt;contact@jeremybarthe.com&gt;</author>
      <pubDate>Thu, 16 Jun 2005 03:17:00 +0200</pubDate>
      <description><![CDATA[<p class="information"><strong>Attention :</strong> cet article a été rédigé en 2005, le contenu ou les éléments abordées peuvent être obsolète.</p>
<p><em>Remarque : L'exemple suivant est traité avec PHP 5 et SQLite (<a href="http://fr.wikipedia.org/wiki/SQLite" hreflang="fr">def. wikipédia</a>).</em></p>
<p><strong>Nature de l'exemple :</strong> Prenons un exemple simple, vous traitez des projets et des employés. Vous gérez un système permettant d'assigner des employés sur un ou plusieurs projets (jusque la rien de compliqué). La contrainte est la suivante : il ne peut y avoir plus de quatre employés assignés à un projet.</p>
<h3>Accéder à une base de donnée SQLite via PHP</h3>
<p>Vous avez deux possibilités pour accéder à une base de donnée SQLite, la méthode procédurale (qui est à éviter si vous coder en PHP 5) et la méthode objet, méthode que je vais présenter.</p>
<p><em>Remarque : Votre base de donnée doit forcément se trouver avec un droit d'accès 777.</em></p>
<h5>Méthode procédurale :</h5>
<pre class="php">$db = sqlite_open(&quot;db/gestionProjet.db&quot;);</pre>
<p> </p>
<h5>Méthode objet :</h5>
<pre class="php">$sqlite = new SQLiteDatabase(&quot;db/gestionProjet.db&quot;);</pre>
<p><em>Information : Il est possible de faire passer deux paramètres de plus, le mode d'accès qui pour le moment est ignoré des bibliothèques de SQLite (valeur par défaut 0666), et un message d'erreur affiché dans le cas où la base n'arrive pas à être ouverte.</em></p>
<h3>Résolution de la contrainte (ancienne méthode)</h3>
<p>Avant, nous aurions simplement exécuté une requête allant compter le nombre de participants actuel au projet, si le chiffre était inférieur à quatre, alors nous aurions laissé faire la requête d'insertion d'un participant, dans le cas contraire nous aurions directement affiché un message d'erreur.</p>
<p><em>Information : La table qui contient les employés participants à des projets s'appelle participer et le champ de cette table qui fait lien avec un projet s'appelle partProjet.</em></p>
<p>Voici le code :</p>
<pre class="php">$nb = $sqlite-&gt;singleQuery(&quot;select count(*) from participer where partProjet=&quot;.$_POST['projet'].&quot;&quot;);
if ($nb &lt; 4) {
     // Requête d'insertion
} else {
     // Message d'erreur (cause : il faut moins de quatre participants pour un projet)
}</pre>
<h3>Résolution de la contrainte (utilisation d'un déclencheur)</h3>
<p>Gràce à SQLite, il est possible de mettre en place un déclencheur (trigger), il est spécifié pour ce dernier dans quelle condition et sur quelle table il sera appelé automatiquement. La condition spécifie si l'action se fera lors d'une insertion (insert), d'une modification (update) ou d'une suppression (delete) ensuite il faut préciser sur quelle table se fera cette vérification. Par la suite automatiquement, lors d'une insertion sur la table spécifié, par exemple, un traitement viendra s'exécuter.</p>
<p>On peut de plus accéder aux données de la requête qui a amené au traitement du déclencheur.</p>
<ul>
<li>Lors d'une insertion, on utilisera le mot clé <em>new</em> avant le champ que l'on cherche à récupérer.</li>
<li>Lors d'une modification, on utilisera <em>old</em> pour accéder à la valeur qui va être remplacée, et <em>new</em> pour accéder à la valeur de remplacement.</li>
<li>Lors d'une suppression, on utilisera <em>old</em> pour accéder à la valeur qui va être supprimée.</li>
</ul>
<p><em>Information : Je ne connais pas trop le langage SQL de SQLite qui permet de faire les déclencheurs, j'ai appris qu'il était fortement semblable au PL SQL de Oracle. Pour ma part j'ai repris un exemple pour m'inspirer de mes déclencheurs.</em></p>
<p>Il faut ensuite mettre en place un déclencheur de ce style :</p>
<pre class="sql">create trigger verifNbreParticipants before insert on participer for each row
begin
select case
when (select count(*) from participer where partProjet=new.partProjet)&gt;=4 then raise (fail, 'Erreur nombre participants')
end;
end;</pre>
<p><em>Information : Exécutez simplement une requête à la base de donnée contenant ce déclencheur pour l'activer.</em></p>
<p>A partir de la, refaites votre insertion, jusqu'à ce qu'il y ai quatre participants pour un projet. Vous verrez apparaître une belle erreur en haut de votre navigateur :</p>
<pre class="php">Warning: SQLiteDatabase::query() [function.query]: Erreur nombre participants</pre>
<p>On reconnaît tout de même le message d'erreur que l'on a prévu dans le déclencheur :</p>
<pre class="php">raise (fail, 'Erreur nombre participants')</pre>
<h3>Redéfinition des messages d'erreurs en PHP</h3>
<p>On ne va pas laisser cette vieille erreur en haut du navigateur quand même ?! La méthode <em>set_error_handler()</em> nous permet de redéfinir les messages d'erreurs de PHP. Il suffit de lui passer en paramètre le nom de la fonction qui prendra en charge les messages d'erreurs.</p>
<p><em>Information : Vous trouverez plus d'information sur cette fonction et sur les paramètres spécifiés ci-dessous, <a href="http://www.nexen.net/docs/php/annotee/function.set-error-handler.php?lien=handler" hreflang="fr">ici</a>.</em></p>
<p>Créons une fonction de gestion des erreurs :</p>
<pre class="php">function gestionErreur($errno, $errstr, $errfile, $errline) {
     if (ereg(&quot;Erreur nombre participants&quot;, $errstr)) {
          $erreur = &quot;Il ne peut pas y avoir plus de quatre développeurs sur un même projet.&quot;;
     }
}</pre>
<p>A partir de la vous pouvez faire afficher cette erreur à l'endroit où vous voulez et avec votre propre mise en page, comme ceci :<br />
<img src="/uploads/skillexchange/Divers/gestionErreur.jpg" alt="" width="401" class="border" /></p>
<h3>Conclusion</h3>
<p>Ce style de programmation permet de bien séparer les tàches et les traitements.<br />
Verdict : je langi vraiment que ce soit implémenté sous MySQL.</p>
]]></description>
    </item>
        <item>
      <title>[Article] Faire son propre moteur de template</title>
      <link>http://jeremybarthe.com/fr/php/faire-son-propre-moteur-de-template</link>
      <guid>http://jeremybarthe.com/fr/php/faire-son-propre-moteur-de-template</guid>
      <comments>http://jeremybarthe.com/fr/php/faire-son-propre-moteur-de-template#comments</comments>
            <category><![CDATA[PHP]]></category>
            <author>Jérémy Barthe &lt;contact@jeremybarthe.com&gt;</author>
      <pubDate>Thu, 14 Apr 2005 17:53:00 +0200</pubDate>
      <description><![CDATA[<p>On est loin des <a href="http://smarty.php.net/">Smarty</a> ou autre <a href="http://www.templeet.org/index.fr.html">templeet</a>, mais l'idée de programmer son propre moteur de template peut être interessante, d'autant plus lorsque votre projet PHP est simple et ne demande donc pas l'utilisation des fonctions complexes de tels moteurs de templates. Vous gagnerez ainsi en rapidité d'execution et en consomation de ressource serveur.</p>
<h4>Mais tout d'abord, qu'est ce qu'un moteur de template ?</h4>
<p>Le moteur de template est un moyen élégant de séparer la forme, de la programmation <i>(le fond)</i>. D'un côté vous aurez votre programmation PHP / ASP / etc. <i>(dans notre cas PHP)</i> et de l'autre vos différents fichiers templates correspondants à un modèle de mise en page.<br />
La conception du projet d'une part, et la conception des pages d'autre part seront grandement facilité.<br />
Immaginez une page PHP sans <i>echo "";</i> ^^<br />
Dans la même optique, fini les <i>"</i> au milieu du HTML :)<br />
Quelques exemples parmis bien d'autres qui vous facilitent la vie lors de l'utilisation d'un moteur de template. </p>
<h4>Rôle du moteur de template</h4>
<p>Le moteur de template va simplement afficher la page que vous souhaitez, en d'autre terme, vous passerez en paramètre le nom du fichier à afficher et le moteur de template se charge du reste.<br />
Vous avez en plus de cela la possibilité de faire afficher la valeur de retour d'une variable, chose pratique sinon vos pages aurez été statique :) Il vous faudra donc choisir un formalisme de notation des variables pour votre moteur de template. Dans l'exemple suivant, le voici : <i>{variable}</i>. La variable <i>{variable}</i> devra donc être remplacée par une valeur. Ce procédé se fait dans votre programmation PHP, juste avant d'afficher le contenu d'un fichier template. </p>
<h4>Les données de la classe de votre moteur de template</h4>
<p>En premier lieu votre fichier devra comporter l'entête de la classe, c'est à dire :</p>
<pre class="php">&lt;?php
class template {}
?&gt;</pre>
<p>Les données vous aideront sans doute à comprendre ce qu'il faut stocker pour que le moteur de template fonctionne, les voici : </p>
<pre class="php">private $repertoireTemplate;
private $contenuAAfficher;
private $variablesAssigneesCle;
private $variablesAssigneesValeur;</pre>
<p><b>$repertoireTemplate</b> contient le chemin vers le répertoire contenant vos fichiers template.<br />
<b>$contenuAAfficher</b> représente le contenu de votre fichier template à afficher.<br />
<b>$variablesAssigneesCle</b> c'est le nom de la variable du moteur de template à remplacer, dans notre cas ci-dessus <i>({variable})</i>, il faudrait donc mettre en clé "variable".<br />
<b>$variablesAssigneesValeur;</b> représente les valeurs de remplacement des variables du moteur de template. </p>
<h4>Le contructeur de la classe</h4>
<pre class="php">function __construct($repertoire) {
     $this-&gt;repertoireTemplate = $repertoire;
     $this-&gt;contenuAAfficher = &quot;&quot;;
     $this-&gt;variablesAssigneesCle = array();
     $this-&gt;variablesAssigneesValeur = array();
}</pre>
<p>Ce constructeur reçoit qu'un paramètre, le chemin vers le répertoire de vos fichiers templates.<br />
Vous allez maintenant voir à quoi ressemble l'entête de votre fichier PHP :</p>
<pre class="php">&lt;?php
require(&quot;template.class.php&quot;); // moteur de template
$tpl = new template(&quot;templates/&quot;);
?&gt;</pre>
<h4>Assigner une valeur PHP à une variable du moteur de template</h4>
<p>La fonction suivante vous permettra d'assigner une clé à une valeur, la clé est le nom de votre variable dans le moteur de template, tandis que la valeur peut être une variable PHP, le résultat d'une requête, une simple chaîne de caractère.</p>
<pre class="php">function ajouteAccolade($val) {
     return &quot;{&quot;.$val.&quot;}&quot;;
}

function assigner($cle, $valeur) {
     $cle = $this-&gt;ajouteAccolade($cle);
     array_push($this-&gt;variablesAssigneesCle, $cle);
     array_push($this-&gt;variablesAssigneesValeur, $valeur);
}</pre>
<p>La fonction <i>ajouteAccolade($val)</i> est en lien avec la notation des variables que nous avons choisi. Si vous souhaitez la changer, c'est ici que ça se passe :)<br />
<i>assigner($cle, $valeur)</i> quant à elle rajoute au tableau de clé et de valeur, les valeurs passées en paramètres. C'est à partir de ce tableau de clé et de valeur que nous ferons ensuite le changement des variables du moteur de template, juste avant d'afficher le contenu. Pour l'exemple (dans votre fichier PHP) : </p>
<pre class="php">$test = &quot;Gnome&quot;;
$tpl-&gt;assigner(&quot;test&quot;, $test);</pre>
<h4>Afficher le contenu d'un fichier template et remplacer les variables par des valeurs</h4>
<p>Voici le code de la fonction :</p>
<pre class="php">function ajouterTemplate($fichier) {
$this-&gt;contenuAAfficher = file_get_contents($this-&gt;repertoireTemplate.$fichier);
}

function afficher($fichier) {
     $this-&gt;ajouterTemplate($fichier);
     $this-&gt;contenuAAfficher = str_replace($this-&gt;variablesAssigneesCle, $this-&gt;variablesAssigneesValeur, $this-&gt;contenuAAfficher);
     echo $this-&gt;contenuAAfficher;
     $this-&gt;contenuAAfficher = &quot;&quot;;
     $this-&gt;variablesAssigneesCle = array();
     $this-&gt;variablesAssigneesValeur = array();
}</pre>
<p>La fonction <i>ajouterTemplate($fichier)</i> récupére tout le contenu du fichier template. <i>afficher($fichier)</i> quant à elle remplace les valeurs des clés par les valeurs des valeurs ^^ et  affiche le résultat. Il faut penser à réinitialiser les variables à vide, sinon votre texte va se cumuler et je ne traiterai pas ce modèle de template ici. Certains en effet permettent d'enregistrer le contenu de plusieurs fichiers templates et de les afficher tous à la fin.<br />
Toujours avec la même simplicité, voila comment faire afficher le contenu d'un fichier template dans votre navigateur. Tout d'abord il vous faut éditer votre premier fichier template :</p>
<pre class="html">Hello World! 
(Ca fait geek ça) 
{test} applets are nice!</pre>
<p>Vous enregistrerez ce dernier dans votre répertoire de templates sous un nom quelconque.<br />
Du côté PHP, voici ce que ça donne :</p>
<pre class="php">&lt;?php
require(&quot;template.class.php&quot;); // moteur de template
$tpl = new template(&quot;templates/&quot;);
$test = &quot;Gnome&quot;;
$tpl-&gt;assigner(&quot;test&quot;, $test);
$tpl-&gt;afficher(&quot;nomdufichiertemplate.tpl&quot;);
?&gt;</pre>
<p>{test} va être remplacé par Gnome dans notre exemple, ce qui donnera au final :</p>
<pre class="html">Hello World!
(Ca fait geek ça)
Gnome applets are nice!</pre>
<h4>Code complet du moteur de template</h4>
<pre class="php">
&lt;?php

class template {
	private $repertoireTemplate;
	private $contenuAAfficher;
	private $variablesAssigneesCle;
	private $variablesAssigneesValeur;

	function __construct($repertoire) {
		$this-&gt;repertoireTemplate = $repertoire;
		$this-&gt;contenuAAfficher = &quot;&quot;;
		$this-&gt;variablesAssigneesCle = array();
		$this-&gt;variablesAssigneesValeur = array();
	}

	function ajouterTemplate($fichier) {
		$this-&gt;contenuAAfficher = file_get_contents($this-&gt;repertoireTemplate.$fichier);
	}

	function assigner($cle, $valeur) {
		$cle = $this-&gt;ajouteAccolade($cle);
		array_push($this-&gt;variablesAssigneesCle, $cle);
		array_push($this-&gt;variablesAssigneesValeur, $valeur);
	}

	function ajouteAccolade($val) {
		return &quot;{&quot;.$val.&quot;}&quot;;
	}

	function afficher($fichier) {

		$this-&gt;ajouterTemplate($fichier);
		$this-&gt;contenuAAfficher = str_replace($this-&gt;variablesAssigneesCle, $this-&gt;variablesAssigneesValeur, $this-&gt;contenuAAfficher);
		echo $this-&gt;contenuAAfficher;
		$this-&gt;contenuAAfficher = &quot;&quot;;
		$this-&gt;variablesAssigneesCle = array();
		$this-&gt;variablesAssigneesValeur = array();
	}

	function setRepertoireTemplate($repertoire) {
		$this-&gt;repertoireTemplate = $repertoire;
	}
}

?&gt;</pre>
<h4>Conclusion</h4>
<p>Les moteurs de templates du style Smarty ou Templeet, vous permettront évidemment de faire beaucoup plus, puiqu'il vous sera possible d'intégrer un code ressemblant au PHP directement dans vos fichiers templates, ce qui vous permettra par exemple d'effectuer une boucle foreach ou un if. Ces moteurs de template compilent un fichier PHP à partir des informations renseignées dans le fichier template. Ils conservent donc une trace et permettent un système de cache. </p>
<p>Donc le moteur de template que je viens de vous présenter là est beaucoup moins complet, mais ne fait que 45 lignes de codes lol :) </p>
<p><i>Pour information, cette technique n'est peut être pas la meilleure, ou peut être déjà connue, je ne sais pas, mais bon, on fait partager, ce qu'on peut faire partager :) <br />j'espère que cet article n'est pas trop décousu et qu'il vous aidera.</i></p>
]]></description>
    </item>
        
  </channel>
</rss>
