Skip to content

Commit 29ac71e

Browse files
author
Aymeric Ratinaud
committed
CommentSubresourceDataProvider
1 parent 6addf42 commit 29ac71e

File tree

8 files changed

+229
-7
lines changed

8 files changed

+229
-7
lines changed

README.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
# Api Platform Sort, Filter and Pagination on custom data
22

3-
Inspired from https://github.com/api-platform/demo
3+
Inspired by https://github.com/api-platform/demo
4+
5+
# Summary
6+
7+
- [First Example use raw data from a csv file] https://github.com/aratinau/api-platform-pagination#first-example-use-raw-data-from-a-csv-file
8+
- [Second example use custom controller] https://github.com/aratinau/api-platform-pagination#second-example-use-custom-controller
9+
- [Third example use MovieCollectionDataProvider and repository] https://github.com/aratinau/api-platform-pagination#third-example-use-MovieCollectionDataProvider-and-repository
10+
- [Fourth example use QueryBuilder in CarCollectionDataProvider (collectionExtensions)] https://github.com/aratinau/api-platform-pagination#fourth-example-use-QueryBuilder-in-CarCollectionDataProvider-(collectionExtensions)
11+
- [Fifth example use JobCollectionDataProvider (paginationExtension)] https://github.com/aratinau/api-platform-pagination#fifth-example-use-JobCollectionDataProvider-(paginationExtension)
12+
- [Sixth example use FurnitureDataProvider (collectionDataProvider)] https://github.com/aratinau/api-platform-pagination#sixth-example-use-FurnitureDataProvider-(collectionDataProvider)
13+
- [Seventh example use QueryBuilder in subresource]
14+
- [Eight example use QueryBuilder in subresource] https://github.com/aratinau/api-platform-pagination#eight-example-use-QueryBuilder-in-subresource
415

5-
There is seven examples in this repo
616

717
## First Example use raw data from a csv file
818

@@ -86,9 +96,15 @@ Basic example showing how use and configure CollectionDataProvider
8696

8797
`api/furniture?page=2`
8898

89-
## Seventh example use QueryBuilder in subresource
99+
## Seventh example : simple DataProvider using subresourceDataProvider
100+
101+
CommentSubresourceDataProvider show how use the standard behaviour
102+
103+
`api/movies/{id}/comments`
104+
105+
## Eight example use QueryBuilder in subresource
90106

91-
DiscussionDataProvider show how use QueryBuilder and order by DESC the result
107+
DiscussionSubresourceDataProvider show how use QueryBuilder and order by DESC the result
92108

93109
### Usage
94110

fixtures/comment.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
App\Entity\Comment:
2+
comment_{1..1000}:
3+
author: <name()>
4+
content: <text()>

fixtures/movie.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ App\Entity\Movie:
22
movie_{1..1000}:
33
title: <text(10, 700)>
44
isPublished: '<numberBetween(0, 1)>'
5+
comments: '<numberBetween(100, 200)>x @comment*'
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\DataProvider;
6+
7+
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
8+
use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface;
9+
use App\Entity\Comment;
10+
11+
final class CommentSubresourceDataProvider implements SubresourceDataProviderInterface, RestrictedDataProviderInterface
12+
{
13+
private $alreadyInvoked = false;
14+
private $subresourceDataProvider;
15+
16+
public function __construct(SubresourceDataProviderInterface $subresourceDataProvider)
17+
{
18+
$this->subresourceDataProvider = $subresourceDataProvider;
19+
}
20+
21+
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
22+
{
23+
return false === $this->alreadyInvoked && $resourceClass === Comment::class;
24+
}
25+
26+
public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null)
27+
{
28+
$this->alreadyInvoked = true;
29+
30+
return $this->subresourceDataProvider->getSubresource($resourceClass, $identifiers, $context, $operationName);
31+
}
32+
}

src/DataProvider/DiscussionDataProvider.php renamed to src/DataProvider/DiscussionSubresourceDataProvider.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use App\Entity\Message;
1111
use Doctrine\Persistence\ManagerRegistry;
1212

13-
class DiscussionDataProvider implements SubresourceDataProviderInterface, RestrictedDataProviderInterface
13+
class DiscussionSubresourceDataProvider implements SubresourceDataProviderInterface, RestrictedDataProviderInterface
1414
{
1515
private $managerRegistry;
1616

@@ -29,8 +29,6 @@ public function supports(string $resourceClass, string $operationName = null, ar
2929

3030
public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null)
3131
{
32-
// $this->subresourceDataProvider->getSubresource($resourceClass, $identifiers, $context, $operationName);
33-
3432
$queryBuilder = $this->managerRegistry
3533
->getManagerForClass($resourceClass)
3634
->getRepository($resourceClass)

src/Entity/Comment.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
namespace App\Entity;
4+
5+
use ApiPlatform\Core\Annotation\ApiResource;
6+
use App\Repository\CommentRepository;
7+
use Doctrine\ORM\Mapping as ORM;
8+
9+
/**
10+
* @ApiResource()
11+
* @ORM\Entity(repositoryClass=CommentRepository::class)
12+
*/
13+
class Comment
14+
{
15+
/**
16+
* @ORM\Id
17+
* @ORM\GeneratedValue
18+
* @ORM\Column(type="integer")
19+
*/
20+
private $id;
21+
22+
/**
23+
* @ORM\Column(type="string", length=255)
24+
*/
25+
private $author;
26+
27+
/**
28+
* @ORM\Column(type="text")
29+
*/
30+
private $content;
31+
32+
/**
33+
* @ORM\ManyToOne(targetEntity=Movie::class, inversedBy="comments")
34+
*/
35+
private $movie;
36+
37+
public function getId(): ?int
38+
{
39+
return $this->id;
40+
}
41+
42+
public function getAuthor(): ?string
43+
{
44+
return $this->author;
45+
}
46+
47+
public function setAuthor(string $author): self
48+
{
49+
$this->author = $author;
50+
51+
return $this;
52+
}
53+
54+
public function getContent(): ?string
55+
{
56+
return $this->content;
57+
}
58+
59+
public function setContent(string $content): self
60+
{
61+
$this->content = $content;
62+
63+
return $this;
64+
}
65+
66+
public function getMovie(): ?Movie
67+
{
68+
return $this->movie;
69+
}
70+
71+
public function setMovie(?Movie $movie): self
72+
{
73+
$this->movie = $movie;
74+
75+
return $this;
76+
}
77+
}

src/Entity/Movie.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44

55
use ApiPlatform\Core\Annotation\ApiResource;
66
use App\Repository\MovieRepository;
7+
use Doctrine\Common\Collections\ArrayCollection;
8+
use Doctrine\Common\Collections\Collection;
79
use Doctrine\ORM\Mapping as ORM;
810
use App\Controller\CustomMovieAction;
911
use Symfony\Component\Serializer\Annotation\Groups;
12+
use ApiPlatform\Core\Annotation\ApiSubresource;
1013

1114
/**
1215
* @ApiResource(
@@ -49,6 +52,17 @@ class Movie
4952
*/
5053
private $isPublished;
5154

55+
/**
56+
* @ORM\OneToMany(targetEntity=Comment::class, mappedBy="movie")
57+
* @ApiSubresource()
58+
*/
59+
private $comments;
60+
61+
public function __construct()
62+
{
63+
$this->comments = new ArrayCollection();
64+
}
65+
5266
public function getId(): ?int
5367
{
5468
return $this->id;
@@ -77,4 +91,34 @@ public function setIsPublished(bool $isPublished): self
7791

7892
return $this;
7993
}
94+
95+
/**
96+
* @return Collection|Comment[]
97+
*/
98+
public function getComments(): Collection
99+
{
100+
return $this->comments;
101+
}
102+
103+
public function addComment(Comment $comment): self
104+
{
105+
if (!$this->comments->contains($comment)) {
106+
$this->comments[] = $comment;
107+
$comment->setMovie($this);
108+
}
109+
110+
return $this;
111+
}
112+
113+
public function removeComment(Comment $comment): self
114+
{
115+
if ($this->comments->removeElement($comment)) {
116+
// set the owning side to null (unless already changed)
117+
if ($comment->getMovie() === $this) {
118+
$comment->setMovie(null);
119+
}
120+
}
121+
122+
return $this;
123+
}
80124
}

src/Repository/CommentRepository.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\Comment;
6+
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
7+
use Doctrine\Persistence\ManagerRegistry;
8+
9+
/**
10+
* @method Comment|null find($id, $lockMode = null, $lockVersion = null)
11+
* @method Comment|null findOneBy(array $criteria, array $orderBy = null)
12+
* @method Comment[] findAll()
13+
* @method Comment[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
14+
*/
15+
class CommentRepository extends ServiceEntityRepository
16+
{
17+
public function __construct(ManagerRegistry $registry)
18+
{
19+
parent::__construct($registry, Comment::class);
20+
}
21+
22+
// /**
23+
// * @return Comment[] Returns an array of Comment objects
24+
// */
25+
/*
26+
public function findByExampleField($value)
27+
{
28+
return $this->createQueryBuilder('c')
29+
->andWhere('c.exampleField = :val')
30+
->setParameter('val', $value)
31+
->orderBy('c.id', 'ASC')
32+
->setMaxResults(10)
33+
->getQuery()
34+
->getResult()
35+
;
36+
}
37+
*/
38+
39+
/*
40+
public function findOneBySomeField($value): ?Comment
41+
{
42+
return $this->createQueryBuilder('c')
43+
->andWhere('c.exampleField = :val')
44+
->setParameter('val', $value)
45+
->getQuery()
46+
->getOneOrNullResult()
47+
;
48+
}
49+
*/
50+
}

0 commit comments

Comments
 (0)