Précédent   Forum des professionnels en informatique > PHP > Bibliothèques et frameworks > symfony
symfony Forum d'entraide sur le framework PHP symfony. Avant de poster : cours symfony et FAQ symfony
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 26/04/2011, 14h41   #1
lr
Membre du Club
 
Inscription : octobre 2003
Messages : 329
Détails du profil
Informations forums :
Inscription : octobre 2003
Messages : 329
Points : 69
Points : 69
Envoyer un message via ICQ à lr
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 :
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%")')
			)
		);
lr est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/05/2011, 12h38   #2
lr
Membre du Club
 
Inscription : octobre 2003
Messages : 329
Détails du profil
Informations forums :
Inscription : octobre 2003
Messages : 329
Points : 69
Points : 69
Envoyer un message via ICQ à lr
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
lr est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/05/2011, 12h33   #3
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
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 !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/05/2011, 16h22   #4
lr
Membre du Club
 
Inscription : octobre 2003
Messages : 329
Détails du profil
Informations forums :
Inscription : octobre 2003
Messages : 329
Points : 69
Points : 69
Envoyer un message via ICQ à lr
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
lr est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/05/2011, 10h59   #5
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
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 !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/05/2011, 11h02   #6
lr
Membre du Club
 
Inscription : octobre 2003
Messages : 329
Détails du profil
Informations forums :
Inscription : octobre 2003
Messages : 329
Points : 69
Points : 69
Envoyer un message via ICQ à lr
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.
lr est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/05/2011, 16h04   #7
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
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 !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/05/2011, 16h07   #8
lr
Membre du Club
 
Inscription : octobre 2003
Messages : 329
Détails du profil
Informations forums :
Inscription : octobre 2003
Messages : 329
Points : 69
Points : 69
Envoyer un message via ICQ à lr
Ce fut laborieux mais ça à l'air de marcher :

SessionForm.class.php :
Code :
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 :
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
lr est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/05/2011, 18h04   #9
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
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 !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 07h05.


 
 
 
 
Partenaires

Hébergement Web