[CakePHP 3.x] Associations belongsTo et belongsToMany

Petit billet technique aujourd’hui pour parler des associations dans CakePHP 3.x

Vous le savez sans doute, la meilleure façon de récupérer des données associées à vos tables en utilisant CakePHP est d’utiliser les associations. 😀 Il existe différent types d’associations dans CakePHP et notamment les associations belongsTo et belongsToMany.

Association belongsTo

Une association belongsTo permet de récupérer les informations d’un enregistrement associé à une table par l’intermédiaire d’une clé étrangère.

Par exemple, il est possible de récupérer les informations de l’enseignant titulaire d’une classe en utilisant cette association si la table classrooms contient une clé étrangère vers la table des users.

Association belongsToMany

À l’inverse des associations belongsTo, les associations belongsToMany permettent — comme leur nom l’indique — d’associer plusieurs enregistrements à une table donnée.

Si l’on reprend mon exemple précédent, on peut très bien utiliser cette association pour lier plusieurs enseignants (qui enseignent différentes matières) à une même classe. Cette association, nécessite obligatoirement la création d’une table de relation (par exemple classrooms_users).

belongsTo et belongsToMany dans un même bateau

Maintenant, quelque chose d’assez insolite. Peut-on utiliser une association belongsTo ainsi qu’une association belongsToMany vers une même table ?

Je m’explique : j’ai dans ma table users une clé étrangère user_id contenant l’id de l’utilisateur titulaire de la classe. Mais, j’ai également une table de relation classrooms_users qui permet de lier l’ensemble des autres enseignants.

C’est tout à fait possible. Cependant, lorsque l’on utilise bin/cake bake model, le générateur de code de CakePHP nomme les associations de façon identique.

On aura donc dans notre fichier de table src/Model/Table/<strong>EstablishmentsTable</strong>.php :

<span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">belongsTo</span><span class="token punctuation">(</span><span class="token string">'Users'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>
    <span class="token string">'foreignKey'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'user_id'</span><span class="token punctuation">,</span>
    <span class="token string">'joinType'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'INNER'</span>
<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">belongsToMany</span><span class="token punctuation">(</span><span class="token string">'Users'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>
   <span class="token string">'foreignKey'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'establishment_id'</span><span class="token punctuation">,</span>
   <span class="token string">'targetForeignKey'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'user_id'</span><span class="token punctuation">,</span>
   <span class="token string">'joinTable'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'establishments_users'</span>
<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
PHP

Cependant, comme les deux associations sont nommées de la même façon lignes 1 et 6 (Users), seule la dernière sera conservée (la belongsToMany donc). Il faut donc renommer l’une des associations. Par exemple, en ce qui me concerne, je met celle en belongsTo au singulier. Il faut par contre du coup indiquer à CakePHP le className associé puisqu’il n’est plus capable de deviner automatiquement la table liée.

On obtient donc :

<span class="token delimiter"><?php</span> <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">></span><span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">belongsTo</span><span class="token punctuation">(</span><span class="token string">'User'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>
    <span class="token string">'className'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'Users'</span><span class="token punctuation">,</span>
    <span class="token string">'foreignKey'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'user_id'</span><span class="token punctuation">,</span>
    <span class="token string">'joinType'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'INNER'</span>
<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">belongsToMany</span><span class="token punctuation">(</span><span class="token string">'Users'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>
   <span class="token string">'foreignKey'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'establishment_id'</span><span class="token punctuation">,</span>
   <span class="token string">'targetForeignKey'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'user_id'</span><span class="token punctuation">,</span>
   <span class="token string">'joinTable'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'establishments_users'</span>
<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
PHP

Ensuite, depuis mon contrôleur, en utilisant l’option contain de find() ou get() je serai à même de récupérer ces deux associations :

<span class="token comment">//On récupère l'établissement, les classes, les périodes </span>
<span class="token comment">//l'utilisateur titulaire et les enseignants associés </span>
<span class="token comment">//correspondant à l'année courante.</span>
<span class="token variable">$establishment</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">Establishments</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token variable">$id</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>
    <span class="token string">'contain'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token punctuation">[</span>
        <span class="token string">'User'</span><span class="token punctuation">,</span>
        <span class="token string">'Users'</span><span class="token punctuation">,</span>
        <span class="token string">'Academies'</span><span class="token punctuation">,</span>
        <span class="token string">'Periods'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token punctuation">[</span>
            <span class="token string">'conditions'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token punctuation">[</span>
                <span class="token string">'Periods.year_id ='</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token variable">$currentYear</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">value</span>
            <span class="token punctuation">]</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token string">'Classrooms'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token punctuation">[</span>
            <span class="token string">'conditions'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token punctuation">[</span>
                <span class="token string">'Classrooms.year_id ='</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token variable">$currentYear</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">value</span>
            <span class="token punctuation">]</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span>
<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">//On passe le tout à la vue.</span>
<span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'establishment'</span><span class="token punctuation">,</span> <span class="token variable">$establishment</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
PHP

On récupère bien les informations attendues dans notre vue. Nous avons donc dans notre objet establishment une propriété membre users qui correspond à notre association belongsToMany ET une propriété membre user qui correspond à notre association belongsTo !

On peut d’ailleurs le vérifier avec DebugKit :

Associations croisées

DebugKit nous permet de vérifier que nous récupérons bien ce que nous souhaitons.

À bientôt 😉

A propos Jean Traullé

Passionné par l'informatique et les nouvelles technos, miagiste, papa de opencomp.fr, #sysadm, #ProxmoxVE, #Docker, #TYPO3, #CakePHP enthousiaste 😊
Ce contenu a été publié dans Non classé, avec comme mot(s)-clé(s) , , , , , . Vous pouvez le mettre en favoris avec ce permalien.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *