mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
adding doc about pagination
This commit is contained in:
parent
6a57cd8388
commit
53a6ca3d6b
@ -20,6 +20,7 @@ As Chill rely on the `symfony <http://symfony.com>`_ framework, reading the fram
|
|||||||
Menus <menus.rst>
|
Menus <menus.rst>
|
||||||
Access control model <access_control_model.rst>
|
Access control model <access_control_model.rst>
|
||||||
Messages to users <messages-to-users.rst>
|
Messages to users <messages-to-users.rst>
|
||||||
|
Pagination <pagination.rst>
|
||||||
Localisation <localisation.rst>
|
Localisation <localisation.rst>
|
||||||
Logging <logging.rst>
|
Logging <logging.rst>
|
||||||
Database migrations <migrations.rst>
|
Database migrations <migrations.rst>
|
||||||
|
189
source/development/pagination.rst
Normal file
189
source/development/pagination.rst
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
.. Copyright (C) 2016 Champs Libres Cooperative SCRLFS
|
||||||
|
Permission is granted to copy, distribute and/or modify this document
|
||||||
|
under the terms of the GNU Free Documentation License, Version 1.3
|
||||||
|
or any later version published by the Free Software Foundation;
|
||||||
|
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
|
||||||
|
A copy of the license is included in the section entitled "GNU
|
||||||
|
Free Documentation License".
|
||||||
|
|
||||||
|
|
||||||
|
Pagination
|
||||||
|
##########
|
||||||
|
|
||||||
|
The Bundle :code:`Chill\MainBundle` provides a **Pagination** api which allow you to easily divide results list on different pages.
|
||||||
|
|
||||||
|
A simple example
|
||||||
|
****************
|
||||||
|
|
||||||
|
In the controller, get the :class:`Chill\Main\Pagination\PaginatorFactory` from the `Container` and use this :code:`PaginatorFactory` to create a :code:`Paginator` instance.
|
||||||
|
|
||||||
|
|
||||||
|
.. literalinclude:: pagination/example.php
|
||||||
|
:language: php
|
||||||
|
|
||||||
|
|
||||||
|
Then, render the pagination using the dedicated twig function.
|
||||||
|
|
||||||
|
.. code-block:: html+jinja2
|
||||||
|
|
||||||
|
{% extends "ChillPersonBundle::layout.html.twig" %}
|
||||||
|
|
||||||
|
{% block title 'Item list'|trans %}
|
||||||
|
|
||||||
|
{% block personcontent %}
|
||||||
|
|
||||||
|
<table>
|
||||||
|
|
||||||
|
{# ... your items here... #}
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% if items|length > paginator.getTotalItems %}
|
||||||
|
{{ chill_pagination(paginator) }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
The function :code:`chill_pagination` will, by default, render a link to the 10 previous page (if they exists) and the 10 next pages (if they exists). Assuming that we are on page 5, the function will render a list to ::
|
||||||
|
|
||||||
|
Previous 1 2 3 4 **5** 6 7 8 9 10 11 12 13 14 Next
|
||||||
|
|
||||||
|
Understanding the magic
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Where does the :code:`$paginator` get the page number ?
|
||||||
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
Internally, the :code:`$paginator` object has a link to the :code:`Request` object, and it reads the :code:`page` parameter which contains the current page number. If this parameter is not present, the :code:`$paginator` assumes that we are on page 1.
|
||||||
|
|
||||||
|
.. figure:: /static/puml/pagination-sequence.png
|
||||||
|
|
||||||
|
The :code:`$paginator` get the current page from the request.
|
||||||
|
|
||||||
|
Where does the :code:`$paginator` get the number of items per page ?
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
As above, the :code:`$paginator` can get the number of items per page from the :code:`Request`. If none is provided, this is given by the configuration which is, by default, 50 items per page.
|
||||||
|
|
||||||
|
:code:`PaginatorFactory`, :code:`Paginator` and :code:`Page`
|
||||||
|
************************************************************
|
||||||
|
|
||||||
|
:code:`PaginatorFactory`
|
||||||
|
========================
|
||||||
|
|
||||||
|
The :code:`PaginatorFactory` may create more than one :code:`Paginator` in a single action. Those :code:`Paginator` instance may redirect to different routes and/or routes parameters.
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
// create a paginator for the route 'my_route' with some parameters (arg1 and arg2)
|
||||||
|
$paginatorMyRoute = $paginatorFactory->create($total, 'my_route', array('arg1' => 'foo', 'arg2' => $bar);
|
||||||
|
|
||||||
|
Those parameters will override the current parameters.
|
||||||
|
|
||||||
|
The :code:`PaginatorFactory` has also some useful shortcuts :
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
// get current page number
|
||||||
|
$paginatorFactory->getCurrentPageNumber( )
|
||||||
|
// get the number of items per page **for the current request**
|
||||||
|
$paginatorFactory->getCurrentItemsPerPage( )
|
||||||
|
// get the number of the first item **for the current page**
|
||||||
|
$paginatorFactory->getCurrentPageFirstItemNumber( )
|
||||||
|
|
||||||
|
|
||||||
|
Working with :code:`Paginator` and :code:`Page`
|
||||||
|
===============================================
|
||||||
|
|
||||||
|
The paginator has some function to give the number of pages are required to displayed all the results, and give some information about the number of items per page :
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
// how many page count this paginator ?
|
||||||
|
$paginator->countPages(); // return 20 in our example
|
||||||
|
|
||||||
|
// we may get the number of items per page
|
||||||
|
$paginator->getItemsPerPage(); // return 20 in our example
|
||||||
|
|
||||||
|
A :code:`Paginator` instance create instance of :code:`Page`, each :code:`Page`, which is responsible for generating the URL to the page number it represents. Here are some possibilities using :code:`Page` and :code:`Paginator` :
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
// get the current page
|
||||||
|
$page = $paginator->getCurrentPage();
|
||||||
|
// on which page are we ?
|
||||||
|
$page->getNumber(); // return 5 in this example (we are on page 5)
|
||||||
|
// generate the url for page 5
|
||||||
|
$page->generateUrl(); // return '/<your route here>?page=5
|
||||||
|
// what is the first item number on this page ?
|
||||||
|
$page->getFistItemNumber(); // return 101 in our example (20 items per page)
|
||||||
|
// what is the last item number on this page ?
|
||||||
|
$page->getLastItemNumber(); // return 120 in our example
|
||||||
|
|
||||||
|
// we can access directly the next and current page
|
||||||
|
if ($paginator->hasNextPage()) {
|
||||||
|
$next = $paginator->getNextPage();
|
||||||
|
}
|
||||||
|
if ($paginator->hasPreviousPage()) {
|
||||||
|
$previous = $paginator->getPreviousPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// we can access directly to a given page number
|
||||||
|
if ($paginator->hasPage(10)) {
|
||||||
|
$page10 = $paginator->getPage(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we can iterate over our pages through a generator
|
||||||
|
foreach ($paginator->getPagesGenerator() as $page) {
|
||||||
|
$page->getNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that a page object is the current page
|
||||||
|
$paginator->isCurrentPage($page); // return false
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
When calling a page which does not exists, the :code:`Paginator` will throw a `RuntimeException`. Example :
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
// our last page is 10
|
||||||
|
$paginator->getPage(99); // out of range => throw `RuntimeException`
|
||||||
|
|
||||||
|
// our current page is 1 (the first page)
|
||||||
|
$paginator->getPreviousPage; // does not exists (the fist page is always 1) => throw `RuntimeException`
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
When you create a :code:`Paginator` for the current route and route parameters, the :code:`Page` instances will keep the same parameters and routes :
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
// assuming our route is 'my_route', for the pattern '/my/{foo}/route',
|
||||||
|
// and the current route is '/my/value/route?arg2=bar'
|
||||||
|
|
||||||
|
// create a paginator for the current route and route parameters :
|
||||||
|
$paginator = $paginatorFactory->create($total);
|
||||||
|
|
||||||
|
// get the next page
|
||||||
|
if ($paginator->hasNext()) {
|
||||||
|
$next = $paginator->getNextPage();
|
||||||
|
|
||||||
|
// get the route to the page
|
||||||
|
$page->generateUrl(); // will print 'my/value/route?arg2=bar&page=2'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Having a look to the `full classes documentation may provide some useful information <http://api.chill.social/Chill-Main/master/namespace-Chill.MainBundle.Pagination.html>`_.
|
||||||
|
|
||||||
|
|
||||||
|
Customizing the rendering of twig's :code:`chill_pagination`
|
||||||
|
************************************************************
|
||||||
|
|
||||||
|
You can provide your own layout for rendering the pagination: provides your twig template as a second argument :
|
||||||
|
|
||||||
|
.. code-block:: html+jinja
|
||||||
|
|
||||||
|
{{ chill_pagination(paginator, 'MyBundle:Pagination:MyTemplate.html.twig') }}
|
||||||
|
|
||||||
|
The template will receive the :code:`$paginator` as :code:`paginator` variable. Let's have a look `at the current template <https://framagit.org/Chill-project/Chill-Main/blob/master/Resources/views/Pagination/long.html.twig>`_.
|
||||||
|
|
42
source/development/pagination/example.php
Normal file
42
source/development/pagination/example.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\MyBundle\Controller;
|
||||||
|
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
|
|
||||||
|
class ItemController extends Controller {
|
||||||
|
|
||||||
|
public function yourAction()
|
||||||
|
{
|
||||||
|
$em = $this->getDoctrine()->getManager();
|
||||||
|
// first, get the number of total item are available
|
||||||
|
$total = $em
|
||||||
|
->createQuery("COUNT (item.id) FROM ChillMyBundle:Item item")
|
||||||
|
->getSingleScalarResult();
|
||||||
|
|
||||||
|
// get the PaginatorFactory
|
||||||
|
$paginatorFactory = $this->get('chill_main.paginator_factory');
|
||||||
|
|
||||||
|
// create a pagination instance. This instance is only valid for
|
||||||
|
// the current route and parameters
|
||||||
|
$paginator = $paginatorFactory->create($total);
|
||||||
|
|
||||||
|
// launch your query on item. Limit the query to the results
|
||||||
|
// for the current page using the paginator
|
||||||
|
$items = $em->createQuery("SELECT item FROM ChillMyBundle:Item item WHERE <your clause>")
|
||||||
|
// use the paginator to get the first item number
|
||||||
|
->setFirstResult($paginator->getCurrentPage()->getFirstItemNumber())
|
||||||
|
// use the paginator to get the number of items to display
|
||||||
|
->setMaxResults($paginator->getItemsPerPage());
|
||||||
|
|
||||||
|
return $this->render('ChillMyBundle:Item:list.html.twig', array(
|
||||||
|
'items' => $items,
|
||||||
|
'paginator' => $paginator
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
BIN
source/static/puml/pagination-sequence.png
Normal file
BIN
source/static/puml/pagination-sequence.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
20
source/static/puml/pagination-sequence.puml
Normal file
20
source/static/puml/pagination-sequence.puml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
@startuml
|
||||||
|
|
||||||
|
actor "controller, service, ..." as x
|
||||||
|
participant "paginator"
|
||||||
|
participant "Request"
|
||||||
|
|
||||||
|
x -> paginator: getCurrentPage()
|
||||||
|
activate paginator
|
||||||
|
|
||||||
|
paginator -> Request: read the `page` parameter in GET request
|
||||||
|
activate Request
|
||||||
|
Request -> paginator
|
||||||
|
deactivate Request
|
||||||
|
|
||||||
|
paginator -> paginator: construct a page object for current page number
|
||||||
|
paginator -> x: return the `page`
|
||||||
|
deactivate paginator
|
||||||
|
|
||||||
|
@enduml
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user