Zend_Form : personnaliser les messages des validateurs

Exemple de message d'erreur

Quand une erreur survient, il faut afficher un message d'erreur le plus explicite possible. Avec Zend_Form, les messages d'erreur sont issus des validateurs.

Traduire les messages

Les messages sont par défaut en anglais. Il faut donc en proposer une version traduite.Zend_Form gère la traduction automatique, il suffit de créer une entrée Zend_Translate dans le registre :

<?php
// Création d'un objet locale qu'on place dans le registre
$locale = new Zend_Locale('fr_FR');
Zend_Registry::set('Zend_Locale'$locale);

// Création d'un objet Zend_Translate utilisant l'adaptateur GetText
$translate = new Zend_Translate('gettext'APPLICATION_PATH '/languages/fr/zf.mo');

// On définit la locale que Zend_Translate doit utiliser
$translate->setLocale($locale);

// On place l'objet dans le registre avec la clé Zend_Translate pour que Zend_Form 
// le trouve et l'utilise
Zend_Registry::set('Zend_Translate'$translate);
?>

On obtient ainsi un message traduit :

Exemple de message d'erreur

Messages adaptés au contexte

C'est mieux, mais il faut idéalement un message correspondant au contexte. Pour cela, il faut utiliser la méthode setMessage du validateur:

<?php
// On crée le validateur
$noRecordExistsVal = new Zend_Validate_Db_NoRecordExists(
    
'estimates',
    
'num'
);

// On définit le message associé à la constante ERROR_RECORD_FOUND
$noRecordExistsVal->setMessage(
    
'Ce numéro est déjà utilisé'
    
Zend_Validate_Db_Abstract::ERROR_RECORD_FOUND
);

// On ajoute l'élément au formulaire
$this->addElement(
    
'text',
    
'num',
    array(
        
'label' => 'Numéro : ',
        
'required' => true,
        
'validators' => array($noRecordExistsVal)
    )
);
?>

Vous pouvez obtenir le détail des différentes constantes en examinant le code source des composants Zend_Validate.

Problème avec l'option required

Si le champ doit être obligatoirement rempli, vous allez mettre l'option required à true. Zend_Form_Element va alors insérer automatiquement un validateur NotEmpty avant de procéder à la validation. Comme il est inséré au niveau de la méthode isValid, vous ne pouvez pas le récupérer avec la méthode getValidator après la création de l'objet.

La solution, c'est de créer explicitement le validateur NotEmpty :

<?php
$notEmptyVal 
= new Zend_Validate_NotEmpty();
$notEmptyVal->setMessage('Obligatoire'Zend_Validate_NotEmpty::IS_EMPTY);

// On ajoute l'élément au formulaire
$this->addElement(
    
'text',
    
'num',
    array(
        
'label' => 'Numéro : ',
        
'required' => true,
        
'validators' => array($notEmptyVal$noRecordExistsVal)
    )
);
?>

Obtenir la liste des messages à traduire

Vous pouvez récupérer les messages à traduire avec la méthode getMessageTemplates. Cela vous permet de définir un message d'erreur générique pour tous les types d'erreurs qui peuvent se produire. Exemple avec Zend_Validate_EmailAddress.

<?php
// Création du validateur
$emailAddressVal = new Zend_Validate_EmailAddress();

// Récupération des messages
$msgTemplates $emailAddressVal->getMessageTemplates();

// On remplace les différents messages d'erreur par un message simple
foreach($msgTemplates as $key => $msg) {
    
$emailAddressVal->setMessage('Cette adresse E-mail n\'est pas valide'$key);
}
?>

Attention cependant, certains validateurs comme Zend_Validate_Hostname peuvent renvoyer plusieurs messages.

Variables dans les messages

Les messages peuvent contenir des variables qui seront automatiquement remplacées lors de la récupération du message. La variable %value%, toujours disponible, correspond à la valeur passée au validateur. Certains validateurs proposent des variables supplémentaires, par exemple %min% pour Zend_Validate_GreaterThan. Vous pouvez récupérer la liste des variables additionnelles avec la méthode getMessageVariables.

Commentaires

Bonjour il est noté "il suffit de créer une entrée Zend_Translate dans le registre":
où se trouve le registre ?

Le registre, c'est Zend_Registry. C'est une classe dotée de méthodes statiques qui permettent de placer et de récupérer des objets dans un espace accessible de façon globale. Une sorte de dictionnaire en quelque sorte qui se substitue aux variables globales.
Si tu veux en savoir plus sur ce motif de conception : http://www.phppatterns.com/docs/design/the_registry


$translate = new Zend_Translate(...);
Zend_Registry::set('Zend_Translate', $translate);

Bonjour Maxence,

Suite à quelques essais sur la personnalisation des messages d'erreurs, je n'arrive pas à récupérer ceux-ci convenablement traduits avec substitution des variables.

Je n'arrive à récupérer que les messages par défaut convenablement traduits... ce qui n'est pas si mal.
Voici ma manière de faire, dans mon IdentificationController, section validation echouée du formulaire:

$translate = Zend_Registry::get('Zend_Translate');

//username messages
$username_messages = $form->getElement('username')->getMessages();
$this->view->username_label = ''.$translate->translate("identification_labelUsername").'';
$this->view->username_messages = '

  • '.implode('
  • ' ,$username_messages).'

';
//password messages
$password_messages = $form->getElement('password')->getMessages();
$this->view->password_label = ''.$translate->translate("identification_labelPassword").'';
$this->view->password_messages = '

  • '.implode('
  • ' ,$password_messages).'

';

Et dans la vue associée à mon formulaire, j'ai ceci:

<?php echo $this->translate("identification_title"); ?>
<?php echo $this->message; ?>
<?php echo $this->username_label.' '.$this->username_messages; ?>
<?php echo $this->password_label.' '.$this->password_messages; ?>
<?php echo $this->form; ?>

Pourrais-tu préciser comment tu récupères les différents messages d'erreurs personnalisés lors de la validation de ton formulaire ? Merci.

Te souhaitant une excellente journée.
Thierry.

En fait, ayant affecté une instance de mon objet responsable des traductions sur mon formulaire, il semblerait que les messages personnalisés des validateurs soient tout à fait ignorés au profit des traductions :P

Suite à la consultation de la documentation, les méthodes de l'api ne sont pas plus fonctionnelles. Par exemple, la méthode suivante:

$val->setErrorMessages(array($key=>$value));
//$key constante de classe du validateur que l'on veut personnaliser
//$val message personnalisé que l'on souhaite affecter à cette clef du validateur

Permet de définir des messages d'erreurs qui ne sont pas traduits par le formulaire lors de la validation... même en utilisant la méthode

$val->setTranslator($translator)

Bon, je vais bien finir par trouver une manière de faire fonctionnelle.

Ajouter un commentaire