我有这样的模型关系:
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)
编辑:正确地省略了不匹配的项目记录; 我想跳过没有匹配项目记录的任何项目记录.
我已经想到手动指定我的联接,但我觉得这不应该是必要的.
看起来这应该是显而易见的,但唉,解决方案让我感到安慰.
我最终解决了这个问题,所以我想我会解释我做了什么,希望它可以帮助别人.
在阅读了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 在哪里.在视图代码中进行了一些小的调整,以适应稍微不同的结果数组结构,并且我已经完成了设置.