KnpPaginatorBundle

repository·master·Indexed 23 days ago

https://github.com/knplabs/knppaginatorbundle

A Symfony bundle for paginating various data sources, including Doctrine ORM, ODM, Propel, and arrays. It separates pagination logic from view representation and provides built-in Twig templates for CSS frameworks like Bootstrap, Tailwind, and Bulma. Features include support for custom pagination subscribers, manual count hints for complex ORM queries, and configurable query parameters.

Tokens
7.4K
Snippets
21
Records
26
Agent score
82%

What's inside KnpPaginatorBundle

  1. Translate pagination labels

    master

    You can translate pagination labels in two ways:

    1. Inline in Twig

    Use the trans filter within the knp_pagination_sortable function. You can pass translation parameters and specify a domain (e.g., messages).

    2. Custom Translation Files

    Create a translation file following the pattern domain.locale.format (e.g., KnpPaginatorBundle.tr.yaml) in your project's translations/ directory.

    Common keys to override:

    • label_previous
    • label_next
    • filter_searchword
    {# Inline translation example #}
    <th>{{ knp_pagination_sortable(pagination, 'Author'|trans({}, 'messages'), 'a.author' )|raw }}</th>
    # translations/KnpPaginatorBundle.tr.yaml
    label_previous: "Önceki"
    label_next: "Sonraki"
    filter_searchword: "Arama kelimesi"
  2. Provide a manual count for complex ORM queries

    master

    When using ORM query pagination, the Paginator may fail to calculate the total number of results if your query contains multiple FROM components or uses composite identifiers. In these cases, the Paginator cannot predict the total count in the database automatically.

    To resolve this, you must calculate the count manually using a separate query and provide it to the main query using the knp_paginator.count hint.

    <?php
    
    $paginator = new Paginator();
    
    // 1. Manually calculate the total count
    $count = $entityManager
        ->createQuery('SELECT COUNT(c) FROM Entity\CompositeKey c')
        ->getSingleScalarResult()
    ;
    
    // 2. Pass the count to the main query using the 'knp_paginator.count' hint
    $query = $entityManager
        ->createQuery('SELECT c FROM Entity\CompositeKey c')
        ->setHint('knp_paginator.count', $count)
    ;
    
    // 3. Paginate as usual
    $pagination = $paginator->paginate($query, 1, 10, ['distinct' => false]);
  3. Override default pagination templates

    master

    You can override the default pagination templates globally, per pagination instance, or directly within a Twig template.

    Global Configuration

    Set the templates globally in config/packages/knp_paginator.yaml:

    knp_paginator.template.pagination: my_pagination.html.twig
    knp_paginator.template.sortable: my_sortable.html.twig

    Per-instance (Controller)

    Use the setter methods on the Pagination object returned by the paginator:

    $pagination->setTemplate('my_pagination.html.twig');
    $pagination->setRelLinksTemplate('my_rel_links.html.twig');
    $pagination->setSortableTemplate('my_sortable.html.twig');

    Per-instance (Twig)

    Use the {% do %} tag in Twig to modify the pagination object before rendering:

    {% do pagination.setTemplate('my_pagination.html.twig') %}

    During Rendering

    Pass the template path directly to the rendering functions:

    {{ knp_pagination_render(pagination, 'my_pagination.html.twig') }}
    {{ knp_pagination_sortable(pagination, 'date', 'c.publishedAt', {}, {}, 'KnpPaginator/Pagination/bootstrap_v4_sortable_link.html.twig') }}
  4. Create a custom pagination subscriber

    master

    You can extend the pagination logic by creating an event subscriber that listens to the knp_pager.items event. This allows you to paginate non-standard data sources, such as directory contents via Symfony's Finder component, instead of standard Doctrine collections or arrays.

    To implement a subscriber:

    1. Implement Symfony\Component\EventDispatcher\EventSubscriberInterface.
    2. Define a method (e.g., items) that accepts a Knp\Component\Pager\Event\ItemsEvent object.
    3. In the method, check if the $event->target is valid for your logic.
    4. Calculate the total count and set the slice of items using $event->count and $event->items (using $event->getOffset() and $event->getLimit()).
    5. Call $event->stopPropagation() to prevent other subscribers from running.
    6. Register the event in getSubscribedEvents() using the knp_pager.items key. Use a high priority (e.g., 1) to ensure your custom logic overrides default internal behaviors.
    <?php
    
    namespace App\Subscriber;
    
    use Knp\Component\Pager\Event\ItemsEvent;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    use Symfony\Component\Finder\Finder;
    
    final class PaginateDirectorySubscriber implements EventSubscriberInterface
    {
        public function items(ItemsEvent $event): void
        {
            if (!is_string($event->target) || !is_dir($event->target)) {
                return;
            }
            $finder = new Finder();
            $finder
                ->files()
                ->depth('< 4') // 3 levels
                ->in($event->target)
            ;
            $iterator = $finder->getIterator();
            $files = iterator_to_array($iterator);
            $event->count = count($files);
            $event->items = array_slice($files, $event->getOffset(), $event->getLimit());
            $event->stopPropagation();
        }
    
        public static function getSubscribedEvents(): array
        {
            return [
                'knp_pager.items' => ['items', 1/* increased priority to override any internal */]
            ];
        }
    }
  5. Pass custom parameters to pagination templates

    master

    If your template requires custom variables (e.g., alignment or size for Bootstrap/Bulma), use setCustomParameters in the controller or pass them via the viewParams argument in Twig.

    In the Controller

    $pagination->setCustomParameters([
        'align' => 'center',
        'size' => 'large',
        'style' => 'bottom',
    ]);

    In Twig

    Pass parameters as the fourth argument (query parameters) or fifth argument (view parameters) to knp_pagination_render:

    {{ knp_pagination_render(pagination, 'template.html.twig', { 'queryParam': 'val' }, { 'viewParam': 'val' }) }}

    Example: Bulma Customization

    To customize Bulma pagination:

    • align: 'left', 'center', or 'right'
    • size: 'small', 'medium', or 'large'
    • rounded: true or false
    {{ knp_pagination_render(pagination, null, {}, {
       'align': 'center',
       'size': 'large',
       'rounded': true,
    }) }}
    $pagination->setCustomParameters([
        'align' => 'center',
        'size' => 'large',
        'style' => 'bottom',
        'span_class' => 'whatever',
    ]);
  6. Adjust page range and page limits

    master

    You can control how many pages are visible in the sliding pagination and set a maximum number of pages allowed.

    Change the page range

    Sets the number of pages to show in the sliding window (default is 5).

    • Controller: $pagination->setPageRange(7);
    • Twig: {% do pagination.setPageRange(7) %}

    Set a page limit

    Limits the total number of pages available.

    • Controller: $pagination->setPageLimit(25);
    • Twig: {% do pagination.setPageLimit(25) %}
    $pagination->setPageRange(7);
    $pagination->setPageLimit(25);
  7. Configure pagination routes and query parameters

    master

    By default, the paginator uses the current route and request query parameters. If you are rendering in a sub-request or need to use a specific route for pagination links, you can manually set them.

    Set a specific route

    $pagination->setUsedRoute('blog_articles');

    Add additional query parameters

    To include extra parameters (like a category filter) in every pagination link:

    $pagination->setParam('category', 'news');
    $pagination->setUsedRoute('blog_articles');
    $pagination->setParam('category', 'news');
  8. Register KnpPaginatorBundle in the Kernel

    master

    If you are not using Symfony Flex, you must manually register the bundle in your application kernel.

    // app/AppKernel.php
    public function registerBundles()
    {
        return [
            // ...
            new Knp\Bundle\PaginatorBundle\KnpPaginatorBundle(),
            // ...
        ];
    }
  9. Configure KnpPaginatorBundle options

    master

    You can configure the paginator's behavior, including query parameter names, page ranges, and default templates.

    Note: If you are using multiple paginators in the same application, you must set a unique alias for each to prevent conflicting query parameters.

    knp_paginator:
        convert_exception: false            # throw a 404 exception when an invalid page is requested
        page_range: 5                       # number of links shown in the pagination menu
        remove_first_page_param: false      # remove the page query parameter from the first page link
        default_options:
            page_name: page                 # page query parameter name
            sort_field_name: sort           # sort field query parameter name
            sort_direction_name: direction  # sort direction query parameter name
            distinct: true                  # ensure distinct results (useful for GROUP BY queries)
            filter_field_name: filterField  # filter field query parameter name
            filter_value_name: filterValue  # filter value query parameter name
            page_out_of_range: ignore       # ignore, fix, or throwException when the page is out of range
            default_limit: 10               # default number of items per page
        template:
            pagination: '@KnpPaginator/Pagination/sliding.html.twig'
            rel_links: '@KnpPaginator/Pagination/rel_links.html.twig'
            sortable: '@KnpPaginator/Pagination/sortable_link.html.twig'
            filtration: '@KnpPaginator/Pagination/filtration.html.twig'