在 CakePHP 中从模型中分页
Posted
技术标签:
【中文标题】在 CakePHP 中从模型中分页【英文标题】:Paginate from within a model in CakePHP 【发布时间】:2011-09-24 00:23:58 【问题描述】:我的 Event
模型中有一个名为 getEvents
的函数 - 您可以通过限制、start
和 end
日期、fields
、event
types
和事件 subtypes
。
我读到paginate
可以接受我正在使用的所有参数,例如joins
、conditions
、limit
...等等,就像普通的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(...)
。那是行不通的。而是这样做。
在您的模型中,实现 paginate
和 paginateCount
方法。
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 链接,您会发现您需要自己实现 paginate
和 paginateCount
方法。当您创建这些时,您的控制器分页逻辑可以自动使用它们。
@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分页不同的模型