Souvenez vous, il y a quelque temps, je vous parlais des associations HABTM (Has And Belong To Many). Ces associations bien pratiques permettent de faire en sorte de créer des relations plusieurs à plusieurs.
Seulement voilà, j’ai remarqué il y a peu de temps que par défaut, CakePHP n’incluait pas de manière simple de contrôler qu’une association était bien renseignée en utilisant les règles de validation intégrées au modèle.
Par exemple, dans l’écran suivant, l’utilisateur a la possibilité d’ajouter un item personnalisé dans le cas ou l’item qu’il souhaite évaluer n’est pas présent dans les items fournis avec l’application.
Cependant, un item possède forcément un où plusieurs niveaux associés (donc relation HABTM). Il est donc obligatoire de contrôler que l’utilisateur a bien sélectionné au moins un niveau pour l’item qu’il souhaite ajouter.
Les méthodes de Callback à la rescousse !
De base, CakePHP ne permet pas de faire une vérification sur ce champ car il n’est pas définit dans le modèle courant (car physiquement parlant, il s’agit d’une table différente).
Heureusement, nous pouvons nous en sortir autrement. CakePHP possède ce que l’on appelle des méthodes de Callback qui peuvent être appelées juste avant où après certains évènements. La méthode qui nous intéresse est beforeValidate()
.
Cette méthode nous permet d’exécuter une logique juste avant la validation des champs du modèle courant. Si vous souhaitez en savoir plus sur les différentes actions de Callback possibles, je vous conseille de jeter un oeil à la documentation CakePHP.
Une solution possible avec beforeValidate()
.
function beforeValidate($options = array()) {
if (!isset($this->data['Level']['Level'])
|| empty($this->data['Level']['Level'])) {
$this->invalidate('Level'); // fake validation error on Item
$this->Level->invalidate('Level', 'Sélectionnez au moins un niveau !');
}
return true;
}
Expliquons maintenant ce bout de code
Si on n’arrive pas à trouver le champ du modèle lié dans le tableau des données récupérées suite à l’envoi du formulaire où que celui-ci est vide, c’est que l’utilisateur n’a sélectionné aucun niveau.
On commence donc par tromper le modèle courant en invalidant n’importe quel champ (même un champ inexistant, cela n’a pas d’importance, cela permet juste de faire échouer la validation du modèle et donc de ne pas sauvegarder le nouvel enregistrement).
On invalide ensuite le champs en question (Level) ce qui aura pour effet de signaler le champ comme étant incorrect et de le mettre en évidence en rouge. Les deux instructions sont donc nécessaires et complémentaires.
Lors de la validation de notre formulaire, l’utilisateur se fera donc maintenant bien réprimander pour n’avoir pas renseigné le(s) niveau(x) du nouvel item 😉
A bientôt 😛