J’ai abordé récemment la mise en place sur quelques modules d’Opencomp des associations CakePHP HABTM (Has And Belong To Many). Mais, c’est quoi une association HABTM ? Has And Belong To Many signifie en français Possède Et Appartient À Plusieurs. Concrètement, il s’agit d’une relation Plusieurs à plusieurs (n : m).
Par exemple, un utilisateur peut gérer 0 à n académie(s) et, une académie doit être gérée par 1 à n utilisateurs.
Si on reprend la méthode d’analyse et de conception Merise, on représenterait donc cette association de la manière suivante :
Traduisons maintenant cela sous forme d’un Modèle Logique de données. Lors de la transposition, une association binaire n : m se matérialise forcément par une table de jointure supplémentaire. Nous allons donc créer la table academies_users. Là encore, le nom à de l’importance puisque il s’agit de conventions de nommage de CakePHP.
Par convention, les noms des modèles à lier doivent être inscrit dans l’ordre alphabétique, au pluriel et être séparés par un underscore (_). Par ailleurs, il n’est normalement pas nécessaire de créer un attribut id dans la table academies_users puisque la clé primaire est donc binaire et composée des deux clés étrangères. Cependant, CakePHP nécessite de placer la clé primaire sur un attribut id de façon à pouvoir effectuer les opérations sur la table de manière plus aisée.
Et avec CakePHP, on fait comment ?
Prenons l’exemple des académies. Je souhaite pour le moment matérialiser la relation « une académie peut être gérée par 1 à n utilisateurs. Dans notre modèle, nous allons devoir ajouter quelques lignes pour indiquer cette relation :
class Academy extends AppModel { var $hasAndBelongsToMany = array( 'User' => array( 'className' => 'User', 'joinTable' => 'academies_users', 'foreignKey' => 'academy_id', 'associationForeignKey' => 'user_id' ) ); ...
Avec ce fragment de code (juste 10 lignes), nous venons d’indiquer à CakePHP que nous utilisons une association HABTM. Là, on indique que les académies sont reliées aux utilisateurs. Cependant, l’intérêt d’utiliser ce type d’association est que l’utilisateur associé à une académie ne l’est pas exclusivement. On peut très bien l’attacher à d’autres académies par ailleurs.
Mais, visuellement ? Ça donne quoi tes HABTM ?!!
Encore une fois, il y a de très nombreuses méthodes pour permettre graphiquement à l’utilisateur d’associer un ou plusieurs utilisateurs à une académie (cases à cocher, select, etc.). Le contrôle privilégié par CakePHP est le select en autorisant les sélections multiples bien évidemment. Cependant, ce n’est pas très ergonomique pour l’utilisateur.
Je me suis donc mis en quête pour trouver un joli plugin Jquery (librairie javascript) permettant d’améliorer tout ceci … et j’ai trouvé l’oiseau rare : Chosen.
Ci-dessous, une petite démonstration du rendu final …
N’hésitez pas à donner votre avis ou à poser des questions dans les commentaires de ce billet …
Bonjour, je travaille sous php myadmin avec ruby comme langage, je souhaiterais faire un formulaire ou les membres peuvent faire plusieurs projets et des projets peuvent contenir plusieurs membres. Donc j’aimerais que lors de la création d’un nouveau membre, j’ai une liste déroulante des projets disponibles et que lorsque je choisis l’un d’eux et que je valide le formulaire, ma table de jointure dans ma base de données sois automatiquement mise à jour et que lorsque je regarde un projet en particulier ou un membre, on m’indique qui participe à quoi? aurais-tu la bonne formule select pour réussir à faire ça? merci d’avance
Je suis désolé, mais je n’ai jamais fait de Ruby. Je forward ton commentaire à un pote qui est fan 😉
Il pourra sans doute te répondre !
Salut.
Tu utilises Ruby on Rails ?
Si oui, je pourrais t’aider. Sinon. Ben non :/
Ping : [CakePHP] Validation des modèles HABTM liés | Opencomp.fr – Carnet de développement
Bonjour,
Merci beaucoup pour cet article, bien expliqué et bien écrit !
Cependant il me reste une petite question à la suite de cette lecture :
La variable $hasAndBelongToMany doit être déclaré dans les deux modèles ?
Je code actuellement une application avec cakePHP dans laquelle j’ai des projets et des utilisateurs. Un projet peut appartenir à 1 ou n utilisateur et un utilisateur peut avoir 0 ou n projet, c’est donc exactement la même utilisation que dans l’exemple.
Bonjour Goulven,
En réalité tout dépend d’à partir d’où tu souhaites lier tes données.
Dans tous les cas, si tu désires lier des deux côtés, dans ce cas, défini le dans les deux modèles 😉
Si tu as d’autres questions ou si ça ne fonctionne pas comme tu le souhaites, n’hésites pas à redemander de l’aide 🙂
Merci beaucoup pour la rapidité de ta réponse 🙂 !
Effectivement il me reste une petite question : Comment je nomme mon modèle selon les convention de nommage de cakePhP?
Je m’explique, ma table s’appelle protocoles_users, mon modèle doit donc être ProtocoleUser.php ou ProtocolesUser.php ?
Je suis toujours un peu bloqué avec ces conventions de nommage..
Si tu souhaites créer le modèle, il devra s’appeler ProtocolesUser.php mais normalement, il n’est pas nécessaire de le créer. Personnellement, ça marche très bien sans créer le fichier (juste en déclarant le HABTM dans les modèles où j’en ai besoin) 😉
Bonjour,
Merci pour cette explication déjà. Je travaille sur un projet sous CakePHP mais j’ai un problème au niveau conceptuel :
– J’ai une table Cities qui contient des noms de ville
– Une 2eme tables Contents qui contient du contenu (un descriptif)
Ce que je voudrais, c’est avoir un sous menu entre cities et Contents : chaque Ville aura un menu (le meme menu pour toutes les villes) et le Contenu changera en fonction de la ville et de l’option du sous menu
(Ville : ‘Paris’ -> Menu : ‘A visiter’ -> Contenu : ‘tour eiffel’) peut etre que c’est plus explicite comme cela
Est ce que tu as une idée du MCD correspondant?
J’ai beau relire encore et encore le commentaire, j’ai du mal à comprendre le cas.
Nous avons donc des villes (OK) et Contents contient un descriptif (texte explicatif en relation avec la ville ?). Ton menu « À visiter » contiendra t-il toujours des lieux ?
Pourrais tu me donner ta structure de donnée actuelle et détailler davantage ce à quoi tu veux arriver ? Cela me permettrait de mieux te conseiller 🙂
Rapide et dispo =)
Alors il y a une table Cities qui ne contient que des villes. Une table Contents qui contient des descriptifs. Je voudrais mettre en place une 3e table qui serait en fait une sorte de menu d’action pour chaque ville (pour l’instant les actions sont ‘A visiter’, ‘Ou manger’, ‘Ou dormir’).
Donc selon la ville choisit et l’action du menu choisit, le contenu doit changer…
J’espère avoir été plus clair
A niveau de la problématique donc, à mon avis, rien ne justifie d’utiliser l’association HABTM puisque tes lieux, restaurants et hôtels seront obligatoirement ratachés à une seule ville.
Pour ma part, je verrais les tables suivantes cities, places, restaurants et hotels. Je supprimerai la table contents qui n’a (à mon avis) pas lieu d’être, autant mettre le descriptif dans la table cities. Les tables places, restaurants et hotels auraient des clés étrangères pointant vers l’enregistrement associé dans la table cities.
Voilà à quoi cela pourrait ressembler http://f.cl.ly/items/3Y0t0g1R262Z021R272o/MLD.png
Si j’ai bien un conseil à te donner, c’est de bien réfléchir à ton modèle de données. C’est la chose la plus cruciale dans une application informatique et rater cette étape peut conduire dans certains cas à devoir tout recommencer car la conception initiale est mauvaise. Donc, prend le temps de bien faire les choses 😉
Si je n’ai pas répondu correctement à ta question, n’hésites pas à re-demander de l’aide 🙂
Oki! Ca correspond à ce que je veux faire. Justement pour la conception, avant que je ne commence réellement à coder, j’ai préféré assurer le MCD! En tout cas Merci pour le coup de pouce!