3.7.6.6 Créer et détruire des Associations à la volée

Quelquefois il devient nécessaire de créer et détruire les associations de modèles à la volée. Cela peut être le cas pour un certain nombre de raisons :

  • Vous voulez réduire la quantité de données associées qui seront récupérées, mais toutes vos associations sont sur le premier niveau de récursion.
  • Vous voulez changer la manière dont une association est définie afin de classer ou filtrer les données associées.

La création et destruction se font en utilisant les méthodes de modèles CakePHP bindModel() et unbindModel(). Mettons en place quelques modèles pour pouvoir ensuite voir comment fonctionnent bindModel() et unbindModel(). Nous commencerons avec deux modèles :

<?php

class Meneur extends AppModel {
    var $name = 'Meneur';

    var $hasMany = array(
        'Suiveur' => array(
            'className' => 'Suiveur',
            'order'     => 'Suiveur.rang'
        )
    );
}

?>

<?php

class Suiveur extends AppModel {
    var $name = 'Suiveur';
}

?>
  1. <?php
  2. class Meneur extends AppModel {
  3. var $name = 'Meneur';
  4. var $hasMany = array(
  5. 'Suiveur' => array(
  6. 'className' => 'Suiveur',
  7. 'order' => 'Suiveur.rang'
  8. )
  9. );
  10. }
  11. ?>
  12.  
  13. <?php
  14. class Suiveur extends AppModel {
  15. var $name = 'Suiveur';
  16. }
  17. ?>

Maintenant, dans le contrôleur MeneursController, nous pouvons utiliser la méthode find() du modèle Meneur pour retrouver un Meneur et les Suiveurs associés. Comme vous pouvez le voir ci-dessus, le tableau d'association dans le modèle Meneur définit une relation "Meneur hasMany (a plusieurs) Suiveurs". Dans un but démonstratif, utilisons unbindModel() pour supprimer cette association dans une action du contrôleur.

function uneAction() {
    // Ceci récupère tous les Meneurs, ainsi que leurs Suiveur
    $this->Meneur->findAll();

    // Supprimons la relation hasMany() ...
    $this->Meneur->unbindModel(
        array('hasMany' => array('Suiveur'))
    );

    // Désormais l'utilisation de la fonction find() retournera
    // des Meneurs, sans aucun Suiveurs
    $this->Meneur->findAll();

    // NOTE : unbindModel n'affecte que la prochaine fonction find.
    // Un autre appel à find() utilisera les informations d'association
    // telles que configurée.

    // Nous avons déjà utilisé findAll() après unbindModel(),
    // ainsi cette ligne récupèrera une fois encore les Meneurs 
    // avec leurs Suiveurs ...
    $this->Meneur->findAll();
}
  1. function uneAction() {
  2. // Ceci récupère tous les Meneurs, ainsi que leurs Suiveur
  3. $this->Meneur->findAll();
  4. // Supprimons la relation hasMany() ...
  5. $this->Meneur->unbindModel(
  6. array('hasMany' => array('Suiveur'))
  7. );
  8. // Désormais l'utilisation de la fonction find() retournera
  9. // des Meneurs, sans aucun Suiveurs
  10. $this->Meneur->findAll();
  11. // NOTE : unbindModel n'affecte que la prochaine fonction find.
  12. // Un autre appel à find() utilisera les informations d'association
  13. // telles que configurée.
  14. // Nous avons déjà utilisé findAll() après unbindModel(),
  15. // ainsi cette ligne récupèrera une fois encore les Meneurs
  16. // avec leurs Suiveurs ...
  17. $this->Meneur->findAll();
  18. }

Encore un rappel. Enlever ou ajouter des associations en utilisant bindModel() et unbindModel() ne fonctionne que pour la prochaine opération sur le modèle à moins que le second paramètre ait été fixé à true. Si le second paramètre a été fixé à true, le lien reste en place pour le rete de la requête. Voici un modèle basique de l'usage de unbindModel() :

$this->Modele->unbindModel(
    array('associationType' => array('nomDeClasseModeleAssocie'))
);
  1. $this->Modele->unbindModel(
  2. array('associationType' => array('nomDeClasseModeleAssocie'))
  3. );

Maintenant que nous sommes arrivés à supprimer une association à la volée, ajoutons-en une. Notre Meneur jusqu'à présent sans Principes a besoin d'être associé à quelques Principes. Le fichier de modèle pour notre modèle Principe est dépouillé, il n'y a que la ligne var $name. Associons à la volée des Principes à notre Meneur (mais rappelons-le, seulement pour la prochaine opération find). Cette fonction apparaît dans le contrôleur MeneursController :

function uneAutreAction() {
    // Il n'y a pas d'association Meneur hasMany Principes
    // dans le fichier de modèle meneur.php, ainsi un find
    // situé ici ne récupèrera que les Meneurs.
    $this->Meneur->findAll();

    // Utilisons bindModel() pour ajouter une nouvelle association
    // au modèle Meneur :
    $this->Meneur->bindModel(
        array('hasMany' => array(
                'Principe' => array(
                    'className' => 'Principe'
                )
            )
        )
    );

    // Maintenant que nous les avons associés correctement,
    // nous pouvons utiliser la fonction find une seule fois
    // pour récupérer les Meneurs avec leurs Principes associés :
    $this->Meneur->findAll();
}
  1. function uneAutreAction() {
  2. // Il n'y a pas d'association Meneur hasMany Principes
  3. // dans le fichier de modèle meneur.php, ainsi un find
  4. // situé ici ne récupèrera que les Meneurs.
  5. $this->Meneur->findAll();
  6. // Utilisons bindModel() pour ajouter une nouvelle association
  7. // au modèle Meneur :
  8. $this->Meneur->bindModel(
  9. array('hasMany' => array(
  10. 'Principe' => array(
  11. 'className' => 'Principe'
  12. )
  13. )
  14. )
  15. );
  16. // Maintenant que nous les avons associés correctement,
  17. // nous pouvons utiliser la fonction find une seule fois
  18. // pour récupérer les Meneurs avec leurs Principes associés :
  19. $this->Meneur->findAll();
  20. }

Ca y est, vous y êtes. L'utilisation basique de bindModel() est l'encapsulation d'un tableau d'association classique dans tableau dont la clé est le nom du type d'association que vous essayez de créer :

$this->Modele->bindModel(
        array('nomAssociation' => array(
                'nomDeClasseModeleAssocie' => array(
                    // les clés normales d'une association sont à mettre ici ...
                )
            )
        )
    );
  1. $this->Modele->bindModel(
  2. array('nomAssociation' => array(
  3. 'nomDeClasseModeleAssocie' => array(
  4. // les clés normales d'une association sont à mettre ici ...
  5. )
  6. )
  7. )
  8. );

Bien que le modèle nouvellement associé n'ait besoin d'aucune définition d'association dans son fichier de modèle, il devra tout de même contenir les clés afin que la nouvelle association fonctionne bien.