belongsTo et INNER JOIN
13/01/2009 | Publié dans cakephp
Encore une astuce bien cachée dans la documentation de CakePHP… Tellement bien cachée d’ailleurs qu’elle n’y apparaît même pas !
Bref, vous avez une relation belongsTo entre deux modèles, par exemple, vous avez un Concert qui belongsTo une salle de concert (a Venue, in English).
Dans la table venues, il y a un champ city, et je voudrais les prochains concerts dans une ville précise.
Si je me contente d’une relation belongsTo standard, CakePHP va générer lors d’un Model::find(’all’), avec juste une petite condition sur la date des concerts, une requête de ce type :
Le problème, c’est que cette requête va retourner toutes les salles de concert de Brest, y compris celle qui n’accueillent pas de concert dans les prochains jours, par le fait de la jointure externe gauche. Voici comment faire :
$this->Concert->unbindModel(array(’belongsTo’ => array(’Venue’)));
$this->Concert->bindModel(array(’belongsTo’ => array(’Venue’ => array(’type’ => ‘inner’))));
$conditions = array(’date >=’ => date(’Y-m-d’));
$order = array (’Concert.date’ => ‘asc’);
$limit = 20;
$params = compact(’contain’, ‘fields’, ‘limit’, ‘conditions’);
$concerts = $this->Concert->find(’all’, $params);
Les lignes intéressantes étant les lignes 2 et 3 : on commence par “défaire” la relation belongsTo définies entre les deux tables au niveau du modèle, avant de la reconstruire avec la clef “type” à “Inner”.
Si vous paginez vos résultats, n’oubliez pas de mettre le deuxième paramètre de Model::unbindModel() et Model::bindModel() à false, sans cela cette nouvelle relation ne s’appliquerait qu’à la requête suivant ces instructions avant d’être remise à zéro pour celle d’après ; or la pagination implique deux requêtes, une qui compte, l’autre qui récupère les résultats.





