Search code examples
symfonydoctrineapi-platform.com

Howt o use DTO for elements of a GetCollection operation in api-platform 3 without loosing doctrine query based pagination info


I would like to have an endpoint for listing of an entity, which is a doctrine managed entity. In this listing endpoint I want some properties which are not part of the entity. As stated in documentation this should be represented by an DTO where I can modify the representation. For single entity GET operation this works fine.

For the GetCollection operation I need a provider where I can instanciate the dto's. To maintain the doctrine filter and pagination logic I duplicated the default doctrine Provider (ApiPlatform\Doctrine\Orm\State\CollectionProvider)

In this provider I got a ApiPlatform\Doctrine\Orm\Paginator Object. I can iterate that and build a result set(array) of my DTO's and return that, but then I lose the pagination information in the serialized output.

How can I preserve this information?

A solution based on Benjamins answer(I'm not allowed to edit there):

# reuse doctrine collection provider
App\State\EntityProvider:
    bind:
        $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
------
EntityProvider implements ProviderInterface {
    public function __construct(
        readonly private ProviderInterface $collectionProvider, readonly private ResourceMetadataCollectionFactoryInterface $collectionFactory){}
        
    public function provide(...)
        $collection = $this->collectionFactory->create...
        $paginator = $this->collectionProvider->provide($collection, $uriVariables, $context);
        
        #rewrite resultset
        $results_new = []; 
        foreach($paginator as $result ) {
            $results_new[] = ...}
            
        return new TraversablePaginator(new \ArrayObject($results_new), $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems());
    }
}

Solution

  • Following the documentation, you should just return in your custom provider a ApiPlatform\State\Pagination\PartialPaginatorInterface or a ApiPlatform\State\Pagination\PaginatorInterface and API-Platform will take care of the rest. You have already implemented object available:

    • ApiPlatform\State\Pagination\ArrayPaginator
    • ApiPlatform\State\Pagination\TraversablePaginator