Skip to content

Commit 53ce829

Browse files
author
Aymeric Ratinaud
committed
CarCollectionDataProvider with collectionExtensions and JobCollectionDataProvider with paginationExtension
1 parent 4d8d22a commit 53ce829

File tree

9 files changed

+217
-14
lines changed

9 files changed

+217
-14
lines changed

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,13 @@ data provider using repository (by group from normalization_context on Movie ent
5454

5555
## Fourth example use QueryBuilder in CarCollectionDataProvider
5656

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

5961
### Usage
6062

61-
`/api/cars?color=color_name`
63+
`/api/cars?color=color_name&isPublished=true|false&page=1`
6264

6365
#### Color name available
6466

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

73+
## Fifth example use JobCollectionDataProvider
74+
75+
This example show how use PaginationExtension in JobCollectionDataProvider
76+
7177
## Install
7278

7379
composer install

config/services.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,7 @@ services:
2929
#decorates: App\Repository\City\CityDataRepository
3030

3131
App\Repository\City\CityDataInterface: '@App\Repository\City\CityDataRepository'
32+
33+
App\DataProvider\CarCollectionDataProvider:
34+
bind:
35+
$collectionExtensions: !tagged api_platform.doctrine.orm.query_extension.collection

fixtures/car.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
App\Entity\Car:
2-
movie_{1..1000}:
2+
car_{1..1000}:
33
name: <word(10, 700)>
44
color: '<randomElement( ["red", "orange", "green", "yellow", "black"] )>'
5+
isPublished: '<numberBetween(0, 1)>'

fixtures/job.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
App\Entity\Job:
2+
job_{1..1000}:
3+
name: <word(10, 700)>
4+
isPublished: '<numberBetween(0, 1)>'

src/DataProvider/CarCollectionDataProvider.php

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace App\DataProvider;
44

5-
use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\PaginationExtension;
5+
use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterExtension;
66
use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface;
77
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator;
88
use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface;
@@ -13,12 +13,14 @@
1313
final class CarCollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface
1414
{
1515
private $managerRegistry;
16-
private $paginationExtension;
16+
private $collectionExtensions;
1717

18-
public function __construct(ManagerRegistry $managerRegistry, PaginationExtension $paginationExtension)
18+
public function __construct(ManagerRegistry $managerRegistry,
19+
$collectionExtensions
20+
)
1921
{
2022
$this->managerRegistry = $managerRegistry;
21-
$this->paginationExtension = $paginationExtension;
23+
$this->collectionExtensions = $collectionExtensions;
2224
}
2325

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

2931
public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable
3032
{
33+
$queryNameGenerator = new QueryNameGenerator();
3134
$queryBuilder = $this->managerRegistry
3235
->getManagerForClass($resourceClass)
33-
->getRepository($resourceClass)->createQueryBuilder('c');
36+
->getRepository($resourceClass)
37+
->createQueryBuilder('c');
3438

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

42-
$this->paginationExtension->applyToCollection($queryBuilder, new QueryNameGenerator(), $resourceClass, $operationName, $context);
43-
44-
if ($this->paginationExtension instanceof QueryResultCollectionExtensionInterface &&
45-
$this->paginationExtension->supportsResult($resourceClass, $operationName, $context)) {
46-
return $this->paginationExtension->getResult($queryBuilder, $resourceClass, $operationName, $context);
46+
/** @var FilterExtension $extension */
47+
foreach ($this->collectionExtensions as $extension) {
48+
$extension->applyToCollection($queryBuilder, $queryNameGenerator, $resourceClass, $operationName, $context);
49+
if ($extension instanceof QueryResultCollectionExtensionInterface &&
50+
$extension->supportsResult($resourceClass, $operationName, $context)
51+
) {
52+
return $extension->getResult($queryBuilder, $resourceClass, $operationName, $context);
53+
}
4754
}
4855

4956
return $queryBuilder->getQuery()->getResult();
50-
5157
}
5258
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace App\DataProvider;
4+
5+
use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\PaginationExtension;
6+
use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface;
7+
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator;
8+
use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface;
9+
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
10+
use App\Entity\Job;
11+
use Doctrine\Persistence\ManagerRegistry;
12+
13+
final class JobCollectionDataProvider implements ContextAwareCollectionDataProviderInterface, RestrictedDataProviderInterface
14+
{
15+
private $managerRegistry;
16+
private $paginationExtension;
17+
18+
public function __construct(ManagerRegistry $managerRegistry, PaginationExtension $paginationExtension)
19+
{
20+
$this->managerRegistry = $managerRegistry;
21+
$this->paginationExtension = $paginationExtension;
22+
}
23+
24+
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
25+
{
26+
return Job::class === $resourceClass;
27+
}
28+
29+
public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable
30+
{
31+
$queryBuilder = $this->managerRegistry
32+
->getManagerForClass($resourceClass)
33+
->getRepository($resourceClass)
34+
->createQueryBuilder('j')
35+
;
36+
37+
$this->paginationExtension->applyToCollection($queryBuilder, new QueryNameGenerator(), $resourceClass, $operationName, $context);
38+
39+
if ($this->paginationExtension instanceof QueryResultCollectionExtensionInterface &&
40+
// next line is from `attributes={"pagination_enabled"=true}` on Job entity
41+
$this->paginationExtension->supportsResult($resourceClass, $operationName, $context))
42+
{
43+
return $this->paginationExtension->getResult($queryBuilder, $resourceClass, $operationName, $context);
44+
}
45+
46+
return $queryBuilder->getQuery()->getResult();
47+
}
48+
}

src/Entity/Car.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@
55
use ApiPlatform\Core\Annotation\ApiResource;
66
use App\Repository\CarRepository;
77
use Doctrine\ORM\Mapping as ORM;
8+
use ApiPlatform\Core\Annotation\ApiFilter;
9+
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
810

911
/**
1012
* @ApiResource()
13+
* @ApiFilter(SearchFilter::class, properties={
14+
* "name": "exact",
15+
* "isPublished": "exact"
16+
* })
1117
* @ORM\Entity(repositoryClass=CarRepository::class)
1218
*/
1319
class Car
@@ -29,6 +35,11 @@ class Car
2935
*/
3036
private $color;
3137

38+
/**
39+
* @ORM\Column(type="boolean")
40+
*/
41+
private $isPublished;
42+
3243
public function getId(): ?int
3344
{
3445
return $this->id;
@@ -57,4 +68,16 @@ public function setColor(string $color): self
5768

5869
return $this;
5970
}
71+
72+
public function getIsPublished(): ?bool
73+
{
74+
return $this->isPublished;
75+
}
76+
77+
public function setIsPublished(bool $isPublished): self
78+
{
79+
$this->isPublished = $isPublished;
80+
81+
return $this;
82+
}
6083
}

src/Entity/Job.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
namespace App\Entity;
4+
5+
use ApiPlatform\Core\Annotation\ApiResource;
6+
use App\Repository\JobRepository;
7+
use Doctrine\ORM\Mapping as ORM;
8+
9+
/**
10+
* @ApiResource(
11+
* attributes={"pagination_enabled"=true}
12+
* )
13+
* @ORM\Entity(repositoryClass=JobRepository::class)
14+
*/
15+
class Job
16+
{
17+
/**
18+
* @ORM\Id
19+
* @ORM\GeneratedValue
20+
* @ORM\Column(type="integer")
21+
*/
22+
private $id;
23+
24+
/**
25+
* @ORM\Column(type="string", length=255)
26+
*/
27+
private $name;
28+
29+
/**
30+
* @ORM\Column(type="boolean")
31+
*/
32+
private $isPublished;
33+
34+
public function getId(): ?int
35+
{
36+
return $this->id;
37+
}
38+
public function getName(): ?string
39+
{
40+
return $this->name;
41+
}
42+
43+
public function setName(string $name): self
44+
{
45+
$this->name = $name;
46+
47+
return $this;
48+
}
49+
50+
public function getIsPublished(): ?bool
51+
{
52+
return $this->isPublished;
53+
}
54+
55+
public function setIsPublished(bool $isPublished): self
56+
{
57+
$this->isPublished = $isPublished;
58+
59+
return $this;
60+
}
61+
}

src/Repository/JobRepository.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace App\Repository;
4+
5+
use App\Entity\Job;
6+
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
7+
use Doctrine\Persistence\ManagerRegistry;
8+
9+
/**
10+
* @method Job|null find($id, $lockMode = null, $lockVersion = null)
11+
* @method Job|null findOneBy(array $criteria, array $orderBy = null)
12+
* @method Job[] findAll()
13+
* @method Job[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
14+
*/
15+
class JobRepository extends ServiceEntityRepository
16+
{
17+
public function __construct(ManagerRegistry $registry)
18+
{
19+
parent::__construct($registry, Job::class);
20+
}
21+
22+
// /**
23+
// * @return Job[] Returns an array of Job objects
24+
// */
25+
/*
26+
public function findByExampleField($value)
27+
{
28+
return $this->createQueryBuilder('j')
29+
->andWhere('j.exampleField = :val')
30+
->setParameter('val', $value)
31+
->orderBy('j.id', 'ASC')
32+
->setMaxResults(10)
33+
->getQuery()
34+
->getResult()
35+
;
36+
}
37+
*/
38+
39+
/*
40+
public function findOneBySomeField($value): ?Job
41+
{
42+
return $this->createQueryBuilder('j')
43+
->andWhere('j.exampleField = :val')
44+
->setParameter('val', $value)
45+
->getQuery()
46+
->getOneOrNullResult()
47+
;
48+
}
49+
*/
50+
}

0 commit comments

Comments
 (0)