[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/EstablishmentsTable.php :

$this->belongsTo('Users', [
    'foreignKey' => 'user_id',
    'joinType' => 'INNER'
]);

$this->belongsToMany('Users', [
   'foreignKey' => 'establishment_id',
   'targetForeignKey' => 'user_id',
   'joinTable' => 'establishments_users'
]);

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 :

<?php $this->$this->belongsTo('User', [
    'className' => 'Users',
    'foreignKey' => 'user_id',
    'joinType' => 'INNER'
]);

$this->belongsToMany('Users', [
   'foreignKey' => 'establishment_id',
   'targetForeignKey' => 'user_id',
   'joinTable' => 'establishments_users'
]);

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 :

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

//On passe le tout à la vue.
$this->set('establishment', $establishment);

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 

À propos de Jean Traullé

Passionné par l'informatique et les nouvelles technos, titulaire d'un DUT Informatique, d'une LP RGI, et d'un Master MIAGE.
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