Reputation: 113
I'm using API-Platform for a projetc. And in this project, I have two resources (Donateur and Don) releted by a ManyToOne relation. One Don is releted to One Donateur and One Donateur can be releted to more Dons. I have a data persister which persists resources in database.
Donateur.php
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\DonateurRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ApiResource(
* normalizationContext={
* "groups"={
* "read:Donateur:collection"
* }
* },
* denormalizationContext={
* "groups"={
* "write:Donateur"
* }
* },
* collectionOperations={
* "get", "post"
* },
* itemOperations={
* "get", "patch", "delete"
* }
* )
* @ORM\Entity(repositoryClass=DonateurRepository::class)
*/
class Donateur
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @Groups("read:Donateur:collection")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
* @Groups({"read:Donateur:collection", "write:Donateur"})
*/
private $nom;
/**
* @ORM\Column(type="float")
* @Groups({"read:Donateur:collection", "write:Don"})
*/
private $solde;
/**
* @ORM\OneToMany(targetEntity=Don::class, mappedBy="donateur")
*/
private $dons;
Don.php
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\DonRepository;
use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ApiResource(
* normalizationContext={
* "groups"={
* "read:Don:item",
* "read:Don:collection"
* }
* },
* denormalizationContext={
* "groups"={
* "write:Don"
* }
* },
* collectionOperations={
* "get", "post"
* },
* itemOperations={
* "get"={
* "normalization_context"={
* "groups"={
* "read:Don:item",
* "read:Don:collection"
* }
* }
* },
* "patch", "delete"
* }
* )
* @ORM\Entity(repositoryClass=DonRepository::class)
*/
class Don
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity=Donateur::class, inversedBy="dons")
* @ORM\JoinColumn(nullable=false)
* @Groups({"read:Don:collection", "write:Don"})
*/
private $donateur;
/**
* @ORM\Column(type="date", nullable=true)
* @Groups({"read:Don:collection", "write:Don"})
*/
private $date;
/**
* @ORM\Column(type="float")
* @Groups({"read:Don:collection", "write:Don"})
*/
private $montant;
The property $solde in Donateur must increase when we save a new Don. And the value which must be added is value of $montant of Don resource.
When I try this code
<?php
namespace App\EventListener;
use ApiPlatform\Core\EventListener\EventPriorities;
use App\Entity\Don;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Security;
class UpdateSoldeDonateurSubscriber implements EventSubscriberInterface
{
private $security;
public function __construct(Security $security)
{
$this->security = $security;
}
public static function getSubscribedEvents()
{
return [
KernelEvents::VIEW => ["updateSoldeDonateur", EventPriorities::POST_WRITE]
];
}
public function updateSoldeDonateur(ViewEvent $event)
{
$data = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
$user = $this->security->getUser();
//On va mettre à jour le solde du donateur. On récupère d'abord l'ancien solde puis on y ajoute le nouveau
if($data instanceof Don){
$ancienSolde = $data->getDonateur()->getSolde();
$nouveauSolde = $ancienSolde + $data->getMontant();
if($method === 'POST'){
$data->getDonateur()->setSolde($nouveauSolde);
}
elseif($method === 'PATCH'){
}
// dd($data->getDonateur(), $ancienSolde, $nouveauSolde);
}
}
}
solde didn't change. I think that it is caused by the data persister but I don't know how can I fix it.
These are my datapersisters
<?php
namespace App\DataPersister;
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
use App\Entity\Donateur;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Security;
class DonateurDataPersister implements ContextAwareDataPersisterInterface
{
private $manager;
private $security;
public function __construct(EntityManagerInterface $manager, Security $security)
{
$this->manager = $manager;
$this->security = $security;
}
public function supports($data, array $context = []): bool
{
return $data instanceof Donateur;
}
public function persist($data, array $context = [])
{
$this->manager->persist($data);
$this->manager->flush();
return $data;
}
public function remove($data, array $context = [])
{
$data->setIsDeleted(true);
$data->setDeletedBy($this->security->getUser());
$data->setDeletedAt(new \DateTime());
$this->manager->flush();
}
}
<?php
namespace App\DataPersister;
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
use App\Entity\Don;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Security;
class DonDataPersister implements ContextAwareDataPersisterInterface
{
private $manager;
private $security;
public function __construct(EntityManagerInterface $manager, Security $security)
{
$this->manager = $manager;
$this->security = $security;
}
public function supports($data, array $context = []): bool
{
return $data instanceof Don;
}
public function persist($data, array $context = [])
{
$this->manager->persist($data);
$this->manager->flush();
return $data;
}
public function remove($data, array $context = [])
{
$data->setIsDeleted(true);
$data->setDeletedBy($this->security->getUser());
$data->setDeletedAt(new \DateTime());
$this->manager->flush();
}
}
Some ideas to help me please
Upvotes: 0
Views: 570
Reputation: 1443
Your subscriber have been called after writing to the database and you should to flush after making changes in it or use another event that called before writing (PRE_WRITE
, in example), as I mentioned in the comment.
Upvotes: 1