Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 26-11-2012 20:36:38

neilime
Membre
Date d'inscription: 28-04-2009
Messages: 42

[Résolu]Le validateur Zend\Validator\NotEmpty ne fonctionne pas

Bonjour,

J'essaye de définir des validateurs pour un formulaire

Le test que je fait est un formulaire avec un champs qui doit contenir une adresse email.
J'ai d'abord commencé par définir le validateur EmailAddress et l'attribut "require" : true.
Lorsque je valide ce formulaire avec une adresse incorrecte le formulaire déclenche correctement une erreur.
Cependant si je valide le formulaire vide, il ne détecte pas d'erreur.

J'ai donc décidé d'ajouter le validateur NotEmpty, mais rien n'y fait, le formulaire se valide malgré le fait que le champ est vide.

Je ne comprends pas l'erreur que j'ai faite, car mon test est on ne le peu plus simpliste.

Voilà le code (un résumé) auteur de mes  tourments :

Code:

[lang=php]
namespace TestForm;
class TestForm extends \Zend\Form\Form{
    /**
     * Constructor
     */
    public function __construct(){
        parent::__construct('test');
        $this->setAttribute('method', 'post')
        ->add(array(
            'name' => 'email',
            'attributes' => array(
                'type' => 'text'
            )
        ))
        ->getInputFilter()->add(array(
            'name' => 'email',
            'required' => true,
            'validators' => array(
                array('name' => 'NotEmpty','option' => array('type'=>\Zend\Validator\NotEmpty::STRING)),
                array('name' => 'EmailAddress')
            )
        ));
    }
}

//Controller

public function testAction{
    //...
    
    $oForm = new \TestForm\TestForm();
    $oForm->prepare();
    
    //Test de valeurs vides
    $oForm->setData(array(
        'email' => ''
    ));
    
    //Il ne devrait pas être valide car email est vide...
    if($oForm->isValid()){
        //Et bien il passe quand même le test
        error_log('valid');
    }
    else error_log('not valid');
    
    //Test d'une adresse email incorrecte
    $oForm->setData(array(
        'email' => 'erreur'
    ));
    
    //Il ne devrait pas être valide car email est incorrect...
    if($oForm->isValid()){        
        error_log('valid');
    }
    //Il ne passe logiquement pas le test
    else error_log('not valid');
    
    
    
    //...
}

Merci d'avance pour vos éclaircissements.

Dernière modification par neilime (27-11-2012 17:18:20)

Hors ligne

 

#2 26-11-2012 22:41:32

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: [Résolu]Le validateur Zend\Validator\NotEmpty ne fonctionne pas

Salut, déjà ce que je peux te conseiller c'est d'aller lire la doc parce que la méthode que tu utilises ne correspond à rien de la doc. Il existe une interface pour ajouter l'input filter soit on le fait via une factory.

Ensuite si tu as l'attribut required ça signifie qu'il y a forcément la validation NotEmpty puisqu'on demande à ce que le champ soit rempli.

Là ce qu'il se passe c'est que ton input filter n'est pas pris en compte parce que tu fais pas ce qu'il faut.

Hors ligne

 

#3 26-11-2012 23:22:57

neilime
Membre
Date d'inscription: 28-04-2009
Messages: 42

Re: [Résolu]Le validateur Zend\Validator\NotEmpty ne fonctionne pas

Je pense qu'il y a méprise, car si on "lit la doc" de la méthode add de la classe InputFilter :

Code:

[lang=php]
    /**
     * Add an input to the input filter
     *
     * @param  array|Traversable|InputInterface|InputFilterInterface $input
     * @param  null|string $name
     * @return InputFilter
     */
    public function add($input, $name = null)
    {
        if (is_array($input)
            || ($input instanceof Traversable && !$input instanceof InputFilterInterface)
        ) {
            $factory = $this->getFactory();
            $input = $factory->createInput($input);
        }
        return parent::add($input, $name);
    }

Il est tout a fait possible de donner en paramètre un array, c'est la fonction qui se charge de créer l'inputFilter via la factory.

En ce qui concerne cette remarque :

Ensuite si tu as l'attribut required ça signifie qu'il y a forcément la validation NotEmpty puisqu'on demande à ce que le champ soit rempli.

Elle corrobore exactement avec la problématique que je soulève : que ce soit avec un require, ou un validator NotEmpty, il m'est impossible de forcer une valeur non vide dans le champs du formulaire.

Enfin l'input filter est bien pris en compte car il valide bien que l'adresse email est correcte lorsque je passe une valeur au formulaire.

Hors ligne

 

#4 27-11-2012 10:04:17

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: [Résolu]Le validateur Zend\Validator\NotEmpty ne fonctionne pas

En fait je parlais plutôt du fait d'ajouter le input filter directement dans le constructeur du formulaire c'est pas comme ça que c'est préconisé dans la documentation officielle. Ca fonctionne peut être mais je trouve pas ça très propre.

Il y a deux façon de faire, la première c'est d'utiliser une interface je me souviens plus du nom mais ça doit être un truc du genre (input proviter interface) qui nous oblige à implémenter une méthode getInputFilter() qui elle va contenir les différents add via un array et donc la factory; soit en le faisait toi même dans la factory ce que je fais mais il faut privilégier l'interface.

Dans le constructeur de ton formulaire :

Code:

$this->add(
            array(
                'name' => 'mail',
                'type' => 'Zend\Form\Element\Email',
                'options' => array(
                    'label' => 'Adresse mail :',
                ),
                'attributes' => array(
                    'required' => 'required',
                    'class' => 'input-medium',
                )
            )
        );[lang=php]

Dans le constructeur de ta classe input filter

Code:

[lang=php]
$this->add(array(
            'name' => 'mail',
            'required' => true,
            'filters' => array(array('name' => 'StringTrim')),
            'validators' => array(
                array(
                    'name' => 'EmailAddress'
                ),
                $this->emailValidator // Validator custom lié à doctrine pour empêcher les doublons de mail
            ),
        ));

Dans mon Module.php

Code:

[lang=php]
public function getServiceConfig() {
        return array(
            'factories' => array(
                'Application\Form\MyForm' => function ($sm) {
                    $form = new MyForm();
                    $form->setInputFilter(new MyFilter());
                    return $form;
                },
         }
}

Et chez moi ça ça fonctionne.

Hors ligne

 

#5 27-11-2012 11:38:11

neilime
Membre
Date d'inscription: 28-04-2009
Messages: 42

Re: [Résolu]Le validateur Zend\Validator\NotEmpty ne fonctionne pas

Effectivement, ta méthode marche très bien, elle est similaire à celle du user guide d’ailleurs.
Cependant je voulais spécifier des validateurs par défaut (obligatoires) directement lors de la construction de mon formulaire.

J'ai donc mis le nez dans le code et j'ai compris le "bug" qui faisait que la directive "required" n'était pas prise en compte :

Lorsque l'on appelle la méthode \Zend\Form\Form->getInputFilter(), un \Zend\InputFilter\InputFilter par défaut est crée s'il n'y a pas un de définit . Cet InputFilter crée pour chaque champ du formulaire un \Zend\InputFilter\Input avec les directives "required" : false et AllowEmpty = true;

Lorsque l'on ajoute via la méthode Zend\InputFilter\InputFilter->add, on crée un nouveau \Zend\InputFilter\Input que l'on merge avec \Zend\InputFilter\Input déjà créé (par défaut).


Et c'est la que se pose le problème car la méthode  \Zend\InputFilter\Input->merge utilise les directives required et AllowEmpty (entre autre) du  \Zend\InputFilter\Input par défaut et donc : "required" : false et AllowEmpty = true;

Ce qui oblige à faire :

Code:

[lang=php]
namespace TestForm;
class TestForm extends \Zend\Form\Form{
    /**
     * Constructor
     */
    public function __construct(){
        parent::__construct('test');
        $this->setAttribute('method', 'post')
        ->add(array(
            'name' => 'email',
            'attributes' => array(
                'type' => 'text'
            )
        ))
        ->getInputFilter()->add(array(
            'name' => 'email',
            'required' => true,
            'validators' => array(
                array('name' => 'NotEmpty','option' => array('type'=>\Zend\Validator\NotEmpty::STRING)),
                array('name' => 'EmailAddress')
            )
        ))
        //Force Required à true & AllowEmpty à false
        ->get('email')->setRequired(true)->setAllowEmpty(false);
    }
}

Hors ligne

 

#6 27-11-2012 13:55:26

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: [Résolu]Le validateur Zend\Validator\NotEmpty ne fonctionne pas

Tu peux le faire directement dans le form via l'interface dont je t'ai parlé comme tu as tout dans la même classe et ça fonctionne très bien là ça ne fait pas propre et il y a de la redondance de code qui n'est pas nécessaire.

Hors ligne

 

#7 27-11-2012 14:16:46

neilime
Membre
Date d'inscription: 28-04-2009
Messages: 42

Re: [Résolu]Le validateur Zend\Validator\NotEmpty ne fonctionne pas

tu peux le faire directement dans le form via l'interface

Je ne comprend pas l'utilité de créer un InputFilter perso alors que la méthode getInputFilter le crée d'elle même.

Ensuite je ne comprend pas l'utilité d'utiliser une interface car la méthode add de la classe InputFilter crée l'input avec une factory à partir d'un array.

là ça ne fait pas propre et il y a de la redondance de code qui n'est pas nécessaire.

Cela "ne fait pas propre" car il y a une erreur de code dans la méthode add de la classe InputFilter qui ne gère pas correctement les attribut require et AllowEmpty et donc m'oblige à le forcer après création de l'input.

Je ne vois pas la redondance de code (en omettant le fait que je sois obliger de forcer les require et allowEmpty car la fonction add ne le gère pas correctement)

Je juge intéressant de définir les validateurs "obligatoires" dans le formulaire, puis ajouter d'autre validateurs dans les services en fonction du contexte.

Je pourrais très bien avoir un service 'test1' qui renvoi le formulaire tel quel et un service 'test2' qui renvoi le formulaire en ajoutant le validateur StringLength au champs "email" par exemple. Mais dans tout les cas le champ email devra être validé par le validateur EmailAddress.

Si je devais implémenté tous les validateurs pour chaque service, là il y aurai redondance de code.

Hors ligne

 

#8 27-11-2012 15:29:50

bakura
Administrateur
Date d'inscription: 30-01-2010
Messages: 353

Re: [Résolu]Le validateur Zend\Validator\NotEmpty ne fonctionne pas

Je n'ai pas lu toute la conversation, mais si tu estimes qu'il y a un bug dans la classe InputFilter, n'hésite pas à soumettre à fix sur GitHub smile.

Hors ligne

 

#9 27-11-2012 15:33:48

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: [Résolu]Le validateur Zend\Validator\NotEmpty ne fonctionne pas

En fait c'est juste que quand tu implémentes l'interface, la factory du form va automatiquement créer le input filter qui est défini dans la méthode à implémenter et celle-ci fonctionne bien.

En fait si tu utilises correctement les formulaires normalement ils sont censé faire uniquement des regroupements de filedset qui eux sont une représentation de tes models via les filter/validators.

J'ai du mal à comprendre dans quel cas en suivant ce modèle tu vas avoir à un moment donné devoir obliger l'utilisateur à saisir un champ qui doit faire tel ou tel longueur ou répondre à tel ou tel critère alors que le fieldset représente un de tes modèles et donc qu'il impose les mêmes contraintes. Si ton modèles ne peux pas prendre de champ nom à null si tu autorises le formulaire à le faire tu vas avoir un problème au niveau des données.

Enfin c'est pas bien grave le principal c'est que ça fonctionne wink

Hors ligne

 

#10 27-11-2012 15:56:41

neilime
Membre
Date d'inscription: 28-04-2009
Messages: 42

Re: [Résolu]Le validateur Zend\Validator\NotEmpty ne fonctionne pas

Code:

[lang=php]
public function add($input, $name = null)
    {
        //...
        if (isset($this->inputs[$name]) && $this->inputs[$name] instanceof InputInterface) {
            // The element already exists, so merge the config. Please note that the order is important (already existing
            // input is merged with the parameter given)
            $input->merge($this->inputs[$name]);
        }

        $this->inputs[$name] = $input;
        return $this;
    }

Alors, je suis celui qui a écrit cette partie du framework. De mémoire, j'ai mergé APRES pour la raison suivante : lorsque tu ajoutes des éléments ayant déjà des règles de validation dans un formulaire (Date, Number...), pour pouvoir surcharger les validateurs existants ajoutés par ces éléments), il est nécessaire que le merge se fasse après.

Je ne me souviens plus exactement pourquoi, mais de mémoire j'avais fait ainsi pour régler cette problématique.

Dans ZF 3, je pense que j'apporterai des modifications à ce composant pour qui'l ne travaille qu'avec des PriorityQueue, pour ne plus avoir de faire de merge et juste se baser sur les priorités des validateurs.

Hors ligne

 

#11 27-11-2012 16:31:44

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: [Résolu]Le validateur Zend\Validator\NotEmpty ne fonctionne pas

neilime a écrit:

Malheureusement ça ne fonctionne pas vraiment, et c'est tout le but de mon message, car l'attribut "require" n'est pas (selon moi) pris en compte correctement. Je dois le forcer manuellement.

D'accord mais ce cas je ne vois pas ce que l'on peut faire pour toi. Tu peux tout à fait passer par l'interface comme je te le disais tout à l'heure et dans le service qui récupère l'instance de ton formulaire ajouter les validateurs qu'il te manque en fonction de ton contexte. Mise à part ça je ne vois pas bien comment t'aider plus sad

Hors ligne

 

#12 27-11-2012 17:10:50

bakura
Administrateur
Date d'inscription: 30-01-2010
Messages: 353

Re: [Résolu]Le validateur Zend\Validator\NotEmpty ne fonctionne pas

Code:

[lang=php]
public function add($input, $name = null)
    {
        //...
        if (isset($this->inputs[$name]) && $this->inputs[$name] instanceof InputInterface) {
            // The element already exists, so merge the config. Please note that the order is important (already existing
            // input is merged with the parameter given)
            $input->merge($this->inputs[$name]);
        }

        $this->inputs[$name] = $input;
        return $this;
    }

Alors, je suis celui qui a écrit cette partie du framework. De mémoire, j'ai mergé APRES pour la raison suivante : lorsque tu ajoutes des éléments ayant déjà des règles de validation dans un formulaire (Date, Number...), pour pouvoir surcharger les validateurs existants ajoutés par ces éléments), il est nécessaire que le merge se fasse après.

Je ne me souviens plus exactement pourquoi, mais de mémoire j'avais fait ainsi pour régler cette problématique.

Dans ZF 3, je pense que j'apporterai des modifications à ce composant pour qui'l ne travaille qu'avec des PriorityQueue, pour ne plus avoir de faire de merge et juste se baser sur les priorités des validateurs.

Hors ligne

 

#13 27-11-2012 17:17:24

neilime
Membre
Date d'inscription: 28-04-2009
Messages: 42

Re: [Résolu]Le validateur Zend\Validator\NotEmpty ne fonctionne pas

Merci bakura pour ton éclaircissement, je comprend effectivement la logique mise en place.
La PriorityQueue est effectivement une solution parfaite pour ce genre de problématiques, mais s'il faut attendre ZF3, je passerai par mon propre InputFilter pour l'instant wink

Merci en tout cas pour votre aide.

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages