Top Related Projects
Doctrine2 behavioral extensions, Translatable, Sluggable, Tree-NestedSet, Timestampable, Loggable, Sortable
Integration bundle for DoctrineExtensions by l3pp4rd in Symfony
Elasticsearch PHP integration for your Symfony project using Elastica.
Quick Overview
KnpPaginatorBundle is a Symfony bundle that provides flexible pagination for your PHP applications. It offers easy integration with Symfony projects, supports various data sources, and allows for customizable pagination templates.
Pros
- Easy integration with Symfony projects
- Supports multiple data sources (ORM, ODM, Arrays, etc.)
- Highly customizable pagination templates
- Extensible through event listeners
Cons
- Limited to Symfony framework
- May require additional configuration for complex use cases
- Documentation could be more comprehensive
- Performance impact on large datasets if not properly optimized
Code Examples
- Basic pagination setup in a controller:
use Knp\Component\Pager\PaginatorInterface;
public function listAction(Request $request, PaginatorInterface $paginator)
{
$query = $this->getDoctrine()->getRepository(Article::class)->createQueryBuilder('a');
$pagination = $paginator->paginate(
$query,
$request->query->getInt('page', 1),
10
);
return $this->render('article/list.html.twig', ['pagination' => $pagination]);
}
- Custom sorting:
$pagination = $paginator->paginate(
$query,
$request->query->getInt('page', 1),
10,
['defaultSortFieldName' => 'a.title', 'defaultSortDirection' => 'asc']
);
- Using with arrays:
$items = [/* ... */];
$pagination = $paginator->paginate(
$items,
$request->query->getInt('page', 1),
10
);
Getting Started
-
Install the bundle using Composer:
composer require knplabs/knp-paginator-bundle
-
If using Symfony Flex, the bundle will be automatically configured. Otherwise, add it to your
config/bundles.php
:return [ // ... Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true], ];
-
Create a basic configuration in
config/packages/knp_paginator.yaml
:knp_paginator: page_range: 5 default_options: page_name: page sort_field_name: sort sort_direction_name: direction distinct: true template: pagination: '@KnpPaginator/Pagination/sliding.html.twig' sortable: '@KnpPaginator/Pagination/sortable_link.html.twig'
-
Use the paginator in your controller as shown in the code examples above.
Competitor Comparisons
Doctrine2 behavioral extensions, Translatable, Sluggable, Tree-NestedSet, Timestampable, Loggable, Sortable
Pros of DoctrineExtensions
- Offers a wider range of extensions beyond pagination, including tree structures, sluggable behavior, and timestampable entities
- Provides more flexibility in customizing database queries and entity behaviors
- Integrates seamlessly with Doctrine ORM, allowing for easy implementation of complex database operations
Cons of DoctrineExtensions
- May have a steeper learning curve due to its broader scope and more advanced features
- Could potentially introduce unnecessary complexity for projects that only require simple pagination
- Might have a slightly higher performance overhead for basic operations compared to a dedicated pagination bundle
Code Comparison
KnpPaginatorBundle:
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$query,
$request->query->getInt('page', 1),
10
);
DoctrineExtensions:
use Gedmo\Mapping\Annotation as Gedmo;
/**
* @Gedmo\Sortable(groups={"group"})
* @ORM\Column(name="position", type="integer")
*/
private $position;
The KnpPaginatorBundle example shows a simple pagination implementation, while the DoctrineExtensions example demonstrates the use of annotations for sortable behavior, highlighting the different focus and capabilities of each library.
Integration bundle for DoctrineExtensions by l3pp4rd in Symfony
Pros of StofDoctrineExtensionsBundle
- Offers a wider range of Doctrine extensions, including Timestampable, Sluggable, and Tree
- Provides seamless integration with Symfony for managing Doctrine extensions
- Allows for easy configuration of multiple extensions through a single bundle
Cons of StofDoctrineExtensionsBundle
- May introduce unnecessary complexity if only basic pagination is required
- Requires additional setup and configuration compared to KnpPaginatorBundle
- Performance impact might be higher due to the broader scope of features
Code Comparison
StofDoctrineExtensionsBundle configuration:
stof_doctrine_extensions:
orm:
default:
timestampable: true
sluggable: true
KnpPaginatorBundle usage:
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$query,
$request->query->getInt('page', 1),
10
);
StofDoctrineExtensionsBundle offers more extensive Doctrine functionality but may be overkill for simple pagination needs. KnpPaginatorBundle provides a straightforward pagination solution with less overhead. Choose based on your project's specific requirements and complexity.
Elasticsearch PHP integration for your Symfony project using Elastica.
Pros of FOSElasticaBundle
- Provides seamless integration with Elasticsearch, offering powerful full-text search capabilities
- Supports complex queries and aggregations, enabling advanced data analysis
- Offers real-time indexing and efficient data synchronization between Symfony and Elasticsearch
Cons of FOSElasticaBundle
- Steeper learning curve due to Elasticsearch-specific concepts and query language
- Requires additional setup and maintenance of Elasticsearch infrastructure
- May be overkill for simple pagination needs, adding unnecessary complexity
Code Comparison
KnpPaginatorBundle:
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$query,
$request->query->getInt('page', 1),
10
);
FOSElasticaBundle:
$finder = $this->container->get('fos_elastica.finder.app.user');
$results = $finder->find('john');
While KnpPaginatorBundle focuses on simple pagination, FOSElasticaBundle provides more advanced search functionality. KnpPaginatorBundle is easier to implement for basic use cases, while FOSElasticaBundle offers greater flexibility and power for complex search requirements.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Intro to KnpPaginatorBundle
Friendly Symfony paginator to paginate everything
Generally this bundle is based on Knp Pager component. This component introduces a different way of pagination handling. You can read more about the internal logic on the given documentation link.
Note: Keep knp-components in sync with this bundle. If you want to use older version of KnpPaginatorBundle - use v3.0 or v4.X tags in the repository which is suitable to paginate ODM MongoDB and ORM 2.0 queries
Latest updates
For notes about the latest changes please read CHANGELOG
,
for required changes in your code please read UPGRADE
chapter of the documentation.
Requirements:
- Knp Pager component
>=2.0
. - KnpPaginatorBundle's master is compatible with Symfony
>=6.4
versions. - Twig
>=3.0
version is required if you use the Twig templating engine.
Features:
- Does not require initializing specific adapters.
- Can be customized in any way needed, etc.: pagination view, event subscribers.
- Possibility to add custom filtering, sorting functionality depending on request parameters.
- Separation of concerns, paginator is responsible for generating the pagination view only, pagination view - for representation purposes.
Note: using multiple paginators requires setting the alias in order to keep non conflicting parameters.
More detailed documentation:
- Creating custom pagination subscribers
- Extending pagination class (todo, may require some refactoring)
- Customizing view templates and arguments
Installation and configuration:
Pretty simple with Composer, run
composer require knplabs/knp-paginator-bundle
Add PaginatorBundle to your application kernel
If you don't use flex (you should), you need to manually enable bundle:
// app/AppKernel.php
public function registerBundles()
{
return [
// ...
new Knp\Bundle\PaginatorBundle\KnpPaginatorBundle(),
// ...
];
}
Configuration example
You can configure default query parameter names and templates
YAML:
knp_paginator:
page_range: 5 # number of links shown in the pagination menu (e.g: you have 10 pages, a page_range of 3, on the 5th page you'll see links to page 4, 5, 6)
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 when ORM queries are using GROUP BY statements
filter_field_name: filterField # filter field query parameter name
filter_value_name: filterValue # filter value query parameter name
template:
pagination: '@KnpPaginator/Pagination/sliding.html.twig' # sliding pagination controls template
rel_links: '@KnpPaginator/Pagination/rel_links.html.twig' # <link rel=...> tags template
sortable: '@KnpPaginator/Pagination/sortable_link.html.twig' # sort link template
filtration: '@KnpPaginator/Pagination/filtration.html.twig' # filters template
PHP:
// config/packages/paginator.php
<?php declare(strict_types=1);
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $configurator): void
{
$configurator->extension('knp_paginator', [
'page_range' => 5, // number of links shown in the pagination menu (e.g: you have 10 pages, a page_range of 3, on the 5th page you'll see links
'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 when ORM queries are using GROUP BY statements
'filter_field_name' => 'filterField', // filter field query parameter name
'filter_value_name' => 'filterValue' // filter value query parameter name
],
'template' => [
'pagination' => '@KnpPaginator/Pagination/sliding.html.twig', // sliding pagination controls template
'rel_links' => '@KnpPaginator/Pagination/rel_links.html.twig', // <link rel=...> tags template
'sortable' => '@KnpPaginator/Pagination/sortable_link.html.twig', // sort link template
'filtration' => '@KnpPaginator/Pagination/filtration.html.twig' // filters template
]
]);
};
Additional pagination templates
That could be used out of the box in knp_paginator.template.pagination
key:
@KnpPaginator/Pagination/sliding.html.twig
(by default)@KnpPaginator/Pagination/bootstrap_v5_pagination.html.twig
@KnpPaginator/Pagination/twitter_bootstrap_v4_pagination.html.twig
@KnpPaginator/Pagination/twitter_bootstrap_v3_pagination.html.twig
@KnpPaginator/Pagination/twitter_bootstrap_pagination.html.twig
@KnpPaginator/Pagination/foundation_v6_pagination.html.twig
@KnpPaginator/Pagination/foundation_v5_pagination.html.twig
@KnpPaginator/Pagination/bulma_pagination.html.twig
@KnpPaginator/Pagination/semantic_ui_pagination.html.twig
@KnpPaginator/Pagination/materialize_pagination.html.twig
@KnpPaginator/Pagination/tailwindcss_pagination.html.twig
@KnpPaginator/Pagination/uikit_v3_pagination.html.twig
Sample rel link tag template
That could be used out of the box in knp_paginator.template.rel_links
key:
@KnpPaginator/Pagination/rel_links.html.twig
(by default)
Additional sortable templates
That could be used out of the box in knp_paginator.template.sortable
key:
@KnpPaginator/Pagination/sortable_link.html.twig
(by default)@KnpPaginator/Pagination/bootstrap_v5_bi_sortable_link.html.twig
@KnpPaginator/Pagination/bootstrap_v5_fa_sortable_link.html.twig
@KnpPaginator/Pagination/bootstrap_v5_md_sortable_link.html.twig
@KnpPaginator/Pagination/twitter_bootstrap_v3_sortable_link.html.twig
@KnpPaginator/Pagination/twitter_bootstrap_v4_font_awesome_sortable_link.html.twig
@KnpPaginator/Pagination/twitter_bootstrap_v4_material_design_icons_sortable_link.html.twig
@KnpPaginator/Pagination/semantic_ui_sortable_link.html.twig
@KnpPaginator/Pagination/uikit_v3_sortable.html.twig
Additional filtration templates
That could be used out of the box in knp_paginator.template.filtration
key:
@KnpPaginator/Pagination/filtration.html.twig
(by default)@KnpPaginator/Pagination/bootstrap_v5_filtration.html.twig
@KnpPaginator/Pagination/twitter_bootstrap_v4_filtration.html.twig
Usage examples:
Controller
Currently paginator can paginate:
array
Doctrine\DBAL\Query\QueryBuilder
Doctrine\ORM\Query
Doctrine\ORM\QueryBuilder
Doctrine\ODM\MongoDB\Query\Query
Doctrine\ODM\MongoDB\Query\Builder
Doctrine\ODM\PHPCR\Query\Query
Doctrine\ODM\PHPCR\Query\Builder\QueryBuilder
Doctrine\Common\Collection\ArrayCollection
- any Doctrine relation collection includingModelCriteria
- Propel ORM query- array with
Solarium_Client
andSolarium_Query_Select
as elements
// App\Controller\ArticleController.php
public function listAction(EntityManagerInterface $em, PaginatorInterface $paginator, Request $request)
{
$dql = "SELECT a FROM AcmeMainBundle:Article a";
$query = $em->createQuery($dql);
$pagination = $paginator->paginate(
$query, /* query NOT result */
$request->query->getInt('page', 1), /*page number*/
10 /*limit per page*/
);
// parameters to template
return $this->render('article/list.html.twig', ['pagination' => $pagination]);
}
View
In <head>
:
{# rel links for pagination #}
{{ knp_pagination_rel_links(pagination) }}
In <body>
:
{# total items count #}
<div class="count">
{{ pagination.getTotalItemCount }}
</div>
<table>
<tr>
{# sorting of properties based on query components #}
<th>{{ knp_pagination_sortable(pagination, 'Id', 'a.id') }}</th>
<th{% if pagination.isSorted('a.title') %} class="sorted"{% endif %}>
{{ knp_pagination_sortable(pagination, 'Title', 'a.title') }}
</th>
<th{% if pagination.isSorted(['a.date', 'a.time']) %} class="sorted"{% endif %}>
{{ knp_pagination_sortable(pagination, 'Release', ['a.date', 'a.time']) }}
</th>
</tr>
{# table body #}
{% for article in pagination %}
<tr {% if loop.index is odd %}class="color"{% endif %}>
<td>{{ article.id }}</td>
<td>{{ article.title }}</td>
<td>{{ article.date | date('Y-m-d') }}, {{ article.time | date('H:i:s') }}</td>
</tr>
{% endfor %}
</table>
{# display navigation #}
<div class="navigation">
{{ knp_pagination_render(pagination) }}
</div>
Translation in view
For translating the following text:
%foo% name
with translation keytable_header_name
. The translation is in the domainmessages
.{0} No author|{1} Author|[2,Inf] Authors
with translation keytable_header_author
. The translation is in the domainmessages
.
translationCount and translationParameters can be combined.
<table>
<tr>
{# sorting of properties based on query components #}
<th>{{ knp_pagination_sortable(pagination, 'Id'|trans({foo:'bar'},'messages'), 'a.id' )|raw }}</th>
<th{% if pagination.isSorted('a.Title') %} class="sorted"{% endif %}>{{ knp_pagination_sortable(pagination, 'Title', 'a.title')|raw }}</th>
<th>{{ knp_pagination_sortable(pagination, 'Author'|trans({}, 'messages'), 'a.author' )|raw }}</th>
</tr>
<!-- Content of the table -->
</table>
Adding translation files
You can also override translations by creating a translation file in the following name format: domain.locale.format
.
So, to create a translation file for this bundle you need to create for instance KnpPaginatorBundle.tr.yaml
file under project_root/translations/
and add your translations there:
label_previous: "Ãnceki"
label_next: "Sonraki"
filter_searchword: "Arama kelimesi"
If you set default translation for configuration accordingly:
framework:
default_locale: tr
Symfony will pick it automatically.
Dependency Injection
You can automatically inject a paginator service into another service by using the knp_paginator.injectable
DIC tag.
The tag takes one optional argument paginator
, which is the ID of the paginator service that should be injected.
It defaults to knp_paginator
.
The class that receives the KnpPaginator service must implement Knp\Bundle\PaginatorBundle\Definition\PaginatorAwareInterface
.
If you're too lazy you can also just extend the Knp\Bundle\PaginatorBundle\Definition\PaginatorAware
base class.
â Warning using
PaginatorAwareInterface
is discouraged, and could be removed in a future version. You should not rely on setter injection, but only on proper constructor injection. Using Symfony built-in autowiring mechanism is the suggested way to go.
Lazy service
The knp_paginator
service will be created lazily if the package symfony/proxy-manager-bridge
is installed.
For more information about lazy services, consult the Symfony documentation on dependency injection.
XML configuration example
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="my_bundle.paginator_aware.class">MyBundle\Repository\PaginatorAwareRepository</parameter>
</parameters>
<services>
<service id="my_bundle.paginator_aware" class="my_bundle.paginator_aware.class">
<tag name="knp_paginator.injectable" paginator="knp_paginator" />
</service>
</services>
</container>
Troubleshooting
- Make sure the translator is activated in your Symfony config:
framework:
translator: { fallbacks: ['%locale%'] }
- If your locale is not available, create your own translation file in
translations/KnpPaginatorBundle.en.yml
(substitute "en" for your own language code if needed). Then add these lines:
label_next: Next
label_previous: Previous
- Note that
<rel>
links are only meaningful when using pagination, they are not relevant to sorting or filtering.
Maintainers
Please read this post first.
This library is maintained by the following people (alphabetically sorted) :
- @garak
- @polc
Top Related Projects
Doctrine2 behavioral extensions, Translatable, Sluggable, Tree-NestedSet, Timestampable, Loggable, Sortable
Integration bundle for DoctrineExtensions by l3pp4rd in Symfony
Elasticsearch PHP integration for your Symfony project using Elastica.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot