Introduction

Il faut voir Zend_Form comme un conteneur, il va contenir des éléments de formulaire que nous pourrons ensuite configurer selon nos besoins. Ces éléments étendent la classe non-abstraite Zend_Form_Element implémentant Zend_Validate_Interface, tout ça peut paraître un peu barbant mais devient très vite intéressant si l'on veut ajouter de nouveaux éléments « à la sauce maison ».

Je ne vous fais pas la liste, mais la quasi-totalisé des éléments de formulaire HTML sont présent dans la librairie.

Pour ceux que ça intéresse, il existe la même liste pour les éléments Dojo (Zend_Dojo_Form_Element_Dijit)! Mais ne vous attendez pas à plus, les éléments un peu plus alambiqués n'y sont pas présents, je ne vous parle même pas de Dojox... retroussage de manche obligatoire !

Construction

Nous allons voir l'exemple d'un formulaire d'authentification, il comportera un champs « login », un champs « password » et un bouton de validation.
Il est tout à fait possible de créer son formulaire directement dans un contrôleur avec $myForm = new Zend_Form('name'); mais je le déconseille fortement car réutilisabilité zero et puis c'est pas très MVC tout ça!

Nous allons donc créer une classe qui étendra Zend_Form et nous redéfinirons son constructeur sans oublier d'y appeler le constructeur parent.

class Form_Login extends Zend_Form {
    public function __construct($options = null) {
       parent::__construct($options);
 
       $this->setName('formAuth');
       $this->setMethod('POST');
  }
}

Deux méthodes importantes pour configurer Zend_Form:

  • setName('name') pour donner un nom à notre formulaire
  • setMethod('GET || POST') pour préciser la méthode d'envoi, (GET par défaut)

D'autres méthodes sont à notre disposition mais je ne les utiliserais pas ici, par exemple:

  • setTranslator() pour la gestion multilangue
  • setLegend() pour ajouter... une légende!
  • AddSubForm() pour créer des formulaires multi-page
  • ...

Plus de détails sur Zend_Form.

Ajoutons nos éléments:

...
 	// login element
            $login = $this->createElement('text', 'userLogin');
            $login->setLabel('Utilisateur:')
                      ->setRequired(true);
            $this->addElement($login);
 
            // password element
            $password = $this->createElement('password', 'userPassword');
            $password->setLabel('Mot de passe:')
                             ->setRequired(true);
            $this->addElement($password);
 
            // submit element<br>            $submit = $this->createElement('submit', 'loginSubmit');
            $submit->setLabel('Connexion');
            $this->addElement($submit);
	...

Pour créer un élément il y a la méthode fabrique createElement($type, $name) , elle remplace si l'on veut l'instanciation new Zend_Form_Element_Type($name). Elle simplifie l'écriture mais surtout la génération automatique des formulaires en passant par exemple par un fichier INI ou XML.

Une fois un élément créé, il faut le configurer.

Comme pour Zend_Form, Zend_Form_Element est pourvu d'une bonne liste d'accesseurs, les plus utilisés étant sans doute :

  • setLabel() pour ajouter un label
  • setAttrib() pour ajouter un attribut
  • setValue() pour donner une valeur
  • addValidator() pour ajouter un validateur
  • addFilter() pour ajouter un filtre
Filtres et validateurs

La validation est une étape importante dans un formulaire, bien choisir ses filtres et ses validateurs c'est l'assurance d'opérer des traitements avec des valeurs fiables réduisant donc les risques de bugs ou de failles de sécurité.

Pour cela il existe Zend_Filter et Zend_Validate, des composants utilisables partout où l'on en a besoin donc aussi dans les formulaire!

Filtrage des données

Zend_Filter va prendre en entrée des données brutes et va leurs appliquer un certain nombre de transformations et formatages. Ainsi les variables que vous récupérez en sortie seront toujours de type et de format connu.

On trouvera par exemple les filtres:

  • Zend_Filter_Int
  • Zend_Filter_Alnum
  • Zend_Filter_HtmlEntities
  • Zend_Filter_StringToLower
  • Zend_Filter_PregReplace
  • ...

Plus de détails sur les filtres.

Son utilisation standard peut se faire sous deux formes :

  • avec l'appel de la méthode filter() :

$myFilter = new Zend_Filter_Type(); $result = $myFilter->filter($value);

  • en utilisant la méthode statique :

$result = Zend_Filter::staticFilter($value, 'type');

Pour les éléments d'un formulaire nous utiliserons la méthode addFilter($type,$options); avec $options en facultatif car il n'y a pas forcément besoins d'options! :)

Prenons l'exemple du champ « login », si nous voulons en sortie que des caractères alpha-numériques et le tout en minuscule nous écrirons ceci:

  • première solution avec chaînage:
$login = $this->createElement('text', 'userLogin');
            $login->setLabel('Utilisateur:')
	          ->addFilter('Alnum')
	          ->addFilter('StringToLower')
  • deuxième solution (avec array $options) :
$login = $this->createElement('text', 'userLogin',
				array('label'=>'Utilisateur',
					'filter'=>'Alnum',
					'filter'=>'StringToLower'
				        )
);
  • troisième solution avec Zend_Filter :
$filter = new Zend_Filter();
$filter->addFilter(new Zend_Filter_Alnum)
	->addFilter(new Zend_Filter_StringToLower);
 
 $login = $this->createElement('text', 'userLogin');
            $login->setLabel('Utilisateur:')
	          ->addFilter($filter);

Bon, il y a 5 ou 6 possibilités pour déclarer tout ça, je vous en donne un aperçu mais n'y voyez rien d'exhaustif.
Vous remarquerez la possibilité de chaînage qui est assez pratique et propre je trouve.

Validation des données

Zend_Validate est un composant pas très bavard, il ne sait dire que « oui » ou « non », mais il est parfait dans son rôle !

On va donc lui passer des valeurs, si elles correspondent à nos attentes elles seront validées sinon Zend_Validate nous renverra les messages d'erreurs à afficher à l'utilisateur.

Comme pour les filtres, une bonne liste de validateurs est mise à notre disposition, entre autre :

  • Zend_Validate_Date
  • Zend_Validate_NotEmpty
  • Zend_Validate_EmailAddress
  • Zend_Validate_Regex
  • Zend_Validate_Alnum
  • ...

plus de détails sur les validateurs.

Son utilisation standard passe par la méthode isValid() :

$validator = new Zend_Validate_Type();
 
if($validate->isValid($value)){
	//code
}else{
	$messages = $validator->getMessages();
}

Après validation, un champ mal renseigné va afficher automatiquement son message d'erreur (par défaut en anglais).

Pour modifier ce message rien de plus simple:

$element->addErrorMessage($message) //ajoute un message à la pile
//OU
$element->setErrorMessages(array $messages) //remplace les messages existant par les nouveaux

Plus de détails sur les messages d'erreurs

Reprenons l'exemple du champ « login », nous voulons qu'il soit obligatoirement rempli donc nous utiliserons Zend_Validate_NotEmpty.

  • Première solution avec la méthode setRequired() qui utilise Zend_Validate_NotEmpty
$login = $this->createElement('text', 'userLogin');
            $login->setLabel('Utilisateur:')
                   ->setRequired(true);
  • Deuxième solution avec la méthode addValidator():
$login = $this->createElement('text', 'userLogin');
            $login->setLabel('Utilisateur :')
                     ->addValidator('NotEmpty');

Comme pour les filtres, je ne vous ferais pas la liste de toutes les manières possibles.

Pour un formulaire « standard », la méthode isValid() sera appelée au niveau de Zend_Form et non plus des éléments, c'est donc le formulaire qui va vérifier récursivement la validité de ses champs.

$form = new My_Form();
if($form->isValid($formValues){}

Il faut passer les valeurs retournées par le formulaire à la méthode isValid() de notre My_Form, soit vous utilisez les $_REQUEST (get, post, etc) soit vous pouvez demander au formulaire de retourner ses valeurs avec les méthodes :

$form->getValues();
$form->getValue($name);

La validation au niveau du formulaire aura pour effet de tester la validité des valeurs de tous les éléments du formulaire (logique !). Un résultat non-validé ou une valeur manquante empêchera la validation du formulaire.

Pour un résultat non-valide, c'est compréhensible mais pour une valeur manquante ça peut devenir gênant dans certaines circonstances... Pour remédier à cela il est possible d'utiliser la méthode isValidPartial() qui ne testera que la validité des éléments correspondants aux valeurs passées en paramètre. Ainsi vous pouvez par exemple valider des valeurs à des moments différents de l'exécution.

Il est aussi possible de récupérer juste les valeurs valide (ça peut être pratique !)

$validValues = $form->setValidValues($formValues);

Remarque:
Quand vous utilisez des variables type $_POST ou $_GET dans un contrôleur, n'hésitez surtout pas à utiliser les accesseurs fournis!

$this->_request->getParams();
$this->_request->getParam($name);
$this->_request->isPost();
$this->_request->isGet();
$this->_request->getPost($name);
$this->_getParam($name);
...

Le $this->_request pouvant être remplacé par son accesseur $this->getRequest();

Utilisation

Voyons maintenant l'utilisation standard de notre formulaire dans un contrôleur.

class MyController extends Zend_Controller_Action{
	public function indexAction(){
 
		$form = new Form_Login();
		$this->view->form = $form;
 
		$request = $this->getRequest();
 
		if($request->isPost() && $form->isValid($request->getParams()){
			//code
		}
	}
}
Conclusion

Nous avons vu le principe de fonctionnement du composant Zend_Form.
Un autre article sera nécessaire pour compléter son utilisation de manière un peu plus avancé mais les bases sont d'ores et déjà à votre disposition, alors à vos clavier !