我有这样的模特关系:
Project
hasMany SubProject
hasMany Item
我想设置一个containable
数组,以便找到属于特定Item
的所有Project
,并对结果进行分页。所以,在ItemsController
我有:
public $paginate = array(
'Item' => array(
'limit' => 10,
'order' => array('
'Item.create_time' => 'desc'
),
'contain' => array(
'SubProject' => array(
'Project'
)
)
)
);
在某个地方,显然,我需要设置一个像"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
.....
编辑:正确地省略了不匹配的项目记录;我想跳过没有匹配项目记录的任何项目记录。
我已经想到了manually specify my joins,但我觉得这不应该是必要的。
看起来这应该是显而易见的,但唉,解决方案让我感到厌烦。
答案 0 :(得分:9)
我最终解决了这个问题,所以我想我会解释我做了什么,希望它可以帮助别人。
在阅读this blog post by Mark Story之后(从1.2时开始,但仍然相关)我决定要做的事情是在我的Item模型中创建一个自定义查找类型,直接绑定Project模型。这给出了Containable可以正确过滤的第一级关联。
因此,在Items模型中,我有类似以下内容(请参阅自定义查找类型的the documentation)。
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;
}
请注意,将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)
),
);
...其中$pid
是要显示的项目的ID。在视图代码中进行了一些小的调整,以适应稍微不同的结果数组结构,并且我已经完成了设置。
答案 1 :(得分:1)
编辑===============
public $paginate = array(
'limit' => 10,
'order' => 'Item.create_time DESC', //'order' => array(''Item.create_time' => 'desc'),
'contain' => array(
'SubProject' => array(
'Project' => array(
'conditions' => array(
'id' => $project_id // Passed parameter
)
)
)
)
);
=============================================== ==
您是否尝试使用conditions
,如下所示?另外,我没有按照你的方式编写代码的“顺序”部分。
public $paginate = array(
'Item' => array(
'limit' => 10,
'order' => 'Item.create_time DESC', //'order' => array(''Item.create_time' => 'desc'),
'contain' => array(
'SubProject' => array(
'Project' => array(
'conditions' => array(
'id' => $project_id // Passed parameter
)
)
)
)
)
);