Bonjour,

j'ai appris récemment les bases de cakePHP2 ici, et je voudrais l'utiliser pour un de mes projets de site.
Je bute un peu sur la fabrication de requête en utilisant le modèle lorsqu'il y'a + de 2 tables à joindre.

Le contexte :
Un groupe de concessions automobiles multi marques, chaque concessions proposent plusieurs marques mais pas toujours les même.
Chaque marques proposent une gamme de modèle et chaque concessions à un lot de véhicules d'occasions.
J'arrive donc à une bdd comme ça :

Lien pour voir en grand : Image de la bdd

Sur la page où j'affiche un modèle d'une marque, je souhaite aussi indiquer la liste de mes concessions qui font cette marque, ainsi que tous les véhicules d'occasions de ce modèle.

La pratique :
J'ai essayé d'utiliser les différentes possibilités que j'ai trouvé pour construire mes requêtes dans le modèle (hasMany,belongsTo,hasAndBelongsToMany, ...) mais j'ai une erreur qui me dit qu'il ne trouve pas de modele_id dans ma table concessions, ce qui est normal.
Du coup j'ai construit ma requête dans le controller comme cela :

<?php 
class JfcmodelesController extends AppController {
    function index() {
        $d'modeles'] = $this->Jfcmodele->find('first',array(
            'conditions' => array(
                'Jfcmodele.slug' => $this->params'modele']
            )
        ));
        $this->loadModel('Concession');
        $d'concessions'] = $this->Concession->find('all', array(
            'joins' => array(
                array(
                    'alias' => 'Concession_Marque',
                    'table' => 'concession_marques',
                    'type' => 'LEFT',
                    'conditions' => 'Concession.id = Concession_Marque.concession_id'
                )
            ),
            'conditions' => array(
                'Concession_Marque.marque_id' => $d'modeles']'Jfcmodele']'marque_id']
            )
        ));
        $this->loadModel('Vehicule');
        $d'occasions'] = $this->Vehicule->find('all', array(
            'limit' => 5, 
            'order' => 'Vehicule.prix DESC',
            'fields' => array('Marque.name','Vehicule.prix','Jfcmodele.name','Media_Vehicule.url','Media_Vehicule.name'),
            'joins' => array(
                array(
                    'alias' => 'Marque',
                    'table' => 'marques',
                    'type' => 'LEFT',
                    'conditions' => 'Marque.id = Vehicule.marque_id'
                ),
                array(
                    'alias' => 'Jfcmodele',
                    'table' => 'jfcmodeles',
                    'type' => 'LEFT',
                    'conditions' => 'Jfcmodele.id = Vehicule.Jfcmodele_id'
                ),
                array(
                    'alias' => 'Media_Vehicule',
                    'table' => 'media_vehicules',
                    'type' => 'LEFT',
                    'conditions' => 'Media_Vehicule.vehicule_id = Vehicule.id'
                )
            ),
            'conditions' => array(
                'Jfcmodele.slug' => $this->params'modele'],
                'vond'  => 'VO'
            )
        ));
        $this->set($d);
    }
}
?>

Est ce la seule solution ? je me dis que ce n'est pas la façon la plus propre pour coder sur cakePhp.
Et surtout que cela ne vas pas m'aider pour utiliser plus tard les beforSave ou afterSave.

Bref qu'en pensez vous?

Merci

6 réponses


Aureroy
Réponse acceptée

C'est énorme, regarde le tutoriel sur le comportement containable de Grafikart et avec les liaisons (hasMany, belongsTo et HasAndBelongsToMany) tu vas faire moins de requête en ne récupérant que le nécéssaire (affiche les requête avec un

echo $this->element('sql_dump');

) dans ton défaut.ctp avec un debug à 2 dans ton core.

Avec ça tu vas pouvoir beaucoup mieux "construire" tes controllers et tes models.

gato
Auteur

Je vais regarder ça, merci.

Regarde du coté de $hasMany et $belongsTo.

gato
Auteur

Je viens de regarder les 2 vidéos que m'a conseillé Aureroy, il semble que le container serve à résoudre mon problème. Faut que je mette les mains dans le cambouis pour bien comprendre, mais ça à l'air d'être ça.

Merci à vous 2 pour vos réponses.

gato
Auteur

Alors, effectivement j'arrive maintenant via le "containable" à faire ma requête et récupérer mes infos plus ou moins comme avant.
Au lieu d'avoir une grosse requete, j'en ai une douzaine.

Sachant que mes marques, mes modèles, et les concessions qui font ces marques ne changeront presque jamais. Seul la liste des véhicules d'occasion que j'affiche sur ces pages va changer.
Si j'ai bien compris le tutoriel de GrafikArt, on peut mettre toute une vue en cache et via la balise html <!-- nocache -->, exclure une partie de la vue pour pouvoir y exécuter du code.

Dans cette page en cache, il n'y a pas d'appel sql ce qui est parfait, mais si j'utilise un <!-- nocache --> pour afficher mes véhicules d'occasion, cakePhp va t'il faire toute la série de requête ou seulement celle qui correspondent à mes véhicules.
Si il refait toutes les requêtes, n'est ce pas mieux de faire 2 "find" ?

gato
Auteur

Au final, après un peu de lecture du book, on ne peut pas mettre en cache une boucle qui fait appel à une requête. Ça semble logique après coup, ça annulerait presque tous les bénéfices du cache.

pour info, j'arrive à un controller qui ressemble à ça :

$d'modeles'] = $this->Jfcmodele->find('first',array(
    'conditions' => array(
        'Jfcmodele.slug' => $this->params'modele']
    ),
    'contain' => array(
        'Marque' => array(
            'fields' => array('id','name','slug'),
            'Concession' => array(
                'fields' => array('id','name')
            )
        )               
    )
));
$this->loadModel('Vehicule');
$d'vehicule'] = $this->Vehicule->find('all',array(
    'contain' => array(
        'Mediavehicule',
        'Marque' => array(
            'fields' => array('id','name')
        ),
        'Jfcmodele' => array(
            'fields' => array('id','name')
        )
    ),
    'limit' => 5,
    'order' => 'Vehicule.prix DESC',
    'fields' => array('id','prix'),
    'conditions' => array(
        'vond'  => 'VO',
        'Vehicule.jfcmodele_id' => $d'modeles']'Jfcmodele']'id']
    )
));

J'ai les même info mais c'est codé dans la norme de cakePhp, enfin je pense.
Merci Aureroy pour m'avoir mis sur cette piste.