CakePHP 2.x深度关联的可包含行为条件

eaj*_*eaj 4 cakephp

我有这样的模型关系:

Project的hasMany SubProject的hasManyItem

我想设置一个containable数组,以便我可以找到Item属于某个特定的所有s Project,并对结果进行分页.所以,在我的ItemsController身上:

public $paginate = array(
  'Item' => array(
    'limit' => 10,
    'order' => array('
      'Item.create_time' => 'desc'
    ),
    'contain' => array(
      'SubProject' => array(
        'Project'
      )
    )
  )
);
Run Code Online (Sandbox Code Playgroud)

在某个地方,显然,我需要设置一个类似的条件"SubProject.project_id = $pid",但我尝试过的任何事情都不会产生正确的结果.我能管理的最好的结果是这样的:

Array
(
[0] => Array
    (
        [Item] => Array
            (
                [id] => 13
                [file_name] => foo.tar.gz
                .... other keys ...
                [create_time] => 2013-01-23 14:59:49
                [subProject_id] => 4
            )

        [SubProject] => Array
            (
                [id] => 4
                [name] => foo
                [project_id] => 2
                ..... other keys ....
                [Project] => Array
                    (
                    )

            )

    )
 [1] => Array
 .....
Run Code Online (Sandbox Code Playgroud)

编辑:正确地省略了不匹配的项目记录; 我想跳过没有匹配项目记录的任何项目记录.

我已经想到手动指定我的联接,但我觉得这不应该是必要的.

看起来这应该是显而易见的,但唉,解决方案让我感到安慰.

eaj*_*eaj 9

我最终解决了这个问题,所以我想我会解释我做了什么,希望它可以帮助别人.

在阅读了Mark Story的博客文章(这是从1.2时开始但仍然相关)之后,我决定要做的是在我的Item模型中创建一个自定义查找类型,直接绑定Project模型.这给出了Containable可以正确过滤的第一级关联.

因此,在Items模型中,我有类似下面的内容(请参阅有关自定义查找类型的文档).

public $findMethods = array('byProject' => true);

public function _findByProject($state, $query, $results=array()) {
    if ($state == 'before') {
        $this->bindModel(array(
            'hasOne' => array(
                'Project' => array(
                    'foreignKey' => false,
                    'conditions' => array('Project.id = SubProject.project_id')
                )
            )
        ));
        return $query;
    }
    return $results;
}
Run Code Online (Sandbox Code Playgroud)

请注意,设置foreignKey为false是必要的,以防止CakePHP尝试自动使用不存在的数据库密钥.在ItemsController中,分页选项现在如下所示:

public $paginate = array(
    'Item' => array(
        'findType' => 'byProject',
        'limit' => 10,
        'order' => array(
            'Item.create_time' => 'desc'
        ),
        'contain' => array(
            'SubProject',
            'Project'
        ),
        'conditions' => array('Project.id' = $pid)
    ),
);
Run Code Online (Sandbox Code Playgroud)

... $pid要显示的项目的ID 在哪里.在视图代码中进行了一些小的调整,以适应稍微不同的结果数组结构,并且我已经完成了设置.