Skip to content

Commit

Permalink
CarCollectionDataProvider with collectionExtensions and JobCollection…
Browse files Browse the repository at this point in the history
…DataProvider with paginationExtension
  • Loading branch information
aratinau committed Jul 5, 2021
1 parent 4d8d22a commit 53ce829
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 14 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@ data provider using repository (by group from normalization_context on Movie ent

## Fourth example use QueryBuilder in CarCollectionDataProvider

This example show how use queryBuilder in CarCollectionDataProvider and filter by color. The pagination is available
This example show how use QueryBuilder and filters with CollectionExtensions in CarCollectionDataProvider.
The collection is filtered by color from the `context` with the QueryBuilder and filtered by `name` and `isPublished` from SearchFilter in Car entity.
The pagination is available

### Usage

`/api/cars?color=color_name`
`/api/cars?color=color_name&isPublished=true|false&page=1`

#### Color name available

Expand All @@ -68,6 +70,10 @@ This example show how use queryBuilder in CarCollectionDataProvider and filter b
- yellow
- black

## Fifth example use JobCollectionDataProvider

This example show how use PaginationExtension in JobCollectionDataProvider

## Install

composer install
Expand Down
4 changes: 4 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ services:
#decorates: App\Repository\City\CityDataRepository

App\Repository\City\CityDataInterface: '@App\Repository\City\CityDataRepository'

App\DataProvider\CarCollectionDataProvider:
bind:
$collectionExtensions: !tagged api_platform.doctrine.orm.query_extension.collection
3 changes: 2 additions & 1 deletion fixtures/car.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
App\Entity\Car:
movie_{1..1000}:
car_{1..1000}:
name: <word(10, 700)>
color: '<randomElement( ["red", "orange", "green", "yellow", "black"] )>'
isPublished: '<numberBetween(0, 1)>'
4 changes: 4 additions & 0 deletions fixtures/job.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
App\Entity\Job:
job_{1..1000}:
name: <word(10, 700)>
isPublished: '<numberBetween(0, 1)>'
28 changes: 17 additions & 11 deletions src/DataProvider/CarCollectionDataProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace App\DataProvider;

use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\PaginationExtension;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterExtension;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator;
use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface;
Expand All @@ -13,12 +13,14 @@
final class CarCollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface
{
private $managerRegistry;
private $paginationExtension;
private $collectionExtensions;

public function __construct(ManagerRegistry $managerRegistry, PaginationExtension $paginationExtension)
public function __construct(ManagerRegistry $managerRegistry,
$collectionExtensions
)
{
$this->managerRegistry = $managerRegistry;
$this->paginationExtension = $paginationExtension;
$this->collectionExtensions = $collectionExtensions;
}

public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
Expand All @@ -28,9 +30,11 @@ public function supports(string $resourceClass, string $operationName = null, ar

public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable
{
$queryNameGenerator = new QueryNameGenerator();
$queryBuilder = $this->managerRegistry
->getManagerForClass($resourceClass)
->getRepository($resourceClass)->createQueryBuilder('c');
->getRepository($resourceClass)
->createQueryBuilder('c');

if (isset($context['filters']['color'])) {
$queryBuilder
Expand All @@ -39,14 +43,16 @@ public function getCollection(string $resourceClass, string $operationName = nul
;
}

$this->paginationExtension->applyToCollection($queryBuilder, new QueryNameGenerator(), $resourceClass, $operationName, $context);

if ($this->paginationExtension instanceof QueryResultCollectionExtensionInterface &&
$this->paginationExtension->supportsResult($resourceClass, $operationName, $context)) {
return $this->paginationExtension->getResult($queryBuilder, $resourceClass, $operationName, $context);
/** @var FilterExtension $extension */
foreach ($this->collectionExtensions as $extension) {
$extension->applyToCollection($queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context);
if ($extension instanceof QueryResultCollectionExtensionInterface &&
$extension->supportsResult($resourceClass, $operationName, $context)
) {
return $extension->getResult($queryBuilder, $resourceClass, $operationName, $context);
}
}

return $queryBuilder->getQuery()->getResult();

}
}
48 changes: 48 additions & 0 deletions src/DataProvider/JobCollectionDataProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace App\DataProvider;

use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\PaginationExtension;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator;
use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use App\Entity\Job;
use Doctrine\Persistence\ManagerRegistry;

final class JobCollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface
{
private $managerRegistry;
private $paginationExtension;

public function __construct(ManagerRegistry $managerRegistry, PaginationExtension $paginationExtension)
{
$this->managerRegistry = $managerRegistry;
$this->paginationExtension = $paginationExtension;
}

public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
{
return Job::class === $resourceClass;
}

public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable
{
$queryBuilder = $this->managerRegistry
->getManagerForClass($resourceClass)
->getRepository($resourceClass)
->createQueryBuilder('j')
;

$this->paginationExtension->applyToCollection($queryBuilder, new QueryNameGenerator(), $resourceClass, $operationName, $context);

if ($this->paginationExtension instanceof QueryResultCollectionExtensionInterface &&
// next line is from `attributes={"pagination_enabled"=true}` on Job entity
$this->paginationExtension->supportsResult($resourceClass, $operationName, $context))
{
return $this->paginationExtension->getResult($queryBuilder, $resourceClass, $operationName, $context);
}

return $queryBuilder->getQuery()->getResult();
}
}
23 changes: 23 additions & 0 deletions src/Entity/Car.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@
use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\CarRepository;
use Doctrine\ORM\Mapping as ORM;
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;

/**
* @ApiResource()
* @ApiFilter(SearchFilter::class, properties={
* "name": "exact",
* "isPublished": "exact"
* })
* @ORM\Entity(repositoryClass=CarRepository::class)
*/
class Car
Expand All @@ -29,6 +35,11 @@ class Car
*/
private $color;

/**
* @ORM\Column(type="boolean")
*/
private $isPublished;

public function getId(): ?int
{
return $this->id;
Expand Down Expand Up @@ -57,4 +68,16 @@ public function setColor(string $color): self

return $this;
}

public function getIsPublished(): ?bool
{
return $this->isPublished;
}

public function setIsPublished(bool $isPublished): self
{
$this->isPublished = $isPublished;

return $this;
}
}
61 changes: 61 additions & 0 deletions src/Entity/Job.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\JobRepository;
use Doctrine\ORM\Mapping as ORM;

/**
* @ApiResource(
* attributes={"pagination_enabled"=true}
* )
* @ORM\Entity(repositoryClass=JobRepository::class)
*/
class Job
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;

/**
* @ORM\Column(type="string", length=255)
*/
private $name;

/**
* @ORM\Column(type="boolean")
*/
private $isPublished;

public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}

public function setName(string $name): self
{
$this->name = $name;

return $this;
}

public function getIsPublished(): ?bool
{
return $this->isPublished;
}

public function setIsPublished(bool $isPublished): self
{
$this->isPublished = $isPublished;

return $this;
}
}
50 changes: 50 additions & 0 deletions src/Repository/JobRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace App\Repository;

use App\Entity\Job;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

/**
* @method Job|null find($id, $lockMode = null, $lockVersion = null)
* @method Job|null findOneBy(array $criteria, array $orderBy = null)
* @method Job[] findAll()
* @method Job[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class JobRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Job::class);
}

// /**
// * @return Job[] Returns an array of Job objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('j')
->andWhere('j.exampleField = :val')
->setParameter('val', $value)
->orderBy('j.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/

/*
public function findOneBySomeField($value): ?Job
{
return $this->createQueryBuilder('j')
->andWhere('j.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
}

0 comments on commit 53ce829

Please sign in to comment.