如何在 CakePHP 中加入第三个 n..n (hasAndBelongsToMany) 关系中的两个表?

发布于 2024-07-06 21:37:48 字数 1150 浏览 8 评论 0原文

我有两个表的 n...n 结构,makesmodels。 到目前为止没有问题。

在第三个表(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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

爱殇璃 2024-07-13 21:37:48

这是我的提示:在尝试使用 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

希望这是朝着正确的方向推动?

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):

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

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:

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

Hopefully this is a nudge in the right direction?

魔法少女 2024-07-13 21:37:48

从您的评论来看,您要求的是如何从某个模型中获取结果,其中条件位于 HABTM 相关模型中。 即您通常使用原始 SQL 中的 JOIN 语句执行的操作。
目前这是 Cake 的少数弱点之一。 有不同的策略来处理这个问题。

  • 让相关模型 B 返回模型 A 的所有可能候选者的 ID,然后对模型 AIe 进行第二次查询:

    $this->ModelB->find('first', array('conditions' => array('field' => $condition))); 
      大批( 
          ['模型B'] =>   大批( ... ), 
          ['模型A'] =>   大批( 
              [0] =>   大批( 
                  '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 语句的迂回方式。 如果您需要多个相关模型的条件,请重复此操作,直到获得 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.:

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

    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:

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

    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 with FROM model_as AS ModelA) Cake will still post-process your results correctly.

Hope this sends you in the right direction.

魂牵梦绕锁你心扉 2024-07-13 21:37:48

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

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

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:

$this->Product->find('all', array('conditions' => array('make_id' => 5)));
依 靠 2024-07-13 21:37:48

查看 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()

天生の放荡 2024-07-13 21:37:48

该解决方案可以通过在模型上使用 habtm 数组中的 with 操作来实现。

使用 with 您可以定义“中间”表,如下所示:

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

在模型或控制器内部,您可以向 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:

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文