Accueil > Développement > CakePHP : Relation HABTM avec champs supplémentaires

CakePHP : Relation HABTM avec champs supplémentaires

Bonjour à tous,

CakePHP est un framework php permettant de réaliser des applications web de façon simple, structurée et rapide, mais lorsqu’on s’attaque aux relations HasAndBelongsToMany (HABTM), ça devient un peu plus compliqué.
Voilà maintenant quelques temps que je suis à la recherche d’une solution simple pour pouvoir gérer les relations HABTM dont la table associative contient un ou plusieurs champs supplémentaires (Mon post sur un forum). Je n’ai jamais trouvé d’exemple complet sur internet, en voici donc un qui j’espère vous aidera à manier la bête !

A titre d’exemple une petite application permettant la saisie de recettes de cuisine. Pour chaque recette créée, il faut indiquer les ingrédients qui entrent en compte.  Pour sauvegarder toutes les informations, j’ai créé les 3 tables suivantes :


recipes (id, name, date_created);
ingredients (id, name);
ingredients_recipes(id, recipe_id,ingredient_id, quantity);

Le but de l’exercice est donc de trouver un moyen de créer une recette et d’insérer directement les ingrédients ainsi que leur quantité dans la table associative ingredients_recipes. La création s’effectue très simplement, il suffit juste d’envoyer les bonnes données au contrôleur. Pour se faire, voici un extrait de la vue que j’utilise  :


echo $form->input('name');
echo $form->input('date_created');
echo $form->select("IngredientsRecipe.0.ingredient_id",$ingredients);
echo $form->input('IngredientsRecipe.0.quantity');
echo "<br />" ;
echo $form->select("IngredientsRecipe.1.ingredient_id", $ingredients);
echo $form->input('IngredientsRecipe.1.quantity');
echo "<br />" ;
echo $form->select("IngredientsRecipe.2.ingredient_id", $ingredients);
echo $form->input('IngredientsRecipe.2.quantity');

Pour sauvegarder le tableau qui sera transmis par le formulaire, il faut utiliser une petite astuce. Il faut en effet relier le modèle Recipe au modèle IngredientsRecipe à l’aide d’une relation $hasMany. Une fois les modèles liés, on peut faire appel à la fonction saveAll :

if (!empty($this->data)) {
//Astuce bind nécessaire pour sauvegarder correctement chaque valeur
$this->Recipe->bindModel(array(‘hasMany’=>array(‘IngredientsRecipe’)));
if ($this->Recipe->saveAll($this->data)) {
$this->Session->setFlash(‘Votre recette a été correctement créée’);
$this->redirect(array(‘action’ => ‘index’));
}
}

Toutes les données sont sauvegardées correctement. Pour la modification d’une recette, c’est la même technique de sauvegarde qui est utilisée. On bind et on saveAll. 
Le grand changement intervient dans la vue permettant de modifier la recette :

//Chaque champs ingrédients doit être géré comme ceci.
echo $form->select("Ingredient.0.IngredientsRecipe.ingredient_id", $ingredients,$recipe['Ingredient'][0]['id']) ;
echo $form->input("Ingredient.0.IngredientsRecipe.quantity") ;
Voilà vous savez quasiment comment sauver vos HABTM avec champs supplémentaires. Comme je ne peux pas poster tout le code source ici et qu’un bon exemple vaut mieux qu’un long discours, je vous propose un package contenant l’exemple complet ainsi que le script de création sql : Télécharger le package

Références :

Astuce pour sauvegarder la relation HABTM
Gestion correcte de la vue en mode édition


Categories: Développement Tags: , , ,
  1. Pas encore de commentaire
  1. Pas encore de trackbacks
*