<!-- EN-Revision: 13843 -->
<sect1 id="zend.form.quickstart">
    <title>Zend_Form démarrage rapide</title>

    <para>Ce guide rapide couvre les bases de la création, de la validation, et du rendu des formulaires
    <classname>Zend_Form</classname>.</para>

    <sect2 id="zend.form.quickstart.create">
        <title>Créer un objet de formulaire</title>

        <para>Instanciez simplement un objet <classname>Zend_Form</classname> :</para>

        <programlisting role="php"><![CDATA[
$form = new Zend_Form;
]]></programlisting>

        <para>Pour des usages avancés, vous voudriez probablement dériver <classname>Zend_Form</classname>, mais pour les
        formulaires simples, vous pouvez créez un formulaire depuis une instance de <classname>Zend_Form</classname>.</para>

        <para>Vous pouvez spécifier (c'est une bonne idée) l'action et la méthode d'envoi du formulaire grâce à
        <code>setAction()</code> et <code>setMethod()</code> :</para>

        <programlisting role="php"><![CDATA[
$form->setAction('/resource/process')
     ->setMethod('post');
]]></programlisting>

        <para>Le code ci-dessus indique au formulaire d'être envoyé vers l'URL "/resource/process" avec la méthode HTTP
        POST. Ceci va impacter le rendu du formulaire (la balise <code>&lt;form&gt;</code>).</para>

        <para>Il est possible d'assigner les attributs HTML supplémentaires à la balise <code>&lt;form&gt;</code> via la
        méthode <code>setAttrib()</code> ou encore <code>setAttribs()</code>. Par exemple, indiquons un attribut "id" au
        formulaire :</para>

        <programlisting role="php"><![CDATA[
$form->setAttrib('id', 'login');
]]></programlisting>
    </sect2>

    <sect2 id="zend.form.quickstart.elements">
        <title>Ajouter des éléments au formulaire</title>

        <para>Un formulaire ne sert à rien sans éléments. Le composant <classname>Zend_Form</classname> est fourni avec un
        ensemble d'éléments qui rendent du code XHTML via les aides de <classname>Zend_View</classname>. Voici ces aides :</para>

        <itemizedlist>
            <listitem>
                <para>button</para>
            </listitem>

            <listitem>
                <para>checkbox (ou plusieurs checkboxes avec multiCheckbox)</para>
            </listitem>

            <listitem>
                <para>hidden</para>
            </listitem>

            <listitem>
                <para>image</para>
            </listitem>

            <listitem>
                <para>password</para>
            </listitem>

            <listitem>
                <para>radio</para>
            </listitem>

            <listitem>
                <para>reset</para>
            </listitem>

            <listitem>
                <para>select (régulier ou à selection multiple)</para>
            </listitem>

            <listitem>
                <para>submit</para>
            </listitem>

            <listitem>
                <para>text</para>
            </listitem>

            <listitem>
                <para>textarea</para>
            </listitem>
        </itemizedlist>

        <para>Vous avez 2 manières de procéder pour ajouter les éléments au formulaire : instanciez vous même les objets
        des éléments, ou passer le type d'élément à <classname>Zend_Form</classname>, qui va alors créer le bon objet pour
        vous.</para>

        <para>Quelques exemples :</para>

        <programlisting role="php"><![CDATA[
// Ajout d'un objet élément :
$form->addElement(new Zend_Form_Element_Text('username'));

// Passage d'un texte décrivant le futur objet élément, à Zend_Form :
$form->addElement('text', 'username');
]]></programlisting>

        <para>Par défaut, ces éléments n'ont ni validateurs, ni filtres. Vous devrez donc ajoutez des validateurs et/ou
        des filtres, manuellement. Ceci est possible soit (a) avant de passer l'élément au formulaire, (b) via les
        options de configuration passés lors de la création de l'élément, ou (c) en récupérant l'objet déjà enregistré,
        depuis le formulaire, et en le configurant ensuite.</para>

        <para>Voyons comment passer un validateur à un élément dont nous créons l'objet. On peut passer soit l'objet
        <classname>Zend_Validate_*</classname>, soit une chaîne le décrivant :</para>

        <programlisting role="php"><![CDATA[
$username = new Zend_Form_Element_Text('username');

// Passage d'un objet Zend_Validate_*:
$username->addValidator(new Zend_Validate_Alnum());

// Passage du nom du validateur:
$username->addValidator('alnum');
]]></programlisting>

        <para>En utilisant la technique de passage par le nom, vous pouvez ajouter un tableau d'options à passer au
        constructeur de l'objet validateur. Ceci se fait en troisième paramètre :</para>

        <programlisting role="php"><![CDATA[
// Passage d'options au validateur
$username->addValidator('regex', false, array('/^[a-z]/i'));
]]></programlisting>

        <para>(Le second paramètre permet d'indiquer au validateur s'il doit briser la chaîne de validation ou non. Par
        défaut, <code>false</code> : ce n'est donc pas le cas.)</para>

        <para>Vous pouvez avoir besoin de spécifier qu'un élément est requis. Ceci peut être fait en utilisant un
        accesseur ou en passant une option à la création de l'élément. Voici un exemple :</para>

        <programlisting role="php"><![CDATA[
// Cet élément est requis:
$username->setRequired(true);
]]></programlisting>

        <para>Lorsqu'un élément est requis, un validateur "NotEmpty" lui est ajouté, sur le dessus de sa pile de
        validateurs.</para>

        <para>La gestion des filtres est très semblable à celle des validateurs. Voyons comment ajouter un filtre qui
        retourne la donnée en minuscules :</para>

        <programlisting role="php"><![CDATA[
$username->addFilter('StringtoLower');
]]></programlisting>

        <para>Finalement, la configuration complète de l'élément pourra ressembler à cela :</para>

        <programlisting role="php"><![CDATA[
$username->addValidator('alnum')
         ->addValidator('regex', false, array('/^[a-z]/'))
         ->setRequired(true)
         ->addFilter('StringToLower');

// ou, de manière plus compacte:
$username->addValidators(array('alnum',
        array('regex', false, '/^[a-z]/i')
    ))
    ->setRequired(true)
    ->addFilters(array('StringToLower'));
]]></programlisting>

        <para>Aussi simple que cela puisse paraître, cela peut très vite devenir fastidieux de répéter ces opérations
        sur tous les éléments du formulaire. Reprenons le cas (b) d'au dessus : lorsque l'on crée un élément,
        <classname>Zend_Form::addElement()</classname> agit comme une fabrique et on peut lui passer des options de configuration.
        Par exemple, des validateurs ou des filtres. Essayons ceci :</para>

        <programlisting role="php"><![CDATA[
$form->addElement('text', 'username', array(
    'validators' => array(
        'alnum',
        array('regex', false, '/^[a-z]/i')
    ),
    'required' => true,
    'filters'  => array('StringToLower'),
));
]]></programlisting>

        <note>
            <para>Si vous vous apercevez que vous créez des éléments basés sur les mêmes options, étendre
            <classname>Zend_Form_Element</classname> peut devenir une bonne option. Votre nouvelle classe configurera directement
            vos objets.</para>
        </note>
    </sect2>

    <sect2 id="zend.form.quickstart.render">
        <title>Rendre (visuellement) un formulaire</title>

        <para>Rendre un formulaire est très simple. La plupart des éléments nécessitent les aides de vue
        <classname>Zend_View</classname> pour être rendus. Ils ont donc besoin d'un objet de vue. Pour rendre un formulaire,
        appelez sa méthode <code>render()</code> ou faites un <code>echo</code> devant l'objet.</para>

        <programlisting role="php"><![CDATA[
// Appel explicite de render() :
echo $form->render($view);

// Supposant que setView() avec passage d'un objet Zend_View a été appelée avant :
echo $form;
]]></programlisting>

        <para>Par défaut, <classname>Zend_Form</classname> et les <classname>Zend_Form_Element</classname> vont essayer de récupérer l'objet
        de vue depuis l'aide d'action <code>ViewRenderer</code>, ce qui signifie que vous n'aurez pas besoin de
        spécifier un objet de vue manuellement si vous utilisez le système MVC de Zend Framework. Pour rendre un
        formulaire dans une vue MVC, un simple <code>echo</code> suffit :</para>

        <programlisting role="php"><![CDATA[
<?php echo $this->form ?>
]]></programlisting>

        <para>Techniquement, <classname>Zend_Form</classname> utilise des "décorateurs" pour effectuer le rendu visuel. Ces
        décorateurs peuvent remplacer le contenu, ou le placer avant ou après. Ils peuvent aussi introspecter l'élément
        qui leur est passé. Ainsi, vous pouvez chaîner plusieurs décorateurs pour utiliser des effets visuels. Par
        défaut, <classname>Zend_Form_Element</classname> combine quatre décorateurs pour s'afficher :</para>

        <programlisting role="php"><![CDATA[
$element->addDecorators(array(
    'ViewHelper',
    'Errors',
    array('HtmlTag', array('tag' => 'dd')),
    array('Label', array('tag' => 'dt')),
));
]]></programlisting>

        <para>(Où &lt;HELPERNAME&gt; est le nom de l'aide de vue à utiliser, qui varie selon l'élément à rendre.)</para>

        <para>Les décorateurs par défaut (rappelés ci-dessus), produisent le rendu suivant :</para>

        <programlisting role="html"><![CDATA[
<dt><label for="username" class="required">Username</dt>
<dd>
    <input type="text" name="username" value="123-abc" />
    <ul class="errors">
        <li>'123-abc' has not only alphabetic and digit characters</li>
        <li>'123-abc' does not match against pattern '/^[a-z]/i'</li>
    </ul>
</dd>
]]></programlisting>

        <para>(Le formatage peut un peu changer.)</para>

        <para>Vous pouvez changer les décorateurs utilisés par un élément si vous voulez avoir un visuel différent ;
        voyez la section sur les décorateurs pour plus d'informations.</para>

        <para>Le formulaire boucle sur ses éléments et entoure leur rendu d'une balise HTML <code>&lt;form&gt;</code>.
        Cette balise prend en compte la méthode, l'action, et les éventuels attributs passés via
        <code>setAttribs()</code>.</para>

        <para>Les éléments sont bouclés dans l'ordre dans lequel ils sont ajoutés, ou, si votre élément possède un
        attribut "order", celui-ci sera alors utilisé pour gérer sa place dans la pile des éléments :</para>

        <programlisting role="php"><![CDATA[
$element->setOrder(10);
]]></programlisting>

        <para>Ou encore, à la création de l'élément via <code>addElement()</code> :</para>

        <programlisting role="php"><![CDATA[
$form->addElement('text', 'username', array('order' => 10));
]]></programlisting>
    </sect2>

    <sect2 id="zend.form.quickstart.validate">
        <title>Vérifier qu'un formulaire est valide</title>

        <para>Après l'envoi du formulaire, il faut vérifier les valeurs que contiennent ses éléments. Tous les
        validateurs de chaque élément sont donc interrogés. Si l'élément était marqué comme requis et que l'élément ne
        reçoit aucune donnée, les validateurs suivants agiront sur une valeur <code>null</code>.</para>

        <para>D'où proviennent les données ? Vous pouvez utiliser <code>$_POST</code> ou <code>$_GET</code>, ou
        n'importe quelle source de données (service Web par exemple) :</para>

        <programlisting role="php"><![CDATA[
if ($form->isValid($_POST)) {
    // succès!
} else {
    // echec!
}
]]></programlisting>

        <para>Avec des requêtes AJAX, il arrive que l'on ait besoin de ne valider qu'un élément, ou un groupe d'élément.
        <code>isValidPartial()</code> validera un formulaire partiel. Contrairement à <code>isValid()</code>, si une
        valeur est absente, les autres validateurs ne seront pas interrogés:</para>

        <programlisting role="php"><![CDATA[
if ($form->isValidPartial($_POST)) {
    // Tous les éléments présents dans $_POST ont passé la validation
} else {
    // un ou plusieurs éléments présent dans $_POST ont échoué
}
]]></programlisting>

        <para>La méthode <code>processAjax()</code> peut aussi être utilisée pour valider partiellement un formulaire.
        Contrairement à <code>isValidPartial()</code>, cette méthode retournera les messages d'erreur de validation au
        format JSON.</para>

        <para>En supposant que les validateurs aient passé, vous pouvez dès lors récupérer les valeurs filtrées depuis
        les éléments :</para>

        <programlisting role="php"><![CDATA[
$values = $form->getValues();
]]></programlisting>

        <para>Si vous désirez les valeurs non filtrées, utilisez :</para>

        <programlisting role="php"><![CDATA[
$unfiltered = $form->getUnfilteredValues();
]]></programlisting>
    </sect2>

    <sect2 id="zend.form.quickstart.errorstatus">
        <title>Les statuts d'erreur</title>

        <para>Votre formulaire a échoué à l'envoi ? Dans la plupart des cas, vous voudrez rendre à nouveau le
        formulaire, mais avec les messages d'erreur affichés :</para>

        <programlisting role="php"><![CDATA[
if (!$form->isValid($_POST)) {
    echo $form;

    // ou en assignant un objet de vue (cas non-MVC typiquement)
    $this->view->form = $form;
    return $this->render('form');
}
]]></programlisting>

        <para>Si vous voulez inspecter les erreurs, 2 méthodes s'offrent à vous. <code>getErrors()</code> retourne un
        tableau associatif avec en clé le nom de l'élément et en valeur un tableau de codes d'erreurs.
        <code>getMessages()</code> retourne un tableau associatif avec en clé le nom de l'élément, et en valeur un
        tableau de messages d'erreurs (code=&gt;message). Tout élément ne comportant pas d'erreur ne sera pas inclus
        dans le tableau.</para>
    </sect2>

    <sect2 id="zend.form.quickstart.puttingtogether">
        <title>Assembler le tout ensemble</title>

        <para>Créons un formulaire de d'authentification. Il aura besoin d'élément représentant :</para>

        <itemizedlist>
            <listitem>
                <para>un nom</para>
            </listitem>

            <listitem>
                <para>un mot de passe</para>
            </listitem>

            <listitem>
                <para>un bouton d'envoi</para>
            </listitem>
        </itemizedlist>

        <para>Pour notre exemple, imaginons un nom composé de caractères alphanumériques uniquement. Le nom commencera
        par une lettre, et devra faire entre 6 et 20 caractères de long, qui seront normalisés en lettres minuscules.
        Les mots de passe feront 6 caractères minimum.</para>

        <para>Nous allons utiliser la puissance de <classname>Zend_Form</classname> pour configurer le formulaire et effectuer le
        rendu :</para>

        <programlisting role="php"><![CDATA[
$form = new Zend_Form();
$form->setAction('/user/login')
     ->setMethod('post');

// élément nom :
$username = $form->createElement('text', 'username');
$username->addValidator('alnum')
         ->addValidator('regex', false, array('/^[a-z]+/'))
         ->addValidator('stringLength', false, array(6, 20))
         ->setRequired(true)
         ->addFilter('StringToLower');

// élément mot de passe :
$password = $form->createElement('password', 'password');
$password->addValidator('StringLength', false, array(6))
         ->setRequired(true);

// Ajout des éléments au formulaire
$form->addElement($username)
     ->addElement($password)
     // addElement() agit comme une fabrique qui crée un bouton 'Login'
     ->addElement('submit', 'login', array('label' => 'Login'));
]]></programlisting>

        <para>Il nous faut à présent un contrôleur pour gérer tout cela:</para>

        <programlisting role="php"><![CDATA[
class UserController extends Zend_Controller_Action
{
    public function getForm()
    {
        // Créer le formulaire comme décrit ci-dessus
        return $form;
    }

    public function indexAction()
    {
        // rend user/form.phtml
        $this->view->form = $this->getForm();
        $this->render('form');
    }

    public function loginAction()
    {
        if (!$this->getRequest()->isPost()) {
            return $this->_forward('index');
        }
        $form = $this->getForm();
        if (!$form->isValid($_POST)) {
            // Validation en echec
            $this->view->form = $form;
            return $this->render('form');
        }

        $values = $form->getValues();
        // les valeurs sont récupérées
    }
}
]]></programlisting>

        <para>Le script de vue pour afficher le formulaire :</para>

        <programlisting role="php"><![CDATA[
<h2>Identifiez vous:</h2>
<?= $this->form ?>
]]></programlisting>

        <para>Comme vous le voyez sur le code du contrôleur, il reste du travail à faire une fois le formulaire validé.
        Par exemple, utiliser <classname>Zend_Auth</classname> pour déclencher un processus d'identification.</para>
    </sect2>

    <sect2 id="zend.form.quickstart.config">
        <title>Utiliser un objet <classname>Zend_Config</classname></title>

        <para>Toutes les classes du composant <classname>Zend_Form</classname> sont configurables au moyen d'un objet
        <classname>Zend_Config</classname> ; vous pouvez passer un objet <classname>Zend_Config</classname> au constructeur ou via la
        méthode <code>setConfig()</code>. Voyons comment créer le formulaire ci-dessus, au moyen d'un fichier INI. Tout
        d'abord, nous nous baserons sur une section "developement", et nos instructions devront être imbriquées afin de
        refléter la configuration. Ensuite nous utiliserons un espace de nom "user" correspondant au contrôleur, puis un
        "login" concernant le formulaire (ceci permet de ranger les données correctement dans le fichier INI) :</para>

        <programlisting role="ini"><![CDATA[
[development]
; informations générales du formulaire
user.login.action = "/user/login"
user.login.method = "post"

; element username
user.login.elements.username.type = "text"
user.login.elements.username.options.validators.alnum.validator = "alnum"
user.login.elements.username.options.validators.regex.validator = "regex"
user.login.elements.username.options.validators.regex.options.pattern = "/^[a-z]/i"
user.login.elements.username.options.validators.strlen.validator = "StringLength"
user.login.elements.username.options.validators.strlen.options.min = "6"
user.login.elements.username.options.validators.strlen.options.max = "20"
user.login.elements.username.options.required = true
user.login.elements.username.options.filters.lower.filter = "StringToLower"

; element password
user.login.elements.password.type = "password"
user.login.elements.password.options.validators.strlen.validator = "StringLength"
user.login.elements.password.options.validators.strlen.options.min = "6"
user.login.elements.password.options.required = true

; element submit
user.login.elements.submit.type = "submit"
]]></programlisting>

        <para>Le constructeur du formulaire ressemblera alors à ceci :</para>

        <programlisting role="php"><![CDATA[
$config = new Zend_Config_Ini($configFile, 'development');
$form   = new Zend_Form($config->user->login);
]]></programlisting>

        <para>et tout le formulaire sera défini.</para>
    </sect2>

    <sect2 id="zend.form.quickstart.conclusion">
        <title>Conclusion</title>

        <para>Vous êtes maintenant capable de libérer la puissance de <classname>Zend_Form</classname>. Continuez de lire les
        chapitres suivants pour utiliser ce composant en profondeur !</para>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->