ashleydawson / simple-pagination-bundle
Symfony bundle for Simple Pagination, the simple, lightweight and universal paginator that implements pagination on collections of things
Installs: 15 609
Dependents: 0
Suggesters: 0
Security: 0
Stars: 4
Watchers: 2
Forks: 2
Open Issues: 1
Type:symfony-bundle
Requires
- php: ^7.2.5
- ashleydawson/simple-pagination: 1.0.*
- symfony/config: ^3.4|^4.2|^5.0
- symfony/dependency-injection: ^3.4|^4.2|^5.0
- symfony/http-kernel: ^3.4|^4.2|^5.0
- symfony/yaml: ^3.4|^4.2|^5.0
- twig/twig: ^2.7|^3.0
Requires (Dev)
- symfony/phpunit-bridge: ^5.0
This package is auto-updated.
Last update: 2024-12-04 18:09:39 UTC
README
Many thanks to BrowserStack for supporting open source projects like this one.
Symfony bundle for the Simple Pagination library.
Installation
You can install the Simple Pagination Bundle via Composer. To do that, simply require
the
package:
$ composer req ashleydawson/simple-pagination-bundle
Run composer update
to install the package. Then you'll need to register the bundle in your app/AppKernel.php
:
$bundles = array( // ... new AshleyDawson\SimplePaginationBundle\AshleyDawsonSimplePaginationBundle(), );
Basic Usage
The simplest collection we can use the paginator service on is an array. Please see below for an extremely simple example of the paginator operating on an array. This shows the service paginating over an array of 12 items.
namespace Acme\DemoBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class WelcomeController extends Controller { public function indexAction() { // Get the paginator service from the container $paginator = $this->get('ashley_dawson_simple_pagination.paginator'); // Build a mock set of items to paginate over $items = array( 'Banana', 'Apple', 'Cherry', 'Lemon', 'Pear', 'Watermelon', 'Orange', 'Grapefruit', 'Blackcurrant', 'Dingleberry', 'Snosberry', 'Tomato', ); // Set the item total callback, simply returning the total number of items $paginator->setItemTotalCallback(function () use ($items) { return count($items); }); // Add the slice callback, simply slicing the items array using $offset and $length $paginator->setSliceCallback(function ($offset, $length) use ($items) { return array_slice($items, $offset, $length); }); // Perform the pagination, passing the current page number from the request $pagination = $paginator->paginate((int)$this->get('request')->query->get('page', 1)); // Pass the pagination object to the view for rendering return $this->render('AcmeDemoBundle:Welcome:index.html.twig', array( 'pagination' => $pagination, )); } }
And in the twig view, it looks like this:
... {# Iterate over items for the current page, rendering each one #} <ul> {% for item in pagination.items %} <li>{{ item }}</li> {% endfor %} </ul> {# Iterate over the page list, rendering the page links #} <div> {% for page in pagination.pages %} <a href="?page={{ page }}">{{ page }}</a> | {% endfor %} </div> ...
You can override the "items per page" and "pages in range" options at runtime by passing values to the paginator like this:
// ... $paginator ->setItemsPerPage(20) ->setPagesInRange(5) ; $pagination = $paginator->paginate((int)$this->get('request')->query->get('page', 1)); // ...
Please note that this is a very simple example, some advanced use-cases and interfaces are coming up (see below).
Doctrine Example
I've expanded the example above to use Doctrine instead of a static array of items:
namespace Acme\DemoBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class WelcomeController extends Controller { public function indexAction() { // Get the paginator service from the container $paginator = $this->get('ashley_dawson_simple_pagination.paginator'); // Create a Doctrine query builder $manager = $this->getDoctrine()->getManager(); $query = $manager->createQueryBuilder(); // Build the initial query, including any special filters $query ->from('AcmeDemoBundle:Film', 'f') ->where('f.releaseAt > :threshold') ->setParameter('threshold', new \DateTime('1980-08-16')) ; // Pass the item total callback $paginator->setItemTotalCallback(function () use ($query) { // Run the count of all records $query ->select('COUNT(f.id)') ; // Return the total item count return (int)$query->getQuery()->getSingleScalarResult(); }); // Pass the slice callback $paginator->setSliceCallback(function ($offset, $length) use ($query) { // Select and slice the data $query ->select('f') ->setFirstResult($offset) ->setMaxResults($length) ; // Return the collection return $query->getQuery()->getResult(); }); // Finally, paginate using the current page number $pagination = $paginator->paginate((int)$this->get('request')->query->get('page', 1)); // Pass the pagination object to the view return $this->render('AcmeDemoBundle:Welcome:index.html.twig', array( 'pagination' => $pagination, )); } }
And in the twig view, it looks like this:
... {# Iterate over films (Doctrine results) for the current page, rendering each one #} <ul> {% for film in pagination.items %} <li> <strong>{{ film.title }}</strong> <time>{{ film.releaseAt | date('jS F, Y') }}</time> </li> {% endfor %} </ul> {# Use the pagination view helper to render the page navigation #} <div> {{ simple_pagination_render( pagination, '_welcome', 'page', app.request.query.all ) }} </div> ...
Configuration
You can configure the Simple Pager Bundle from app/config/config.yml
with the following optional parameters:
ashley_dawson_simple_pagination: defaults: items_per_page: 10 pages_in_range: 5 template: AshleyDawsonSimplePaginationBundle:Pagination:default.html.twig
Twig Function
I've provided a handy twig function to render the built in pagination template. The default template
can be configured in your app/config/config.yml
or simply overridden as an argument in the twig function.
The arguments passed to the twig function are as follows:
simple_pagination_render(pagination : Pagination, routeName : string, [pageParameterName : string = 'page'], [queryParameters : array = array()], [template : string | null = null])
A brief description of each argument is:
- pagination: The
AshleyDawson\SimplePagination\Pagination
object returned byAshleyDawson\SimplePagination\Paginator::paginate()
- routeName: Route name to be passed to the navigation
{{ path() }}
function, defined in your routing config - pageParameterName: The name of the page number parameter in your request (optional)
- queryParameters: The array of query parameters to append to the path (optional)
- template: The template you'd like to use to override the default (optional)
An exhaustive twig view example is as follows:
<div> {{ simple_pagination_render( pagination, '_welcome', 'page', app.request.query.all, 'AcmeBundle:Default:pagination.html.twig' ) }} </div>
A better example, with the accompanying item list:
<div> <ul> {% for item in pagination.items %} <li>{{ item }}</li> {% endfor %} </ul> </div> <div> {{ simple_pagination_render(pagination, 'my_route_name', 'page', app.request.query.all) }} </div>
Custom Service
If you'd like to define the paginator as a custom service, please use the following service container configuration.
In YAML:
services: my_paginator: class: AshleyDawson\SimplePagination\Paginator calls: - [ setItemsPerPage, [ 10 ] ] - [ setPagesInRange, [ 5 ] ]
or in XML:
<services> <service id="my_paginator" class="AshleyDawson\SimplePagination\Paginator"> <call method="setItemsPerPage"> <argument>10</argument> </call> <call method="setPagesInRange"> <argument>5</argument> </call> </service> </services>
Then use it in your controllers like this:
// Get my paginator service from the container $paginator = $this->get('my_paginator'); // ...