如何在CakePHP中的第三个n..n(hasAndBelongsToMany)关系中联接两个表?
我有两个表," makes"和" models"的" n ... n"结构。到目前为止没有问题。
在第三个表格("产品")中,例如:
id make_id model_id ...
我的问题是在我的ProductsController
内为一个特定make
的产品创建一个视图,其中只包含make模型:
我认为这可以工作:
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传递到视图中以创建单选按钮,则必须在make数组中执行一次foreach()来查找所有模型标题并创建一个新数组并将其发送到通过$ this-> set()
查看。
$makeArray = $this->Make->find(); foreach ($makeArray['Model'] as $model) { $modelList[] = $model['title']; } $this->set('models', $models)
有没有更简单的方法来获得该列表而无需强调make
数组。在我的应用程序中开发此类方案将是一项常见的任务。
预先感谢任何提示!
解决方案
这是我的提示:在尝试使用Cake库进行重构之前,请尝试以常规SQL编写查询。本质上,我们正在做数据库可以为我们完成的许多额外工作。
方法(仅用于显示不好的SQL):
SELECT * FROM makes, models, products WHERE make_id = 5
我们无需考虑这些关系(除非Cake自动魔术地理解表的关系)
我们可能正在寻找将这些东西结合在一起的东西:
SELECT models.title FROM models INNER JOIN products ON products.model_id = models.model_id AND products.make_id = 5
希望这是朝正确方向前进的推动力?
我们所有不同的Make-> find()和Model-> find()调用都是完全独立的。即使Make-> Model-> find()与Model-> find()相同,Cake也不会记住或者考虑我们在其他模型中已经发现的内容。我们正在寻找的东西是这样的:
$this->Product->find('all', array('conditions' => array('make_id' => 5)));
检出Set :: extract()方法,从$ this-> Make-> find()的结果中获取模型标题的列表
从评论中判断,我们要查询的是如何从某个模型中获得结果,而该条件位于与HABTM相关的模型中。 IE。通常在原始SQL中使用JOIN语句执行的操作。
目前,这是Cake的少数弱点之一。有不同的策略可以解决这个问题。
- 让相关的模型B返回模型A的所有可能候选者的ID,然后对模型A进行第二次查询。
$this->ModelB->find('first', array('conditions' => array('field' => $condition))); array( ['ModelB'] => array( ... ), ['ModelA'] => array( [0] => array( 'id' => 1 ) )
现在,我们拥有一个符合我们条件的,属于ModelB的所有ModelA的ID数组,我们可以使用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语句的一种round回方式。如果我们需要多个以上相关模型的条件,请重复执行直到获得ModelA的所有ID,SQL将使用所有ID的交集(ID IN(1、2、3)和ID IN(3、4、5) )
)。
- 如果我们只需要ModelB上的一个条件,但想要检索ModelA,则只需搜索ModelB。 Cake将自动为我们检索相关的ModelA(请参见上文)。我们可能需要再次Set :: extract(),但这可能已经足够了。
- 我们可以使用上述方法,并将其与Containable行为结合使用,以更好地控制结果。
- 如果所有其他方法均失败,或者上述方法仅产生过多的开销,我们仍然可以使用$ this-> Model-> query()编写自己的原始SQL。如果我们遵循Cake SQL标准(使用
FROM model_as AS ModelA
正确命名表),Cake仍将正确地对结果进行后处理。
希望这能给我们正确的方向。
解决方案可以通过在模型的habtm数组中使用" with"操作来实现。
使用with
,我们可以定义"中间"表,如下所示:
$habtm = " ... 'with' => 'MakeModel', ... ";
在内部,我们可以在Model或者Controller中向条件find发出条件。
参见:http://www.cricava.com/blogs/index.php?blog=6&title=modelizing_habtm_join_tables_in_cakephp_&more=1&c=1&tb=1&pb=1