How To Paginate Doctrine Entities with Symfony 5

How To Paginate Doctrine Entities with Symfony 5

Using the Doctrine Paginator to easily paginate entities in Symfony 5.

The Doctrine Paginator

The Doctrine ORM makes paginating entities effortless with the Doctrine Paginator.

Below I've provided a simple Repository class for some generic Article entity. It contains a few examples for you to analyze, and I'll go over the 1st with you.


The Doctrine Query Builder

The following assumes knoledge of the Doctrine Query Builder. If you're unfamiliar with the Doctrine Query Builder, it's a topic for another post, but you can read all about it in the Doctrine docs.


Get Paginated Posts

Take a look at the getPaginatedPosts() method below. It takes two arguments, a page number $page, and the number of posts per page $postsPerPage.

First we'll create a query using the Doctrine Query Builder. The line $this->createQueryBuilder('a')->orderBy('a.timestamp', 'DESC')->getQuery() creates a query of Article objects, sorted in descending order by a timestamp property.

Next we create an instance of the Doctrine Paginator, and pass it the query we just created.

Finnaly the line $paginator->getQuery()->setFirstResult($postsPerPage * ($page - 1))->setMaxResults($postsPerPage) is what actually does the pagination.

We get the query from the paginator object, and then set the 1st result to the product of $postsPerPage * ($page - 1). This tells Doctrine Paginator to offset the results starting at a particular number. Finnaly we tell Doctrine the max amount of posts we want per page.

The result is the function returns the number of posts specified by $postsPerPage beginning from the result of setFirstResult(). Pretty simple huh?

php
1// src/Repository/ArticleRepository.php
2
3namespace App\Repository;
4
5use App\Entity\Article;
6use Doctrine\ORM\Tools\Pagination\Paginator;
7use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
8use Symfony\Bridge\Doctrine\RegistryInterface;
9
10class ArticleRepository extends ServiceEntityRepository {
11
12 public function __construct(RegistryInterface $registry) {
13 parent::__construct($registry, Article::class); }
14
15 public function getPaginatedPosts($page = 1, $postsPerPage = 9) {
16 $query = $this->createQueryBuilder('a')
17 ->orderBy('a.publishedAt', 'DESC')
18 ->getQuery();
19 $paginator = new Paginator($query);
20 $paginator->getQuery()
21 ->setFirstResult($postsPerPage * ($page - 1))
22 ->setMaxResults($postsPerPage);
23 return $paginator;
24 }
25
26 /**
27 * Assuming the associated Article entity has a many to one relationship to some Category entity.
28 */
29 public function getPaginatedPostsFromCategory($page = 1, $postsPerPage = 9, $category) {
30 $query = $this->createQueryBuilder('a')
31 ->leftJoin('a.category', 'c')
32 ->andWhere('c.slug = :val')
33 ->setParameter('val', $category)
34 ->orderBy('a.timestamp', 'DESC')
35 ->getQuery();
36 $paginator = new Paginator($query);
37 $paginator->getQuery()
38 ->setFirstResult($postsPerPage * ($page - 1))
39 ->setMaxResults($postsPerPage);
40 return $paginator;
41 }
42
43 /**
44 * Assuming the associated Article entity has a many to many relationship to some Tags entity.
45 */
46 public function getPaginatedPostsFromTag($page = 1, $postsPerPage = 9, $tag) {
47 $query = $this->createQueryBuilder('a')
48 ->leftJoin('a.tags', 'c')
49 ->andWhere('c.slug = :val')
50 ->setParameter('val', $tag)
51 ->orderBy('a.publishedAt', 'DESC')
52 ->getQuery();
53 $paginator = new Paginator($query);
54 $paginator->getQuery()
55 ->setFirstResult($limit * ($page - 1))
56 ->setMaxResults($limit);
57 return $paginator;
58 }
59}
60

- Comments -