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

Symfony PHP Discussion :

Besoin d'aide pour créer un validateur personnalisé


Sujet :

Symfony PHP

  1. #1
    lr
    lr est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2003
    Messages : 338
    Points : 114
    Points
    114
    Par défaut Besoin d'aide pour créer un validateur personnalisé
    Salut,

    Dans mon application, je peux saisir des cours qui ont une date de début et une date de fin et des sessions qui sont rattachées à des cours avec aussi une date de début et une date de fin.

    La date de début d'une session doit être antérieure à sa date de fin.

    La plage définie par la date de début et la date de fin d'une session doit se trouver à l'intérieur de la plage définie par la date de début et la date de fin du cours (dont l'id figure dans un champs du formulaire).

    Ensuite je devrais aussi vérifier que les sessions ne se chevauchent pas mais pour l'instant, restons-en là.

    J'ai étudié la documentation mais je ne sais pas trop comment démarrer, entre une méthode définie comme callback dans le postvalidator ou un validator personnalisé et j'ai du mal à trouver des exemples.

    Merci d'avance pour vos conseils

    PS pour la première contrainte, j'ai fait ça et ça marche bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $this->validatorSchema->setPostValidator(
    			new sfValidatorSchemaCompare('datedebut', sfValidatorSchemaCompare::LESS_THAN_EQUAL, 'datefin',
    				array(),
    				array('invalid' => 'La date de début ("%left_field%") doit être antérieure à la date de fin ("%right_field%")')
    			)
    		);

  2. #2
    lr
    lr est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2003
    Messages : 338
    Points : 114
    Points
    114
    Par défaut
    Qqun aurait un exemple de validation d'un champs pour qu'il satisfasse à deux contraintes liées à des autres champs voir à des autres tables de la BDD ?

    Merci d'avance

  3. #3
    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 ne comprend pas ce que tu veux pour la deuxième contrainte.
    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 !

  4. #4
    lr
    lr est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2003
    Messages : 338
    Points : 114
    Points
    114
    Par défaut
    Un cours est composé de sessions. Lorsqu'on saisit une session, il faut valider qu'elle ne chevauche pas une session déjà existante.

    Par exemple, pour un cours intitulé "introduction à la mécanique" pour lequel on saisirait une première session du 10 mai à 10h au 14 mai à 18h, il ne faudrait pas qu'on puisse saisir une deuxième session du 13 mai à 10h au 20 mai à 18h.

    Le validateur devra donc récupérer les sessions existantes pour le cours et vérifier que la date de début de la session en cours de saisie n'est pas comprise dans une plage définie par une session déjà existante pour le même cours.

    Du point de vue de l'algorythmie et de l'interaction avec doctrine, je m'en sortirai mais je ne sais pas comment intégrer ça proprement à symfony sous forme de validateur.

    Merci pour ton aide

  5. #5
    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
    Intéressant.

    Et c'est très proche d'un validateur qu'il faut que je mette en place aussi.

    Il faut créer un validateur sur le modèle de sfValidatorSchemaCompare qui sera un enfant de sfValidatorSchema. On récupère donc dans la méthode doClean() le tableau des valeurs du form (récupérées par le bind).

    Il reste à faire appel à une méthode de l'objet du modèle qui vérifiera s'il y a chevauchement et, si oui, retournera un false qui pourra générer, dans le validateur, l’interruption pour l'erreur.

    Dans l'idée ce pourrait être cela, qu'en penses tu ?
    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 !

  6. #6
    lr
    lr est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2003
    Messages : 338
    Points : 114
    Points
    114
    Par défaut
    Je pense que oui. J'espérais trouver un exemple mais avec ce que tu dis je devrais pouvoir me débrouiller pour essayer.

    Pour l'instant je dois laisser ça de coté mais dès que je fais un test je le partage ici.

  7. #7
    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
    Si j'arrive dessus avant, je partage aussi
    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 !

  8. #8
    lr
    lr est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2003
    Messages : 338
    Points : 114
    Points
    114
    Par défaut
    Ce fut laborieux mais ça à l'air de marcher :

    SessionForm.class.php :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    	public function configure()
    	{
    		$this->validatorSchema->setPostValidator(
    			new myValidatorSessionCompare( 
    				array(),
    				array(),
    				array(
    					"interval" => "La date de début ('%datedebut%') doit être antérieure à la date de fin ('%datefin%')",
    					"chevauchement" => "La nouvelle session chevauche une session existante ('%lieu%')"))
    		);
    	}
    myValidatorSessionCompare.class.php :
    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    <?php
     
    /**
     * Vérifier que la session en cours de saisie ne chevauche pas une session déjà
     * existante et que sa date de début est antérieure à sa date de fin
     */
    class myValidatorSessionCompare extends sfValidatorSchema
    {
    	protected static
    	    $globalDefaultMessages = array(
    	    	"interval" => "La date de début ('%datedebut%') doit être antérieure à la date de fin ('%datefin%')",
    	    	"chevauchement" => "La nouvelle session chevauche une session existante ('%lieu%')" );
     
    	/**
    	 * Constructeur recopié de sfValidatorBase pour qu'il me laisse passer les codes
    	 * "interval" et "chevauchement" (cf $globalDefaultMessages)
    	 *
    	 * @see sfValidatorBase
    	 */
    	public function __construct( $options = array(), $messages = array() )
    	{
    		$this->options  = array_merge(array('required' => true, 'trim' => false, 'empty_value' => null), $this->options);
    	    $this->messages = array_merge(array('interval' => self::$globalDefaultMessages['interval'], 'chevauchement' => self::$globalDefaultMessages['chevauchement']), $this->messages);
     
    	    $this->configure($options, $messages);
     
    	    $this->setDefaultOptions($this->getOptions());
    	    $this->setDefaultMessages($this->getMessages());
     
    	    $currentOptionKeys = array_keys($this->options);
    	    $optionKeys = array_keys($options);
     
    	    // check option names
    	    if ($diff = array_diff($optionKeys, array_merge($currentOptionKeys, $this->requiredOptions)))
    	    {
    	      throw new InvalidArgumentException(sprintf('%s does not support the following options: \'%s\'.', get_class($this), implode('\', \'', $diff)));
    	    }
     
    	    // check error code names
    	    if ($diff = array_diff(array_keys($messages), array_keys($this->messages)))
    	    {
    	      throw new InvalidArgumentException(sprintf('%s does not support the following error codes: \'%s\'.', get_class($this), implode('\', \'', $diff)));
    	    }
     
    	    // check required options
    	    if ($diff = array_diff($this->requiredOptions, array_merge($currentOptionKeys, $optionKeys)))
    	    {
    	      throw new RuntimeException(sprintf('%s requires the following options: \'%s\'.', get_class($this), implode('\', \'', $diff)));
    	    }
     
    	    $this->options  = array_merge($this->options, $options);
    	    $this->messages = array_merge($this->messages, $messages);
    	}
     
    	/**
    	 * @see sfValidatorBase
    	 */
    	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');
    		}
     
    		$sessionCoursId = $values[ "cours_id" ];
    		$sessionDateDeb = $values[ "datedebut" ];
    		$sessionDateFin = $values[ "datefin" ];
     
    		//vérifier que la date de début est antérieure à la date de fin
    		$valid = $sessionDateDeb <= $sessionDateFin;
     
    		if (!$valid)
    		{
    			$error = new sfValidatorError($this, "interval", array(
    		        "datedebut"  => $sessionDateDeb,
    		        "datefin" => $sessionDateFin,
    			));
    			/*if ($this->getOption('throw_global_error'))
    			 {
    			 	throw $error;
    			 }*/
     
    			throw new sfValidatorErrorSchema($this, array("datedebut" => $error));
    		}
     
    		//vérifier que la session ne chevauche pas une sesson déjà existante
    		$cours = Doctrine_Core::getTable( "Cours" )->find( $sessionCoursId );
    		if ( !$cours )
    			return $values;
     
    		foreach( $cours->getSessions() as $session )
    		{
    			if ( $sessionDateDeb < $session->getDateDebut()  )	//la session est avant la session existante
    				if ( $sessionDateFin >= $session->getDateDebut() )	//la date de fin doit être avant le début de la session existante 
    					$this->error( $session );
     
    			if ( $sessionDateDeb > $session->getDateDebut() )	//la session est après la session existante
    				if ( $sessionDateDeb <= $session->getDateFin() )	//la date de début doit être après la fin de la session exisante
    					$this->error( $session );
    		}
     
     
    		return $values;
    	}
     
    	private function error( $session )
    	{
    		$error = new sfValidatorError($this, "chevauchement", array(
    	        "lieu"  => $session->getLieu()
    		));
    		throw $error;
    	}
    }
    Pas sûr que ce soit vraiment dans les règles de l'art, mais bon

  9. #9
    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
    C'est pas top.

    La requête ne peut faire partie du validateur. Ceci le limite drastiquement à ce cas très précis.

    En fait, il faudrait prévoir une options pour récupérer le nom du modèle et une pour la méthode du modèle qui retournera les données a tester.

    Ceci permettra alors un bon fonctionnement de la chose et sur tous les modèles de données envisageable.

    J'ai pris du retard sur du dessin en svg, mais j'arrive doucement à cette partie du développement.
    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 !

Discussions similaires

  1. Besoin d'aide pour créer une requête
    Par fabien59420 dans le forum Requêtes et SQL.
    Réponses: 44
    Dernier message: 26/05/2008, 11h08
  2. Besoin d'aide pour créer une BD
    Par desfrags dans le forum Débuter
    Réponses: 6
    Dernier message: 30/01/2008, 22h20
  3. Besoin d'aide pour créer un .reg sous Vista
    Par Silverscott dans le forum Windows Vista
    Réponses: 3
    Dernier message: 25/07/2007, 14h09
  4. On a besoin d'aide pour créer un site de soirée électorale
    Par pliporte75 dans le forum Administration
    Réponses: 2
    Dernier message: 01/04/2007, 18h02
  5. besoin d'aide pour créer un uml
    Par bob75018 dans le forum UML
    Réponses: 9
    Dernier message: 11/03/2006, 12h18

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