如何在 CakePHP 中加入第三个 n..n (hasAndBelongsToMany) 关系中的两个表?
我有两个表的 n...n
结构,makes
和 models
。 到目前为止没有问题。
在第三个表(products
)中,例如:
id
make_id
model_id
...
我的问题是为内部的一个特定 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
传递到我的视图来创建单选按钮,我将不得不在我的 make
数组中执行 foreach()
来查找所有模型标题并创建一个新数组并通过 $ 发送到视图this->set()
。
$makeArray = $this->Make->find();
foreach ($makeArray['Model'] as $model) {
$modelList[] = $model['title'];
}
$this->set('models', $models)
有没有更简单的方法来获取该列表而不用强调 make
数组。 在我的应用程序中开发此类场景将是一项常见任务。
预先感谢您的任何提示!
I have a n...n
structure for two tables, makes
and models
. So far no problem.
In a third table (products
) like:
id
make_id
model_id
...
My problem is creating a view for products of one specifi make
inside my ProductsController
containing just that's make models:
I thought this could work:
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
So, If I want to use the list
to pass to my view to create radio buttons I will have to do a foreach()
in my make
array to find all models titles and create a new array and send to the view via $this->set()
.
$makeArray = $this->Make->find();
foreach ($makeArray['Model'] as $model) {
$modelList[] = $model['title'];
}
$this->set('models', $models)
Is there any easier way to get that list without stressing the make
Array. It will be a commom task to develops such scenarios in my application(s).
Thanks in advance for any hint!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这是我的提示:在尝试使用 Cake 库进行重建之前,尝试用常规 SQL 编写查询。 本质上,您正在做数据库可以为您做的许多额外工作。
你的方法(只是为了展示 - 不是好的 SQL):
你没有考虑关系(除非 Cake 自动神奇地理解表的关系)
你可能正在寻找将这些东西连接在一起的东西:
希望这是朝着正确的方向推动?
Here's my hint: Try getting your query written in regular SQL before trying to reconstruct using the Cake library. In essence you're doing a lot of extra work that the DB can do for you.
Your approach (just for show - not good SQL):
You're not taking into consideration the relationships (unless Cake auto-magically understands the relationships of the tables)
You're probably looking for something that joins these things together:
Hopefully this is a nudge in the right direction?
从您的评论来看,您要求的是如何从某个模型中获取结果,其中条件位于 HABTM 相关模型中。 即您通常使用原始 SQL 中的 JOIN 语句执行的操作。
目前这是 Cake 的少数弱点之一。 有不同的策略来处理这个问题。
让相关模型 B 返回模型 A 的所有可能候选者的 ID,然后对模型 AIe 进行第二次查询:
现在您拥有了属于 ModelB 且符合您的条件的 ModelA 的所有 id 的数组,您可以使用 Set::extract() 轻松提取该数组。 基本上相当于 SELECT model_a.id FROM model_b JOIN model_a WHERE model_b.field = xxx。 接下来寻找 ModelA:
这将生成
SELECT model_a.* FROM model_a WHERE id IN (1, 2, 3)
,这是执行 JOIN 语句的迂回方式。 如果您需要多个相关模型的条件,请重复此操作,直到获得 ModelA 的所有 id,SQL 将使用所有 id 的交集 (WHERE id IN (1, 2, 3) AND id IN (3, 4 , 5)
).如果您只需要 ModelB 上的一个条件,但想要检索 ModelA,则只需搜索 ModelB。 Cake会自动为你检索相关的ModelAs(见上文)。 您可能需要再次 Set::extract() 它们,但这可能已经足够了。
您可以使用上述方法并将其与 Containable 行为 结合起来,得到更好地控制结果。
如果所有其他方法都失败或者上述方法只是产生太多开销,您仍然可以使用
$this->Model->query()
编写自己的原始 SQL。 如果您坚持 Cake SQL 标准(使用FROM model_as AS ModelA
正确命名表),Cake 仍将正确地后处理您的结果。希望这能让您朝着正确的方向前进。
Judging from your comment, what you're asking for is how to get results from a certain model, where the condition is in a HABTM related model. I.e. something you'd usually do with a JOIN statement in raw SQL.
Currently that's one of the few weak points of Cake. There are different strategies to deal with that.
Have the related model B return all ids of possible candidates for Model A, then do a second query on Model A. I.e.:
Now you have an array of all ids of ModelA that belong to ModelB that matches your conditions, which you can easily extract using Set::extract(). Basically the equivalent of
SELECT model_a.id FROM model_b JOIN model_a WHERE model_b.field = xxx
. Next you look for ModelA:That will produce
SELECT model_a.* FROM model_a WHERE id IN (1, 2, 3)
, which is a roundabout way of doing the JOIN statement. If you need conditions on more than one related model, repeat until you have all the ids for ModelA, SQL will use the intersection of all ids (WHERE id IN (1, 2, 3) AND id IN (3, 4, 5)
).If you only need one condition on ModelB but want to retrieve ModelA, just search for ModelB. Cake will automatically retrieve related ModelAs for you (see above). You might need to Set::extract() them again, but that might already be sufficient.
You can use the above method and combine it with the Containable behaviour to get more control over the results.
If all else fails or the above methods simply produce too much overhead, you can still write your own raw SQL with
$this->Model->query()
. If you stick to the Cake SQL standards (naming tables correctly withFROM model_as AS ModelA
) Cake will still post-process your results correctly.Hope this sends you in the right direction.
所有不同的 Make->find() 和 Model->find() 调用都是完全独立的。 即使 Make->Model->find() 与 Model->find() 相同,Cake 也不会以任何方式记住或考虑您已经在其他模型中找到的内容。 你正在寻找的是这样的:
All your different Make->find() and Model->find() calls are completely independent of each other. Even Make->Model->find() is the same as Model->find(), Cake does not in any way remember or take into account what you have already found in other models. What you're looking for is something like:
查看 Set::extract() 方法,用于从 $this->Make->find() 的结果中获取模型标题列表
Check out the Set::extract() method for getting a list of model titles from the results of $this->Make->find()
该解决方案可以通过在模型上使用 habtm 数组中的
with
操作来实现。使用
with
您可以定义“中间”表,如下所示:在模型或控制器内部,您可以向
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
The solution can be achieved with the use of the
with
operation in habtm array on the model.Using
with
you can define the "middle" table like:And internally, in the Model or Controller, you can issue conditions to the
find
method.See: http://www.cricava.com/blogs/index.php?blog=6&title=modelizing_habtm_join_tables_in_cakephp_&more=1&c=1&tb=1&pb=1