在 CakePHP 中从模型中分页

Posted

技术标签:

【中文标题】在 CakePHP 中从模型中分页【英文标题】:Paginate from within a model in CakePHP 【发布时间】:2011-09-24 00:23:58 【问题描述】:

我的 Event 模型中有一个名为 getEvents 的函数 - 您可以通过限制、startend 日期、fieldsevent types 和事件 subtypes

我读到paginate 可以接受我正在使用的所有参数,例如joinsconditionslimit...等等,就像普通的find 一样。

当我不尝试分页时,它会很好地返回数据。但是 - 我希望能够传递一个 paginate 变量来告诉它而不是这样做:

$this->recursive = -1;
$data = $this->find('all', $qOptions);

这样做:

$this->recursive = -1;
$data = $this->paginate($qOptions);

但是,当我尝试这样做时,它给了我很多错误。如果需要,我可以稍后指定错误 - 现在,我想我正在寻找 - 这是可以做到的吗?如果有,怎么做?

还有其他更好的方法来做这样的事情吗?我花了足够的时间让这个函数做我想做的事情,并允许所有选项通过......等等 - 如果我不能也将它用于分页,这似乎是一种浪费。但是 - 如果它不理想,我也可以听到。提前致谢。

编辑:

我在网上阅读其他内容说您不应该在模型中使用分页,因为它从 URL 变量中提取,这违背了 MVC 结构的目的。这是有道理的,但这是否意味着我必须在模型和控制器中编写相同的连接/查询?在每一个需要它的行动中?

【问题讨论】:

【参考方案1】:

我想出如何在我的模型中保留复杂的find 而不必在控制器中第二次重写它的方法是传递一个$paginate 布尔变量。

如果$paginate 为真,它只返回创建的选项,然后可以在控制器的分页中使用。如果它是假的(意味着我们不想分页),它返回实际的事件结果。到目前为止,这似乎是有效的。

在我的getEvents() 函数中(此方法在事件模型中)

    if($paginate) 
        return $qOpts; // Just return the options for the paginate in the controller to use
     else 
        $data = $this->find('all', $qOpts); // Return the actual events
        return $data;
    

然后,在我的事件/索引(事件控制器,索引操作 - 我知道我想要分页的地方):

$this->Event->recursive = -1; // (or set recursive = -1 in the appModel)
$opts['paginate'] = true;

$paginateOptions = $this->Event->getEvents($opts);

$this->paginate = $paginateOptions; // Set paginate options to just-returned options
$data = $this->paginate('Event'); // Get paginate results
$this->set('data', $data); // Set variable to hold paginated results in view

【讨论】:

【参考方案2】:

paginate() 模型方法接受与find() 相同的参数。具体来说,find() 想要一个选项数组,但 paginate() 想要单独传递每个选项。请参阅 Cakephp 书籍中的 Custom Query Pagination。

所以,而不是:

$data = $this->paginate($qOptions);

你想要这样的东西:

$data = $this->paginate($qOptions['conditions'], $qOptions['fields'], ...);

编辑

自定义模型分页不是您调用的函数。这是一个您需要实现的函数,将由 CakePHP 框架调用。在您问题的示例中,您尝试从模型中的某个位置手动调用 $this->paginate(...)。那是行不通的。而是这样做。

在您的模型中,实现 paginatepaginateCount 方法。

function paginate($conditions, $fields, ...)

    // return some data here based on the parameters passed


function paginateCount($conditions, ...)

    // return some rowcount here based off the passed parameters

然后,在您的控制器中,您可以使用标准的分页功能。

function index()

    $this->paginate = array('MyModel' => array(
        'conditions' => array(...),
        'fields' => array(...),
    ));

    $this->set('myobjects', $this->paginate('MyModel'));

现在,Controller::paginate() 函数将从Controller::paginate 参数中获取条件和其他数据,而不是将其传递给您的Model::find,而是将其传递给您的自定义Model::paginate()Model::paginateCount() 函数。因此,返回的数据基于您在这两种方法中所做的任何事情,而不是基于标准find()

【讨论】:

啊,好的-我会试试的,谢谢。那么-这方面的“规范”是什么?制作 2 个不同的功能,一个用于分页结果,一个用于不分页?或者如果它是分页与查找,则组合成一个并且只是构建不同的选项?任何想法/方向表示赞赏。这很可能是答案,并且会在早上尝试第一件事 - 谢谢agian! @Sander - 在尝试和尝试之后,我仍然无法让它工作。我什至无法让正常的$data = $this->paginate(); 在模型中工作。当我这样做时,我得到Warning (512): SQL Error: 1064: You have an error in your SQL syntax; check the manual that corresponds to your mysql server version for the right syntax to use near 'paginate'Query: paginate 该错误意味着您的模型没有paginate 方法。如果您阅读我发布的 CakePHP Book 链接,您会发现您需要自己实现 paginatepaginateCount 方法。当您创建这些时,您的控制器分页逻辑可以自动使用它们。 @sander - 您发布的链接实际上不起作用 - 介意为未来的用户修复它吗?谢谢! 我发现我认为您链接到的页面对我来说毫无意义。也许我遗漏了一些东西,但是 - 这似乎是 CakePHP 文档不佳的另一个例子。您是否有机会解释或展示我将如何使用与上述问题相关的示例?【参考方案3】:

你可以使用这个对我来说很好用的。

$condition="你的条件"; $this->分页=数组( 'fields' => 数组('AsinsBookhistory.id'、'AsinsBookhistory.reffer_id'、'AsinsBookhistory.ISBN'、'AsinsBookhistory.image'、'AsinsBookhistory.title'、'AsinsBookhistory.last_updatedtime')、 '条件' => $条件, '组' => 数组('AsinsBookhistory.ISBN'), '订单' => 数组('AsinsBookhistory.last_updatedtime' => 'desc') ); $this->set('lastvisitedbooks', $this->paginate('AsinsBookhistory'));

【讨论】:

【参考方案4】:

$paginate数组类似于Model->find('all')方法的参数,即:conditions、fields、order、limit、page、contain、joins、recursive .

所以你可以像这样定义你的条件:

var $paginate = array(
 'Event' => array (...)
 );

或者您也可以在您的操作中的 $paginate 数组中设置条件和其他键。

 $this->paginate = array(
 'conditions' => array(' ... '),
 'limit' => 10
 );
 $data = $this->paginate('Event');
http://book.cakephp.org/2.0/en/controllers.html http://book.cakephp.org/2.0/en/core-libraries/components/pagination.html

你在你的控制器中使用$name = 'Event' 吗?

如果我们不在 $this->paginate() 中提及模型名称,它将使用 $name 中提到的模型,否则在 var $uses 数组中查找模型名称(第一个)

例如var $uses = array('Model1','Model2'); // $name != 提到

n 你想对 Model2 进行分页,那么你必须在分页数组中指定 ModelName,如 $this->paginate('Model2') 否则将在分页中考虑 Model1。

【讨论】:

我的模型中确实有 $name = "Event" 并且我已经尝试设置您提到的选项,但它仍然尝试运行 sql 查询“分页”(这显然不是一个问题)。我认为这与上述桑德所说的有关,但无法弄清楚 Controller::paginate 参数、Controller::paginate() 方法和Model::paginate() 方法之间存在明显区别。戴夫问的是后者。你说的是前两者。

以上是关于在 CakePHP 中从模型中分页的主要内容,如果未能解决你的问题,请参考以下文章

PHP Cakephp:与当前和使用Containable分页不同的模型

Cakephp 分页按计算字段排序( COUNT )

cakephp从另一个表中将数据检索到控制器中

CakePHP 3.0 中虚拟字段/实体属性上的分页排序链接

使用 CakePHP 分页助手的引导分页

Cakephp分页问题