D
D
Daria Motorina2020-08-09 21:39:10
symfony
Daria Motorina, 2020-08-09 21:39:10

How to properly serialize a collection of elements with pagination data?

There is Symfony 5, you need to create a couple of endpoints that return a list of elements with pagination.
I decided to use FosRestBundle + babdev/pagerfanta-bundle , because half of the API Platform documentation is incomprehensible and difficult to adapt to myself without rewriting a third of the project.
I decided to make pagination following the example of the SymfonyCasts lesson (adapted to the modern version).
Source:

src/AppBundle/Pagination/PaginationFactory.php

<?php
namespace AppBundle\Pagination;
use Doctrine\ORM\QueryBuilder;
use Pagerfanta\Adapter\DoctrineORMAdapter;
use Pagerfanta\Pagerfanta;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
class PaginationFactory
{
    private $router;
    public function __construct(RouterInterface $router)
    {
        $this->router = $router;
    }
    public function createCollection(QueryBuilder $qb, Request $request, $route, array $routeParams = array())
    {
        $page = $request->query->get('page', 1);
        $adapter = new DoctrineORMAdapter($qb);
        $pagerfanta = new Pagerfanta($adapter);
        $pagerfanta->setMaxPerPage(10);
        $pagerfanta->setCurrentPage($page);
        $programmers = [];
        foreach ($pagerfanta->getCurrentPageResults() as $result) {
            $programmers[] = $result;
        }
        $paginatedCollection = new PaginatedCollection($programmers, $pagerfanta->getNbResults());
        $createLinkUrl = function($targetPage) use ($route, $routeParams) {
            return $this->router->generate($route, array_merge(
                $routeParams,
                array('page' => $targetPage)
            ));
        };
        $paginatedCollection->addLink('self', $createLinkUrl($page));
        $paginatedCollection->addLink('first', $createLinkUrl(1));
        $paginatedCollection->addLink('last', $createLinkUrl($pagerfanta->getNbPages()));
        if ($pagerfanta->hasNextPage()) {
            $paginatedCollection->addLink('next', $createLinkUrl($pagerfanta->getNextPage()));
        }
        if ($pagerfanta->hasPreviousPage()) {
            $paginatedCollection->addLink('prev', $createLinkUrl($pagerfanta->getPreviousPage()));
        }
        return $paginatedCollection;
    }
}

The controller action from the tutorial

public function listAction(Request $request)
    {
        $qb = $this->getDoctrine()
            ->getRepository('AppBundle:Programmer')
            ->findAllQueryBuilder();
        $paginatedCollection = $this->get('pagination_factory')
            ->createCollection($qb, $request, 'api_programmers_collection');
        $response = $this->createApiResponse($paginatedCollection, 200);
        return $response;
    }


My PaginatedCollection object before serialization

5f3041ffce1cb849175598.png

The collection is formed correctly, it has all the elements of the entity for the page and pagination links, but serialization does not work - it outputs an empty array (both through the standard symfony serializer component and through json_encode).

Need to write a custom serializer for PaginatedCollection?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Daria Motorina, 2020-08-09
@glaphire

It was necessary to implement JsonSerializable in the PaginatedCollection class in order for the serializer to start working with this class

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question