Nouvelle Discussion
A ce stade, si nous utilisons la route POST /discussions avec le payload
{
"participants": [
"/api/users/10",
"/api/users/11",
"/api/users/12"
]
}
Nous avons comme réponse
{
"@context": "/api/contexts/Discussion",
"@id": "/api/discussions/84",
"@type": "Discussion",
"id": 84,
"participants": [
"/api/users/10",
"/api/users/11",
"/api/users/12"
],
"messages": []
}
Mais nous voudrions pouvoir envoyer le premier message dans ce POST et également le retourner lors de la réponse de façon à avoir
{
"participants": [
"/api/users/10",
"/api/users/11",
"/api/users/12"
],
"contentMessage" : "Quae amet consequatur quod iusto non facere. Architecto aut molestias ea."
}
DTO CreateDiscussionInput
Pour ce faire, allons dans notre entité Discussion pour rajouter le DTO input
/**
* @ApiResource(
* collectionOperations={
* "post"={
* "input"=CreateDiscussionInput::class,
* "denormalization_context"={"groups"={"discussion:write"}},
* },
* "get"
* },
* normalizationContext={"groups"={"discussion:read"}},
* )
* @ORM\Entity(repositoryClass=DiscussionRepository::class)
*/
class Discussion
Il nous reste à le créer :
<?php
// src/DTO/CreateDiscussionInput.php
namespace App\DTO;
use App\Entity\User;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Serializer\Annotation\Groups;
class CreateDiscussionInput
{
/**
* @Groups({"discussion:write"})
*/
private $participants;
/**
* @Assert\NotBlank()
* @Groups({"discussion:write"})
*/
public $contentMessage;
public function __construct()
{
$this->participants = new ArrayCollection();
}
/**
* @return Collection|User[]
*/
public function getParticipants(): Collection
{
return $this->participants;
}
public function addParticipant(User $participant): self
{
if (!$this->participants->contains($participant)) {
$this->participants[] = $participant;
}
return $this;
}
public function removeParticipant(User $participant): self
{
$this->participants->removeElement($participant);
return $this;
}
}
Ainsi que son DataTransformer
<?php
// src/DataTransformer/CreateDiscussionInputDataTransformer.php
namespace App\DataTransformer;
use ApiPlatform\Core\DataTransformer\DataTransformerInterface;
use App\Entity\Discussion;
class CreateDiscussionInputDataTransformer implements DataTransformerInterface
{
/**
* {@inheritdoc}
*/
public function transform($data, string $to, array $context = [])
{
return $data;
}
/**
* {@inheritdoc}
*/
public function supportsTransformation($data, string $to, array $context = []): bool
{
// in the case of an input, the value given here is an array (the JSON decoded).
if ($data instanceof Discussion) {
return false;
}
return (Discussion::class === $to)
&& null !== ($context['input']['class'] ?? null)
&& (array_key_exists('collection_operation_name', $context))
&& $context['collection_operation_name'] === 'post';
}
}
Nous allons modifier le __construct de Discussion afin de lui envoyer directement la liste des participants
public function __construct($participants = null)
{
if ($participants) {
$this->participants = $participants;
} else {
$this->participants = new ArrayCollection();
}
}
Et enfin son DataPersister
<?php
namespace App\DataPersister;
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
use App\DTO\CreateDiscussionInput;
use App\Entity\Discussion;
use App\Entity\Message;
use Doctrine\ORM\EntityManagerInterface;
class DiscussionDataPersister implements ContextAwareDataPersisterInterface
{
private $entityManager;
public function __construct(EntityManagerInterface $entityManager) {
$this->entityManager = $entityManager;
}
public function supports($data, array $context = []): bool
{
return $data instanceof CreateDiscussionInput;
}
public function persist($data, array $context = [])
{
$discussion = new Discussion($data->getParticipants());
$message = new Message();
$message->setContent($data->contentMessage);
$message->setDiscussion($discussion);
$this->entityManager->persist($discussion);
$this->entityManager->persist($message);
$this->entityManager->flush();
return $discussion;
}
public function remove($data, array $context = [])
{
}
}
C'est dans DiscussionDataPersister que nous créons une nouvelle Discussion avec ses participants grâce à son __construct, puis nous créons un nouveau Message et nous l'attachons à cette Discussion.
En faisant POST /api/discussions
{
"participants": [
"/api/users/10",
"/api/users/11",
"/api/users/12"
],
"contentMessage" : "Quae amet consequatur quod iusto non facere. Architecto aut molestias ea."
}
Nous avons comme réponse :
{
"@context": "/api/contexts/Discussion",
"@id": "/api/discussions/87",
"@type": "Discussion",
"participants": [
"/api/users/10",
"/api/users/11",
"/api/users/12"
],
"messages": []
}
Nous allons créer un DTO output pour pouvoir afficher le message
DTO CreateDiscussionOutput
Dans Discussion rajoutez la ligne output
/**
* @ApiResource(
* collectionOperations={
* "post"={
* "input"=CreateDiscussionInput::class,
* "denormalization_context"={"groups"={"discussion:write"}},
* "output"=CreateDiscussionOutput::class
* },
* "get"
* },
* normalizationContext={"groups"={"discussion:read"}},
* )
* @ORM\Entity(repositoryClass=DiscussionRepository::class)
*/
class Discussion
Maintenant créons notre CreateDiscussionOutput
<?php
namespace App\DTO;
use Symfony\Component\Serializer\Annotation\Groups;
class CreateDiscussionOutput
{
/**
* @Groups({"discussion:read"})
*/
public $participants;
/**
* @Groups({"discussion:read"})
*/
public $contentMessage;
}
Ainsi que son DataTransformer
<?php
namespace App\DataTransformer;
use ApiPlatform\Core\DataTransformer\DataTransformerInterface;
use App\DTO\CreateDiscussionOutput;
use App\Entity\Discussion;
use App\Repository\MessageRepository;
class CreateDiscussionOutputDataTransformer implements DataTransformerInterface
{
private $messageRepository;
public function __construct(MessageRepository $messageRepository)
{
$this->messageRepository = $messageRepository;
}
/**
* @param Discussion $object
* @param string $to
* @param array $context
* @return CreateDiscussionOutput
*/
public function transform($object, string $to, array $context = [])
{
$output = new CreateDiscussionOutput();
$output->participants = $object->getParticipants();
$output->contentMessage = $this->messageRepository->findOneBy(['discussion' => $object->getId()])->getContent();
return $output;
}
public function supportsTransformation($data, string $to, array $context = []): bool
{
return CreateDiscussionOutput::class === $to && $data instanceof Discussion;
}
}
Dans transform nous créons une nouvelle instance de CreateDiscussionOutput et nous associons avec participants et contentMessage
Maintenant, en faisant un POST /api/discussions/
Nous avons comme retour :
{
"@context": {
"@vocab": "https://127.0.0.1:8080/api/docs.jsonld#",
"hydra": "http://www.w3.org/ns/hydra/core#",
"participants": "CreateDiscussionOutput/participants",
"contentMessage": "CreateDiscussionOutput/contentMessage"
},
"@type": "Discussion",
"@id": "/api/discussions/91",
"participants": [
"/api/users/10",
"/api/users/11",
"/api/users/12"
],
"contentMessage" : "Quae amet consequatur quod iusto non facere. Architecto aut molestias ea."
}
prev
next
Commentaires
Connectez-vous pour laisser un commentaire