IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 PHP Discussion :

Validateur par comparaison sous condition [1.x]


Sujet :

PHP

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    163
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 163
    Points : 74
    Points
    74
    Par défaut Validateur par comparaison sous condition
    Bonjour,

    décidément symfony me donne du fil à retordre pour des choses qui sont toutes bêtes sans framework mais bon,
    je m'explique :

    j'ai un formulaire avec une année de début et une année de fin.
    Je voudrais que le validateur compare ces deux années pour que l'année de fin soit supérieure ou égale à l'année de début (jusque là c'est bon), mais uniquement si l'année de fin est renseignée (elle est facultative, et là çà se complique).

    J'ai donc écrit cela :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    $validateur_debut = new sfValidatorInteger(array('min'=>1990, 'max'=>9999));
    $this->validatorSchema['anneedebut'] = new sfValidatorAnd(array(
                    $this->validatorSchema['anneedebut'],  $validateur_debut));
     
    $validateur_fin = new sfValidatorInteger(array('min'=>1990, 'max'=>9999));
    $this->validatorSchema['anneefin'] = new sfValidatorAnd(array(
                    $this->validatorSchema['anneefin'],  $validateur_fin));
     
    $this->validatorSchema->setPostValidator(
     
                new sfValidatorSchemaCompare('anneedebut', sfValidatorSchemaCompare::LESS_THAN_EQUAL, 'anneefin',
                    array('throw_global_error' => false),
                    array('invalid' => 'La date de début de formation (%left_field%) doit être antérieure à celle de fin (%right_field%)'))
    );

    et je pensais ajouter un sfValidatorOr en global mais je vois pas quoi mettre en deuxième option. Après pas mal de recherches dans la doc de symfony, pas moyen de trouver.

    Je pense que c'est tout bébête mais bon "ouf" je suis dans la bonne rubrique ("débuter") :p

  2. #2
    Expert éminent
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Points : 8 486
    Points
    8 486
    Par défaut
    Débutant, débutant... c'est vite dit, c'est une question difficile à résoudre.

    Je vois trois solutions.

    1) En restant sur des validateurs existants, mais je ne sais pas si elle fonctionne.

    Dans ton post validator tu mets effectivement un sfValidatorOr avec ton code et un sfValidatorCallback qui va appeler la fonction is_null.


    2) Toujours avec sfValidatorCallback. Tu définis une méthode qui permettent de valider tes dates.

    Le validateur devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    $this->validatorSchema->setPostValidator(
                   new sfValidatorCallback(array('callback'=>array($this,
                   'compareAnnees')))
               );
    et dans un fichier dans lib/ de ton application tu définis ta fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    public function compareAnnees($validator, $values)
      {
        if (empty($values['anneefin']))
        {
          return $values;
        }
        else if ( anneefin > anneedebut)
        {
          throw new sfValidatorError($validator, 'Erreur les années ne sont pas bonnes');
        }
     
        return $values;
     
      }
    Code non testé.

    3) Tu peux dériver un validateur pour créer le tiens à utiliser dans tes form. Là tu y fais ce que tu veux.


    Personnellement, je prendrais l'option 3 qui est la plus souple mais peut-être pas la plus simple.

    Pour toi, j'essayerais la 1 et si cela ne passe pas, la 2.
    Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).

    • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
    • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
    • Une discussion est terminée ? Alors le bouton est votre ami !

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    163
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 163
    Points : 74
    Points
    74
    Par défaut
    Oula, ben moi qui pensait que çà passerait tout seul ... :p

    Merci pour votre réponse. La solution avec le callback m'effrayant un peu je vais tenter la proposition numéro 3, il me semble avoir vu un exemple de personnification de validateur dans la doc, je vais essayer de retrouver çà.

    Je sais que l'on peut accéder à la valeur du champ sur lequel porte le validateur par la variable $value mais comment peut-on accéder à une autre valeur du formulaire ?
    Pour faire simple, si je pose mon validateur correspondant au widget $this->widgetSchema['anneeFin'], comment accèder à la valeur correspondant au widget $this->widgetSchema['anneeDebut'] ?

  4. #4
    Expert éminent
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Points : 8 486
    Points
    8 486
    Par défaut
    Tu peux modifier les données de la méthode construct, qui correspondent aux données d’initialisation du validateur, le "compare" a plusieurs valeurs...
    Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).

    • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
    • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
    • Une discussion est terminée ? Alors le bouton est votre ami !

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    163
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 163
    Points : 74
    Points
    74
    Par défaut
    Citation Envoyé par Michel Rotta Voir le message
    Tu peux modifier les données de la méthode construct, qui correspondent aux données d’initialisation du validateur, le "compare" a plusieurs valeurs...
    Oui, mais comment fait-on pour récupérer les valeurs des champs du formulaire ? Je pensais à un truc du genre
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    $this->widgetSchema['anneeDebut']->getValue();
    mais çà n'existe pas :p

  6. #6
    Expert éminent
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Points : 8 486
    Points
    8 486
    Par défaut
    Dans ton validator tu as une méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    __construct($param1, $param2, $param3){
    Qui correspond à la construction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ... new monValidator($param1, $param2, $param3)
    Cette méthode est appelée pour chaque instantiation.

    Pense a récupérer et garder les notions standards, notamment pour les options, pour que tu n'aies pas à redéfinir toutes les méthodes.

    Inspire toi du code du validator compare, c'est le plus proche de ce que tu cherches. Possible même que tu puisses directement le dériver.
    Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).

    • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
    • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
    • Une discussion est terminée ? Alors le bouton est votre ami !

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    163
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 163
    Points : 74
    Points
    74
    Par défaut
    Bon, du coup j'ai créé mon validateur en me basant sur le sfValidatorSchemaCompare :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
    class ValidatorAnnees extends sfValidatorSchema{
        public function __construct($anneeDebut, $anneeFin, $options = array(), $messages = array()){
            $this->addOption('annee_debut', $anneeDebut);
            $this->addOption('annee_fin', $anneeFin);
     
            $this->addOption('min_value', 1900);
            $this->addOption('max_value', 9999);
     
            $this->addOption('throw_global_error', false);
     
            parent::__construct(null, $options, $messages);
        }
     
        protected function doClean($values){
            if (null === $values){
              $values = array();
            }        
     
            $anneeDebut  = isset($values[$this->getOption('annee_debut')]) ? $values[$this->getOption('annee_debut')] : null;
            $anneeFin = isset($values[$this->getOption('annee_fin')]) ? $values[$this->getOption('annee_fin')] : null;
     
            $min = $this->getOption('min_value');
            $max = $this->getOption('max_value');
     
            $valid = false;
     
            if( ($anneeDebut>=$min) && ($anneeDebut<=$max) ){
                if( ($anneeFin===null ) || ($anneeDebut<=$anneeFin && $anneeFin>=$min && $anneeFin<=$max) ){
                    $valid = true;
                }else{
                    $valid = false;
                }
            }else{
                $valid = false;        
            }
     
            if(!$valid){
                $error = new sfValidatorError($this, 'invalid', array(
                'annee_debut'  => $anneeDebut,
                'annee_fin' => $anneeFin);
     
                if ($this->getOption('throw_global_error')){
                    throw $error;
                }
     
              throw new sfValidatorErrorSchema($this, array($this->getOption('annee_debut') => $error, $this->getOption('annee_fin')=>$error));
            }
     
            return $values;
        }
    }
    mais je rencontre quelques problèmes.

    La comparaison entre les deux années se fait bien. Si l'année de fin est vide tout se passe bien.
    Le seul problème est que les bornes min et max ne sont pas prises en compte.
    Autrement dit je peut mettre "1800" et "1852" çà passera, si je mets 1852 et 1800 çà ne passera pas car la condition debut<=fin n'est pas respectée.

    Le plus curieux est que si je lance l'exception à tous les coups en enlevant le "if(!$valid){", cela ne change rien. Autrement dit tant que l'année de début est inférieure à celle de fin le formulaire passe, sinon non.

    Je me dis qu'il y a donc quelque chose que je ne saisis pas avec le fonctionnement.
    Mais quoi ?

    Précision : j'active mon validateur par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $this->validatorSchema->setPostValidator(new ValidatorAnnees('anne_debut', 'annee_fin'));

  8. #8
    Expert éminent
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Points : 8 486
    Points
    8 486
    Par défaut
    Je n'ai pas regardé ton code en détail mais...

    Si cela marche pour certaines chose, c'est que ton objet validateur est correcte, ce qui est le principale.

    Pour le code de validation, comme dirait un de mes vieux (il doit être mort) professeur d’algorithmie : "moins c'est compliqué, plus c'est facile" ou encore "si tu as un gros problème compliqué, découpe le en plusieurs petits problèmes simples". Peut-être qu'en limitant le nombre de vérifications simultanées tu réduirais la probabilité d'erreur ?
    Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).

    • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
    • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
    • Une discussion est terminée ? Alors le bouton est votre ami !

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    163
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 163
    Points : 74
    Points
    74
    Par défaut
    Concernant le découpage, oui je suis d'accord

    Le souci c'est qu'en déclenchant l'exception quelque soit les vérifications, le formulaire peut passé. C'est cela qui m'intrigue.

  10. #10
    Expert éminent
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Points : 8 486
    Points
    8 486
    Par défaut
    Toujours très rapidement (désolé) tu n'aurais pas un problème avec ce code ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
                if ($this->getOption('throw_global_error')){
                    throw $error;
                }
    essaye de le mettre en commentaire, pour voir.
    Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).

    • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
    • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
    • Une discussion est terminée ? Alors le bouton est votre ami !

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    163
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 163
    Points : 74
    Points
    74
    Par défaut
    Bon, honte à moi. Je sais pas si je devrais vous dire ce que je vais vous dire mais bon...
    Après de nombreux tests j'ai fini par réfléchir (oui oui çà m'arrive :p).
    Et je me suis dit que vu que j'essayais des trucs tordus et que cela ne changeait rien, c'est peut-être parce que effectivement, çà ne changeait rien...

    Bref, une copie de fichier foireuse, je travaillais pas sur le bon fichier, j'avais complétement oublié que j'avais fait une copie.

    Je suis désolé de vous avoir fait réfléchir sur un problème qui n'en était finalement pas un.



    Bon pour la peine, vu que çà peut peut-être intéresser, voici mon code final qui marche impeccablement bien :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
    class ValidatorAnnees extends sfValidatorSchema{
        public function __construct($anneeDebut, $anneeFin, $min=1900, $max=9999, $options = array(), $messages = array()){
            $this->addOption('annee_debut', $anneeDebut);
            $this->addOption('annee_fin', $anneeFin);
     
            $this->addMessage('invalid_'.$anneeDebut, 'Année de début invalide');
            $this->addMessage('invalid_'.$anneeFin, 'Année de fin invalide');
     
            $this->addOption('min', $min);
            $this->addOption('max', $max);
     
            $this->addOption('throw_global_error', false);
     
            parent::__construct(null, $options, $messages);
        }
     
        protected function doClean($values){
            if (null === $values){
              $values = array();
            }
     
            if (!is_array($values)){
              throw new InvalidArgumentException('You must pass an array parameter to the clean() method');
            }
     
            $anneeDebut  = isset($values[$this->getOption('annee_debut')]) ? $values[$this->getOption('annee_debut')] : null;
            $anneeFin = isset($values[$this->getOption('annee_fin')]) ? $values[$this->getOption('annee_fin')] : null;
     
            $anneeMin = $this->getOption('min');
            $anneeMax = $this->getOption('max');
     
            $error_values = array( 'annee_debut'  => $anneeDebut, 'annee_fin' => $anneeFin,
                                    'annee_min'  => $anneeMin, 'annee_max' => $anneeMax );
     
     
            if($anneeDebut<=$anneeMax && $anneeDebut>= $anneeMin){
                if(($anneeFin===null) || ($anneeDebut<=$anneeFin && $anneeFin<=$anneeMax)){            
                    $error_field = "";
                }else{
                    $error_field = $this->getOption('annee_fin');
                }
            }else{
                $error_field = $this->getOption('annee_debut');
            }
     
     
            if($error_field != ""){
                $error = new sfValidatorError($this, 'invalid_'.$error_field, $error_values);
     
                if ($this->getOption('throw_global_error'))
                {
                    throw $error;
                }
     
                throw new sfValidatorErrorSchema($this, array($error_field => $error));
     
            }
     
            return $values;
        }
    }

    Encore désolé !!!

  12. #12
    Expert éminent
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Points : 8 486
    Points
    8 486
    Par défaut
    Tu es presque bon pour aller poster ici.
    Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).

    • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
    • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
    • Une discussion est terminée ? Alors le bouton est votre ami !

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    163
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 163
    Points : 74
    Points
    74
    Par défaut
    Héhé oui, je crois bien !

    En tout cas, merci beaucoup pour votre aide. Bon et promis, j'essaie de plus faire des boulettes du genre !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2013] Remplacer une ligne par X lignes sous conditions
    Par unlucky dans le forum Excel
    Réponses: 3
    Dernier message: 10/06/2015, 11h43
  2. Comparaison de cellules sous conditions
    Par SPG except in VBA dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 17/07/2014, 19h45
  3. [XL-2007] Suppression données dans une colonne par comparaison et conditions
    Par cathodique dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 21/04/2013, 09h29
  4. Réponses: 5
    Dernier message: 16/11/2011, 00h59
  5. Réponses: 6
    Dernier message: 30/08/2008, 16h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo