Automatisons l'enregistrement du User sur n'importe quelle entité [Symfony]

aratinau

Aymeric Ratinaud

Posted on June 17, 2024

Automatisons l'enregistrement du User sur n'importe quelle entité [Symfony]

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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
// ...
Enter fullscreen mode Exit fullscreen mode

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

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

💖 💪 🙅 🚩
aratinau
Aymeric Ratinaud

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