你如何在CakePHP 3中对子查询进行分页?

时间:2017-04-19 08:54:49

标签: php cakephp pagination

我有一个CakePHP 3应用程序,它有2个模型,UrlsDownloads。这些模型相关联,因此URL可能有多个下载(Cake术语中的Urls hasMany Downloads)。

当我执行此类查询时,它将从Urls表和所有关联的Downloads返回1行:

// This is in a view() method
$query = $this->Urls->find()->contain(['Downloads' => ['sort' => ['Downloads.created' => 'DESC'] ] ])->where(['id' => $id]);

我想对Downloads列表进行分页,但无法看到如何执行此操作。我已经看了https://book.cakephp.org/3.0/en/controllers/components/pagination.html,但我唯一能找到的就是:

public function initialize()
{
    parent::initialize();
    $this->loadComponent('Paginator');
}

// In my view() method
$this->paginate = [
    'contain' => ['Downloads']
];

$query = $this->Urls->find()->contain(['Downloads' => ['sort' => ['Downloads.created' => 'DESC'] ] ])->where(['id' => $id])->paginate();

但它只是错误说 未知方法"分页"

3 个答案:

答案 0 :(得分:0)

由于您只展示了一个网址,因此您可以进行两次查询。

检索网址的一个查询(没有下载)

$url = $this->Urls->get($id);

第二个检索(和分页!)下载

$downloads = $this->Urls->Downloads->find()
    ->sort(['created' => 'DESC'])
    ->where(['url_id' => $id]);

$downloads = $this->paginate($downloads) 

答案 1 :(得分:0)

由于下载属于Urls,您可以采取相反的行动,如下所示:

$downloads = $this->Urls->Downloads->find()
    ->contain('Urls')
    ->where(['url_id' => $id])
    ->order(['created' => 'DESC']);

答案 2 :(得分:0)

您的错误是因为paginate()不是表类的方法,而是在表对象上调用它,因此它是未知的。您需要在Controller对象上调用它: -

$this->paginate();

由于paginate是一种控制器方法,因此在您的示例中尝试检索Url时,无法将其作为查询的一部分进行调用。这意味着您需要执行两个查询,但如果您包含下载,这就是CakePHP会失败的。例如: -

$this->Urls->get($id, ['contain' => 'Downloads']);

这实际上导致了以下两个查询,因为使用JOIN无法在SQL中完成: -

$this->Urls->get($id);
$this->Urls->Downloads->find('all')->where(['url_id' => $id])->all();

所以,你需要先得到Url: -

$url = $this->Urls->get($id);

然后将您希望将下载的查询查询传递到您的分页方法的下载分页: -

$query = $this->Urls->Downloads->find()
    ->sort(['created' => 'DESC'])
    ->where(['url_id' => $id]);
$downloads = $this->paginate($query);