2008-09-22 57 views
0

我有一个n...n结构两个表,makesmodels。到目前为止没有问题。如何在CakePHP中的第三个n..n(hasAndBelongsToMany)关系中连接两个表?

在第三个表(products),如:

id 
make_id 
model_id 
... 

我的问题是创建包含一个specifi make产品我ProductsController内部的观点只是我们做的模型:

我认为这可以工作:

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 

所以,如果我想使用list传递给我的视图中创建单选按钮我会做一个foreach()make阵列找到所有车型的标题,并创建一个新的数组,并通过$this->set()发送到视图。

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

有没有更简单的方法来获取列表而不强调make阵列。在我的应用程序中开发这样的场景将是一个普遍的任务。

在此先感谢您的任何提示!

回答

1

这里是我的提示:在尝试使用Cake库重新构建之前,尝试使用常规SQL编写查询。实质上,你正在做很多额外的工作,数据库可以为你做。 你的方法(作秀 - 不好SQL):

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

你没有考虑到的关系(除非蛋糕自动神奇地理解表之间的关系)

你可能寻找将这些东西连接在一起的东西:

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

希望这是一个正确方向的微调?

0

所有不同的Make-> find()和Model-> find()调用都是完全独立的。即使Make-> Model-> find()与Model-> find()相同,Cake也不会以任何方式记住或考虑您在其他模型中已经找到的内容。您要查找的是一样的东西:

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

好吧,我知道了,但是,我有品牌和型号之间的n ... N的关系。请问我写的所有n ... N条件下,像makes.id = make_models.make_id和make_models.model_id = models.id ......等等......我的意思是...有一个HABTM ......可我用那个? – 2008-09-22 13:55:12

0

退房设置::提取物()用于从$这个 - > Make->找到()

结果得到的模型标题的列表方法
1

从您的评论中判断,您所要求的是如何从某个模型中获得结果,其中的条件在HABTM相关模型中。即你通常会用原始SQL中的JOIN语句来做这件事。
目前这是Cake的几个弱点之一。有不同的策略来解决这个问题。

  • 有相关的B型回归模型A可能的候选人的所有ID,然后做了第二次查询的型号AIE:

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

    现在你有属于MODELA的所有ID数组到符合您的条件的ModelB,您可以使用Set :: extract()轻松提取这些条件。基本上相当于SELECT model_a.id FROM model_b JOIN model_a WHERE model_b.field = xxx。接下来,您找MODELA:

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

    这将产生SELECT model_a.* FROM model_a WHERE id IN (1, 2, 3),这是做JOIN语句的一种迂回的方式。如果你需要一个以上的相关模型的条件下,重复,直到你有MODELA所有的ID,SQL将使用所有的IDS(WHERE id IN (1, 2, 3) AND id IN (3, 4, 5))的交叉点。

  • 如果你只需要在ModelB一个条件,但要检索MODELA,只需搜索ModelB。 Cake会为你自动检索相关的ModelAs(见上文)。你可能需要再次Set :: extract(),但这可能已经足够了。

  • 您可以用上面的方法,并与Containable behaviour结合起来,并得到了结果的更多控制。

  • 如果一切都失败或上述方法产生的开销过大,您仍然可以使用$this->Model->query()编写自己的原始SQL。如果你坚持Cake SQL标准(正确命名表FROM model_as AS ModelA)Cake仍然会正确地后处理你的结果。

希望这会让您朝正确的方向发展。

相关问题