Skip to content

Commit

Permalink
QueryBuilder in subresource
Browse files Browse the repository at this point in the history
  • Loading branch information
aratinau committed Jul 5, 2021
1 parent 2cab86c commit 6addf42
Show file tree
Hide file tree
Showing 8 changed files with 317 additions and 1 deletion.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Inspired from https://github.com/api-platform/demo

There is six examples in this repo
There is seven examples in this repo

## First Example use raw data from a csv file

Expand Down Expand Up @@ -86,6 +86,14 @@ Basic example showing how use and configure CollectionDataProvider

`api/furniture?page=2`

## Seventh example use QueryBuilder in subresource

DiscussionDataProvider show how use QueryBuilder and order by DESC the result

### Usage

`api/discussions/{id}/messages?page=1`

## Install

composer install
Expand Down
3 changes: 3 additions & 0 deletions fixtures/discussion.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
App\Entity\Discussion:
discussion_{1..100}:
name: <word(10, 700)>
4 changes: 4 additions & 0 deletions fixtures/message.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
App\Entity\Message:
message_{1..5000}:
content: <text(10, 700)>
discussion: '@discussion_*'
53 changes: 53 additions & 0 deletions src/DataProvider/DiscussionDataProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?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\RestrictedDataProviderInterface;
use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface;
use App\Entity\Message;
use Doctrine\Persistence\ManagerRegistry;

class DiscussionDataProvider implements SubresourceDataProviderInterface, 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 $resourceClass === Message::class;
}

public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null)
{
// $this->subresourceDataProvider->getSubresource($resourceClass, $identifiers, $context, $operationName);

$queryBuilder = $this->managerRegistry
->getManagerForClass($resourceClass)
->getRepository($resourceClass)
->createQueryBuilder('m')
->orderBy('m.id', 'DESC')
->innerJoin('m.discussion', 'd', 'WITH', 'm.discussion = :discussion')
->setParameter('discussion', $identifiers['id']['id'])
;

$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);
}

return $queryBuilder->getQuery()->getResult();
}
}
87 changes: 87 additions & 0 deletions src/Entity/Discussion.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\DiscussionRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use ApiPlatform\Core\Annotation\ApiSubresource;

/**
* @ApiResource()
* @ORM\Entity(repositoryClass=DiscussionRepository::class)
*/
class Discussion
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;

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

/**
* @ORM\OneToMany(targetEntity=Message::class, mappedBy="discussion", orphanRemoval=true)
* @ApiSubresource()
*/
private $messages;

public function __construct()
{
$this->messages = new ArrayCollection();
}

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;
}

/**
* @return Collection|Message[]
*/
public function getMessages(): Collection
{
return $this->messages;
}

public function addMessage(Message $message): self
{
if (!$this->messages->contains($message)) {
$this->messages[] = $message;
$message->setDiscussion($this);
}

return $this;
}

public function removeMessage(Message $message): self
{
if ($this->messages->removeElement($message)) {
// set the owning side to null (unless already changed)
if ($message->getDiscussion() === $this) {
$message->setDiscussion(null);
}
}

return $this;
}
}
61 changes: 61 additions & 0 deletions src/Entity/Message.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\MessageRepository;
use Doctrine\ORM\Mapping as ORM;

/**
* @ApiResource()
* @ORM\Entity(repositoryClass=MessageRepository::class)
*/
class Message
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;

/**
* @ORM\Column(type="text")
*/
private $content;

/**
* @ORM\ManyToOne(targetEntity=Discussion::class, inversedBy="messages")
* @ORM\JoinColumn(nullable=false)
*/
private $discussion;

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

public function getContent(): ?string
{
return $this->content;
}

public function setContent(string $content): self
{
$this->content = $content;

return $this;
}

public function getDiscussion(): ?Discussion
{
return $this->discussion;
}

public function setDiscussion(?Discussion $discussion): self
{
$this->discussion = $discussion;

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

namespace App\Repository;

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

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

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

/*
public function findOneBySomeField($value): ?Discussion
{
return $this->createQueryBuilder('d')
->andWhere('d.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
}
50 changes: 50 additions & 0 deletions src/Repository/MessageRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace App\Repository;

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

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

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

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

0 comments on commit 6addf42

Please sign in to comment.