Une clé étrangère présente deux fois dans une table
Imaginons une application de gestion de résultats sportifs : nous avons une table “equipes” et une table “rencontres”. La table “recontres” va comporter deux fois la clé primaire de la table “equipes” : equipe_locaux_id pour l’équipe locale et equipe_visiteurs_id pour l’équipe des visiteurs. Comment gérer cette association particulière dans CakePHP ?
1. Définition des alias de Modèle
Voyons le Modèle “Equipe” :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Equipe extends AppModel { var $name = "Equipe"; var $hasMany = array( 'RencontreDomicile' => array( 'className' => 'Rencontre', 'foreignKey' => 'equipe_locaux_id' ), 'RencontreExterieur' => array( 'className' => 'Rencontre', 'foreignKey' => 'equipe_visiteurs_id' ) ); } |
Et le Modèle “Rencontre” :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Rencontre extends AppModel { var $name = "Rencontre"; var $belongsTo = array( 'EquipeLocaux' => array( 'className' => 'Equipe', 'foreignKey' => 'equipe_locaux_id' ), 'EquipeVisiteurs' => array( 'className' => 'Equipe', 'foreignKey' => 'equipe_visiteurs_id' ) ); } |
Grâce à cette définition de l’association, nous pouvons faire référence à la même table “equipes” mais en différenciant bien le statut de chaque équipe pour une rencontre donnée.
Dans le Contrôleur “RencontresController”, nous pouvons obtenir les informations sur les deux équipes qui ont participé à une rencontre donnée :
1 2 3 4 5 6 7 8 9 10 11 12 13 | // /controllers/rencontres_controller.php function adversaires($id) { $this->set( 'equipe_locaux', $this->Rencontre->EquipeLocaux->findByRencontreId($id) ); $this->set( 'equipe_visiteurs', $this->Rencontre->EquipeVisiteurs->findByRencontreId($id) ); } |
Dans le Contrôleur “EquipesController”, nous pouvons savoir pour une équipe donnée, les matchs joués à domicile et ceux joués à l’extérieur :
1 2 3 4 5 6 7 8 9 10 11 12 13 | // /controllers/equipes_controller.php function rencontres_jouees($id) { $this->set( 'rencontres_domicile', $this->Equipe->RencontreDomicile->findAllByEquipeId($id) ); $this->set( 'rencontres_exterieur', $this->Equipe->RencontreExterieur->findAllByEquipeId($id) ); } |
2. Utilisation des alias à l’intérieur du Modèle
Grâce à la définition des associations faites dans le Modèle, nous avons défini des alias différents pour la même classe Model. Nous devons faire attention à employer l’alias plutôt que le nom du Modèle à l’intérieur des méthodes de la classe Model : l’alias en cours est accessible via $this->alias.
Voyons par exemple le callback afterFind du Modèle Equipe, à qui l’on va demander de tester l’existence d’un drapeau en GIF portant le nom de l’id de l’équipe dans le répertoire img/drapeaux, et de compléter le tableau de données renvoyé par la base avec le nom de l’image trouvée.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // /app/model/equipe.php function afterFind($results) { $drapeaux_dir = 'img/drapeaux/'; foreach($results as $k => $result) { if($result[$this->alias]['id']) { $drapeau_img = $result[$this->alias]['id'].'.gif'; if(@file_exists($drapeaux_dir.$drapeau_img)) { $results[$k][$this->alias]['drapeau_img'] = $drapeaux_dir.$drapeau_img; } else { $results[$k][$this->alias]['drapeau_img'] = $drapeaux_dir.'no_flag.gif'; } } } return $results; } |
Si nous avions écrit, intuitivement, $result['Equipe']['id'] au lieu de $result[$this->alias]['id'], nous aurions eu droit à un message d’erreur, car ‘Equipe’ est bien le nom du Modèle, mais pas le nom de l’instance en cours. Ce nom peut être, selon la méthode qui appelle le find ou le findAll :
- soit effectivement ‘Equipe’,
- soit ‘EquipeLocaux’,
- soit ‘EquipeVisiteurs’.
Pierre-Emmanuel Fringant
Salut,
Dirais-tu que ton exemple permet de modéliser sous Cake une “association réflexive” ?
Parce qu’en cas de multiples rencontres entre les mêmes équipes (relation n:m), l’association “hasMany / bleongsTo” ne tiendrait plus… or Cake semble ne pas pouvoir modéliser correctement ce genre de relation (SQLellement parlant bien entendu).
Je suis à la recherche de solutions sur le sujet, car je dois utiliser des schémas de BDD tout fait, dont je ne peux modifier les associations et les clés/index…
13 février 2008 à 11:57
Auteur : Avairet