4

我有这样的模型关系:

Project有很多SubProject有很多Item

我想设置一个containable数组,以便我可以找到Item属于特定 s 的所有 s 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
 .....

编辑:忽略不匹配的项目记录是完全正确的;我想跳过没有匹配项目记录的任何项目记录。

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

看起来这应该是显而易见的,但是,解决方案让我无法理解。

4

2 回答 2

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;
}

请注意,必须设置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 在哪里。视图代码中的一些细微调整以适应略有不同的结果数组结构,我已经准备好了。

于 2013-01-26T23:30:04.637 回答
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
                    )
                )
            )
        )
     )
);
于 2013-01-25T19:53:17.547 回答