Aymeric Ratinaud
Posted on June 17, 2024
Admettons que nous ayons des entités avec l'attribut author
, nous allons voir comment factoriser la logique en une ligne pour enregistrer l'utilisateur automatiquement.
Prenons l'exemple de cette entité qui contient l'attribut author
.
<?php
namespace App\Entity;
use App\Repository\CategoryRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: CategoryRepository::class)]
class Category
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $name = null;
#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: false)]
private ?User $author = null;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
public function getAuthor(): ?User
{
return $this->author;
}
public function setAuthor(?User $author): static
{
$this->author = $author;
return $this;
}
}
Dans notre projet nous avons également une dizaine d'entités qui contient également l'attribut author
.
La premiere solution serait de faire un controller ou un DoctrineListener pour chaque entité. Comme celui-là par exemple :
<?php
namespace App\DoctrineListener;
use App\Entity\Category;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener;
use Doctrine\ORM\Events;
use Doctrine\Persistence\Event\LifecycleEventArgs;
#[AsEntityListener(event: Events::prePersist, entity: Category::class)]
class CategoryDoctrineListener
{
public function __construct(
private Security $security,
) {
}
public function prePersist(Category $category, LifecycleEventArgs $event)
{
$user = $this->security->getUser();
$entity->setAuthor($user);
}
}
Au lieu de ça nous allons garder la logique métier de CategoryDoctrineListener
et l'adapter à toutes les entités qui contiennent l'attribut author
Pour cela nous allons faire une interface
<?php
namespace App\Entity;
interface AuthorInterface
{
public function setAuthor(?User $author): static;
}
Ainsi nous allons l'implementer sur toutes les entités qui ont la méthode setAuthor
Exemple avec Catégory
<?php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use App\Repository\CategoryRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Attribute\Groups;
#[ORM\Entity(repositoryClass: CategoryRepository::class)]
#[ApiResource(paginationEnabled: false)]
class Category implements AuthorInterface
// ...
Maintenant nous pouvons créer un DoctrineListener qui regarde si l'entité implemente AuthorInterface
en utilisant la réflexion comme suit
<?php
namespace App\DoctrineListener;
use App\Entity\AuthorInterface;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\PrePersistEventArgs;
use Symfony\Bundle\SecurityBundle\Security;
#[AsDoctrineListener('prePersist')]
class AttachAuthorDoctrineListener
{
public function __construct(
private Security $security,
) {
}
public function prePersist(PrePersistEventArgs $event): void
{
$entity = $event->getObject();
$reflectionClass = new \ReflectionClass($entity);
if (!$reflectionClass->implementsInterface(AuthorInterface::class)) {
return;
}
$user = $this->security->getUser();
$entity->setAuthor($user);
}
}
Et c'est tout, maintenant vous n'aurez qu'à ajouter implements AuthorInterface
sur les entités qui ont besoin d'enregistrer l'auteur 🚀
Lisez aussi "comment filtrer les GET uniquement sur l'utilisateur connecté" https://dev.to/aratinau/api-platform-filtrer-les-resultats-uniquement-sur-lutilisateur-connecte-1fp6
Posted on June 17, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 2, 2024
June 25, 2024