PageRenderTime 26ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/en/controllers/pagination.rst

https://github.com/cakephp/docs
ReStructuredText | 294 lines | 235 code | 59 blank | 0 comment | 0 complexity | c0d0115e2a8d177654fc66ebb871313c MD5 | raw file
  1. Pagination
  2. ##########
  3. One of the main obstacles of creating flexible and user-friendly web
  4. applications is designing an intuitive user interface. Many applications tend to
  5. grow in size and complexity quickly, and designers and programmers alike find
  6. they are unable to cope with displaying hundreds or thousands of records.
  7. Refactoring takes time, and performance and user satisfaction can suffer.
  8. Displaying a reasonable number of records per page has always been a critical
  9. part of every application and used to cause many headaches for developers.
  10. CakePHP eases the burden on the developer by providing a terse way to
  11. paginate data.
  12. Pagination in CakePHP controllers is done through the ``paginate()`` method. You
  13. then use :php:class:`~Cake\\View\\Helper\\PaginatorHelper` in your view templates
  14. to generate pagination controls.
  15. Basic Usage
  16. ===========
  17. You can call ``paginate()`` using an ORM table instance or ``Query`` object::
  18. public function index()
  19. {
  20. // Paginate the ORM table.
  21. $this->set('articles', $this->paginate($this->Articles));
  22. // Paginate a partially completed query
  23. $query = $this->Articles->find('published');
  24. $this->set('articles', $this->paginate($query));
  25. }
  26. Advanced Usage
  27. ==============
  28. More complex use cases are supported by configuring the ``$paginate``
  29. controller property or as the ``$settings`` argument to ``paginate()``. These
  30. conditions serve as the basis for you pagination queries. They are augmented
  31. by the ``sort``, ``direction``, ``limit``, and ``page`` parameters passed in
  32. from the URL::
  33. class ArticlesController extends AppController
  34. {
  35. public $paginate = [
  36. 'limit' => 25,
  37. 'order' => [
  38. 'Articles.title' => 'asc'
  39. ]
  40. ];
  41. }
  42. .. tip::
  43. Default ``order`` options must be defined as an array.
  44. While you can include any of the options supported by
  45. :php:meth:`~Cake\\ORM\\Table::find()` such as ``fields`` in your pagination
  46. settings. It is cleaner and simpler to bundle your pagination options into
  47. a :ref:`custom-find-methods`. You can use your finder in pagination by using the
  48. ``finder`` option::
  49. class ArticlesController extends AppController
  50. {
  51. public $paginate = [
  52. 'finder' => 'published',
  53. ];
  54. }
  55. If your finder method requires additional options you can pass those
  56. as values for the finder::
  57. class ArticlesController extends AppController
  58. {
  59. // find articles by tag
  60. public function tags()
  61. {
  62. $tags = $this->request->getParam('pass');
  63. $customFinderOptions = [
  64. 'tags' => $tags
  65. ];
  66. // We're using the $settings argument to paginate() here.
  67. // But the same structure could be used in $this->paginate
  68. //
  69. // Our custom finder is called findTagged inside ArticlesTable.php
  70. // which is why we're using `tagged` as the key.
  71. // Our finder should look like:
  72. // public function findTagged(Query $query, array $options) {
  73. $settings = [
  74. 'finder' => [
  75. 'tagged' => $customFinderOptions
  76. ]
  77. ];
  78. $articles = $this->paginate($this->Articles, $settings);
  79. $this->set(compact('articles', 'tags'));
  80. }
  81. }
  82. In addition to defining general pagination values, you can define more than one
  83. set of pagination defaults in the controller. The name of each model can be used
  84. as a key in the ``$paginate`` property::
  85. class ArticlesController extends AppController
  86. {
  87. public $paginate = [
  88. 'Articles' => [],
  89. 'Authors' => [],
  90. ];
  91. }
  92. The values of the ``Articles`` and ``Authors`` keys could contain all the
  93. properties that a basic ``$paginate`` array would.
  94. Once you have used ``paginate()`` to create results. The controller's request
  95. will be updated with paging parameters. You can access the pagination metadata
  96. at ``$this->request->getAttribute('paging')``.
  97. Simple Pagination
  98. =================
  99. By default ``Controller::paginate()`` uses the ``Cake\Datasource\Paging\NumericPaginator``
  100. class which does a ``COUNT()`` query to calculate the size of the result set so
  101. that page number links can be rendered. On very large datasets this count query
  102. can be very expensive. In situations where you only want to show 'Next' and 'Previous'
  103. links you can use the 'simple' paginator which does not do a count query::
  104. class ArticlesController extends AppController
  105. {
  106. public $paginate = [
  107. 'className' => 'Simple', // Or use Cake\Datasource\Paging\SimplePaginator::class FQCN
  108. ];
  109. }
  110. When using the ``SimplePaginator`` you will not be able to generate page
  111. numbers, counter data, links to the last page, or total record count controls.
  112. .. _paginating-multiple-queries:
  113. Paginating Multiple Queries
  114. ===========================
  115. You can paginate multiple models in a single controller action, using the
  116. ``scope`` option both in the controller's ``$paginate`` property and in the
  117. call to the ``paginate()`` method::
  118. // Paginate property
  119. public $paginate = [
  120. 'Articles' => ['scope' => 'article'],
  121. 'Tags' => ['scope' => 'tag']
  122. ];
  123. // In a controller action
  124. $articles = $this->paginate($this->Articles, ['scope' => 'article']);
  125. $tags = $this->paginate($this->Tags, ['scope' => 'tag']);
  126. $this->set(compact('articles', 'tags'));
  127. The ``scope`` option will result in ``PaginatorComponent`` looking in
  128. scoped query string parameters. For example, the following URL could be used to
  129. paginate both tags and articles at the same time::
  130. /dashboard?article[page]=1&tag[page]=3
  131. See the :ref:`paginator-helper-multiple` section for how to generate scoped HTML
  132. elements and URLs for pagination.
  133. Paginating the Same Model multiple Times
  134. ----------------------------------------
  135. To paginate the same model multiple times within a single controller action you
  136. need to define an alias for the model.::
  137. // In a controller action
  138. $this->paginate = [
  139. 'Articles' => [
  140. 'scope' => 'published_articles',
  141. 'limit' => 10,
  142. 'order' => [
  143. 'id' => 'desc',
  144. ],
  145. ],
  146. 'UnpublishedArticles' => [
  147. 'scope' => 'unpublished_articles',
  148. 'limit' => 10,
  149. 'order' => [
  150. 'id' => 'desc',
  151. ],
  152. ],
  153. ];
  154. $publishedArticles = $this->paginate(
  155. $this->Articles->find('all', [
  156. 'scope' => 'published_articles'
  157. ])->where(['published' => true])
  158. );
  159. // Load an additional table object to allow differentiating in paginator
  160. $unpublishedArticlesTable = $this->fetchTable('UnpublishedArticles', [
  161. 'className' => 'App\Model\Table\ArticlesTable',
  162. 'table' => 'articles',
  163. 'entityClass' => 'App\Model\Entity\Article',
  164. ]);
  165. $unpublishedArticles = $this->paginate(
  166. $unpublishedArticlesTable->find('all', [
  167. 'scope' => 'unpublished_articles'
  168. ])->where(['published' => false])
  169. );
  170. .. _control-which-fields-used-for-ordering:
  171. Control which Fields Used for Ordering
  172. ======================================
  173. By default sorting can be done on any non-virtual column a table has. This is
  174. sometimes undesirable as it allows users to sort on un-indexed columns that can
  175. be expensive to order by. You can set the allowed list of fields that can be sorted
  176. using the ``sortableFields`` option. This option is required when you want to
  177. sort on any associated data, or computed fields that may be part of your
  178. pagination query::
  179. public $paginate = [
  180. 'sortableFields' => [
  181. 'id', 'title', 'Users.username', 'created'
  182. ]
  183. ];
  184. Any requests that attempt to sort on fields not in the allowed list will be
  185. ignored.
  186. Limit the Maximum Number of Rows per Page
  187. =========================================
  188. The number of results that are fetched per page is exposed to the user as the
  189. ``limit`` parameter. It is generally undesirable to allow users to fetch all
  190. rows in a paginated set. The ``maxLimit`` option asserts that no one can set
  191. this limit too high from the outside. By default CakePHP limits the maximum
  192. number of rows that can be fetched to 100. If this default is not appropriate
  193. for your application, you can adjust it as part of the pagination options, for
  194. example reducing it to ``10``::
  195. public $paginate = [
  196. // Other keys here.
  197. 'maxLimit' => 10
  198. ];
  199. If the request's limit param is greater than this value, it will be reduced to
  200. the ``maxLimit`` value.
  201. Joining Additional Associations
  202. ===============================
  203. Additional associations can be loaded to the paginated table by using the
  204. ``contain`` parameter::
  205. public function index()
  206. {
  207. $this->paginate = [
  208. 'contain' => ['Authors', 'Comments']
  209. ];
  210. $this->set('articles', $this->paginate($this->Articles));
  211. }
  212. Out of Range Page Requests
  213. ==========================
  214. ``Controller::paginate()`` will throw a ``NotFoundException`` when trying to
  215. access a non-existent page, i.e. page number requested is greater than total
  216. page count.
  217. So you could either let the normal error page be rendered or use a try catch
  218. block and take appropriate action when a ``NotFoundException`` is caught::
  219. use Cake\Http\Exception\NotFoundException;
  220. public function index()
  221. {
  222. try {
  223. $this->paginate();
  224. } catch (NotFoundException $e) {
  225. // Do something here like redirecting to first or last page.
  226. // $this->request->getAttribute('paging') will give you required info.
  227. }
  228. }
  229. Pagination in the View
  230. ======================
  231. Check the :php:class:`~Cake\\View\\Helper\\PaginatorHelper` documentation for
  232. how to create links for pagination navigation.
  233. .. meta::
  234. :title lang=en: Pagination
  235. :keywords lang=en: paginate,pagination,paging