Comment puis-je joindre deux tables dans une troisième relation n..n (hasAndBelongsToMany) dans CakePHP?

StackOverflow https://stackoverflow.com/questions/112730

Question

J'ai une structure n ... n pour deux tables, crée et modèles . . Jusqu'à présent, pas de problème.

Dans une troisième table ( produits ) telle que:

id
make_id
model_id
...

Mon problème est de créer une vue pour les produits d'un constructeur spécifié dans mon ProductsController contenant uniquement des modèles de modèle:

Je pensais que cela pourrait fonctionner:

var $uses = array('Make', 'Model');

$this->Make->id = 5; // My Make

$this->Make->find(); // Returns only the make I want with it's Models (HABTM)
$this->Model->find('list'); // Returns ALL models
$this->Make->Model->find('list'); // Returns ALL models

Donc, si je veux utiliser la liste pour passer à mon écran afin de créer des boutons radio, je devrai faire un pour chaque () dans mon < code> make pour rechercher tous les modèles de titres, créer un nouveau tableau et l'envoyer à la vue via $ this- > set () .

$makeArray = $this->Make->find();
foreach ($makeArray['Model'] as $model) {
    $modelList[] = $model['title'];
}
$this->set('models', $models)

Existe-t-il un moyen plus simple d'obtenir cette liste sans insister sur le tableau make . Ce sera une tâche courante de développer de tels scénarios dans mes applications.

Merci d'avance pour tout indice!

Était-ce utile?

La solution 5

La solution peut être obtenue en utilisant l'opération avec dans le tableau habtm du modèle.

En utilisant avec , vous pouvez définir le " milieu " table comme:

$habtm = " ...
  'with' => 'MakeModel',
   ... ";

Et en interne, dans le modèle ou le contrôleur, vous pouvez émettre des conditions pour la méthode find .

Voir: http: /www.cricava.com/blogs/index.php?blog=6&title=modelizing_habtm_join_tables_in_cakephp_&more=1&c=1&tb=1&pb=1

Autres conseils

Voici mon conseil: essayez d’écrire votre requête en SQL normal avant d’essayer de reconstruire à l’aide de la bibliothèque Cake. En gros, vous faites beaucoup de travail supplémentaire que la base de données peut faire pour vous. Votre approche (juste pour montrer - pas bon SQL):

SELECT * FROM makes, models, products WHERE make_id = 5

Vous ne prenez pas en compte les relations (à moins que Cake comprenne automatiquement les relations des tables)

Vous recherchez probablement quelque chose qui unit ces éléments:

SELECT models.title FROM models 
INNER JOIN products 
  ON products.model_id = models.model_id 
  AND products.make_id = 5

Espérons que ceci est un coup de pouce dans la bonne direction?

À en juger par votre commentaire, vous demandez comment obtenir les résultats d’un modèle donné, lorsque la condition se trouve dans un modèle lié à HABTM. C'est à dire. Ce que vous feriez habituellement avec une instruction JOIN en SQL brut.
Actuellement, c'est l'un des rares points faibles de Cake. Il existe différentes stratégies pour y faire face.

  • Demandez au modèle B associé de renvoyer tous les identifiants des candidats possibles pour le modèle A, puis effectuez une seconde requête sur le modèle A. I.e.:

    $this->ModelB->find('first', array('conditions' => array('field' => $condition)));
    array(
        ['ModelB'] => array( ... ),
        ['ModelA'] => array(
            [0] => array(
                'id' => 1
            )
    )
    

    Vous avez maintenant un tableau de tous les identifiants de ModelA appartenant à ModelB qui correspond à vos conditions, que vous pouvez facilement extraire à l’aide de Set :: extract (). En gros, l'équivalent de SELECT modèle_a.id FROM modèle_b JOIN modèle_a WHERE modèle_b.field = xxx . Ensuite, vous recherchez ModelA:

     $this->ModelA->find('all', array('conditions' => array('id' => $model_a_ids)));
    

    Cela produira SELECT modèle_a. * FROM modèle_a WHERE id IN (1, 2, 3) , qui est un moyen détourné de faire l'instruction JOIN. Si vous avez besoin de conditions pour plusieurs modèles associés, répétez l'opération jusqu'à ce que tous les identifiants de ModelA soient disponibles. SQL utilisera l'intersection de tous les identifiants ( WHERE id IN (1, 2, 3) ET id IN (3, 4). , 5) ).

  • Si vous n'avez besoin que d'une condition sur ModelB mais souhaitez récupérer ModelA, recherchez simplement ModelB. Cake récupérera automatiquement les ModelAs associés pour vous (voir ci-dessus). Vous devrez peut-être à nouveau Set :: extract (), mais cela pourrait déjà suffire.

  • Vous pouvez utiliser la méthode ci-dessus et la combiner avec le Comportement conteneurable pour avoir plus de contrôle sur les résultats.

  • Si tout le reste échoue ou si les méthodes ci-dessus génèrent simplement trop de temps système, vous pouvez toujours écrire votre propre code SQL brut avec $ this- > Model- > query () . Si vous vous en tenez aux standards de Cake SQL (nommer correctement les tables avec FROM modèle_as AS ModelA ), Cake post-traitera toujours correctement vos résultats.

J'espère que cela vous envoie dans la bonne direction.

Tous vos différents appels Make- > find () et Model- > find () sont complètement indépendants les uns des autres. Même Make-> Model- & find () est identique à Model- & find (), Cake ne se souvient en aucun cas de ce que vous avez déjà trouvé dans d'autres modèles. Ce que vous cherchez, c'est quelque chose comme:

$this->Product->find('all', array('conditions' => array('make_id' => 5)));

Découvrez la méthode Set :: extract () pour obtenir une liste des titres de modèle à partir des résultats de $ this- > Make- > find ()

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top