5

我有三个模型,UsersCommentsPages

用户 有很多 评论评论 属于 页面

所有模型都使用该containable行为,并且默认为recursive -1.

如果我在Comments上调用find()查询,其中包含请求包括Page模型的字段,这将使用单个查询正确返回结果,自动将Page表连接到用户。

如果我从User模型(包含 CommentComment.Page)调用一个类似的查询,结果是一个查询以获取Comments,然后是每个评论的查询以获取相关的Page

有没有办法配置模型以保持 JOIN 优化?我假设相关模型( Comments )上的 belongsTo 声明将遵循主机模型(Users)。

更新

我应该澄清一下,我的问题使用了我实际案例研究的简化版本。虽然我需要的最小解决方案将包括这个初始模型 hasMany Model belongsTo Model结构,但我也在寻找一个或多个额外的belongsTo 模型的解决方案(虽然我会自动使用 LEFT JOIN,因为这将是可行的)。

4

5 回答 5

2

嗯,这很有趣。这是一种应该在核心中实现的优化:)

无论如何,我认为您可以通过稍微不同地构建查询来获得相同的结果(可能格式不同):

$this->User->Comment->find('all', array(
  'conditions' => array(
    'Comment.user_id' => $userId
  ),
  'contain' => array(
    'User',
    'Page'
  )
));

通过从 Comment 模型中搜索,它应该使用两个左连接来连接数据,因为它们都是 1:1 的关系。注意:结果数组可能看起来与从 User 模型中搜索时略有不同。

于 2012-10-24T14:42:35.737 回答
1

我找到一个很好的方法是创建一个自定义的 find 方法

例如,我会在您的 User 模型中创建一个方法,例如调用_findUserComments(). 然后,您将在此方法中执行所有连接、包含等操作。然后在您的控制器中,无论您需要获取所有用户的评论,您都可以这样称呼它:

$this->User->find('UserComments', array(
    "conditions" => array(
        'User.id' => $userId
    )
));

我希望这有帮助。

于 2012-10-31T14:50:34.910 回答
1

如果模型定义如下:

  1. 评论模型属于页面和用户。
  2. 页面属于用户,有很多评论。
  3. 用户有很多页面和评论

下面的代码将返回一个连接查询:

$this->loadModel('Comment');
$this->Comment->Behaviors->attach('Containable');
$queryResult = $this->Comment->find('all', array(
   'contain' => array(
       'User', 
       'Page'
    )
));

下面的代码将返回两个查询。页面和用户加入一个查询并在另一个查询中加入所有评论

$this->loadModel('Page');
$this->Page->Behaviors->attach('Containable');
$queryResult = $this->Page->find('all', array(
   'contain' => array(
        'User', 
    'Comment'
   )
));

并且下面的代码将返回三个查询,每个模型一个:

$this->loadModel('User');
$this->User->Behaviors->attach('Containable');
$queryResult = $this->User->find('all', array(
    'contain' => array(
        'Page', 
        'Comment'
    )
));
于 2012-11-03T03:32:33.480 回答
1

那么您是否在问是否有更简单的方法来包含您的所有查询?如果您想包含当前控制器中的所有内容。您可以在 beforeFilter() 回调中执行包含,它将应用于该控制器中的所有查询。

于 2012-10-24T12:43:11.240 回答
1

我不太确定我是否理解您的问题,但我认为您对 Comment -> Page 链接的许多 sql 调用有疑问?如果这是正确的,那么

  1. 尝试可链接的行为,它可以减少 sql 调用,并且几乎可以像 contains 一样工作
  2. 或者,如果它几乎与您想要的数据相同,则在您对 hte sql 调用(例如 Comment-Model)感到满意的特定模型中创建一个函数,并通过用户模型调用它$this->Comment->myFindFct($params);

希望有帮助

编辑:我想到的一件事。您可以将关联数组中的连接类型更改为inner,这使得蛋糕也可以单独调用关联模型

于 2012-10-24T12:58:36.103 回答