Imaginez avoir dans votre projet plusieurs entités avec la relation author
comme par exemple ces deux entités suivantes :
<?php namespace App\Entity; use ApiPlatform\Metadata\ApiResource; use App\Repository\CourierFavoriteRepository; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: CourierFavoriteRepository::class)] #[ApiResource()] class Book { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] private ?int $id = null; #[ORM\ManyToOne] #[ORM\JoinColumn(nullable: false)] private ?User $author = null; #[ORM\Column(length: 255)] private ?string $title = null; public function getId(): ?int { return $this->id; } public function getAuthor(): ?User { return $this->author; } public function setAuthor(?User $author): static { $this->author = $author; return $this; } public function getTitle(): ?string { return $this->title; } public function setTitle(string $title): self { $this->title = $title; return $this; } }
<?php namespace App\Entity; use ApiPlatform\Metadata\ApiResource; use App\Repository\TodoRepository; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: TodoRepository::class)] #[ApiResource()] class Todo { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] private ?int $id = null; #[ORM\ManyToOne] #[ORM\JoinColumn(nullable: false)] private ?User $author = null; #[ORM\Column(type: Types::TEXT)] private ?string $content = null; public function getId(): ?int { return $this->id; } public function getAuthor(): ?User { return $this->author; } public function setAuthor(?User $author): static { $this->author = $author; return $this; } public function getContent(): ?string { return $this->content; } public function setContent(string $content): static { $this->content = $content; return $this; } }
Nous voulons verrouiller les résultats des GET item et collection uniquement sur l'user connecté.
Nous allons créer une interface que nous implémenterons sur nos entités
<?php namespace App\Entity; interface CurrentUserIsAuthorInterface { public function setAuthor(?User $author): static; }
Maitenant nous allons faire une DoctrineExtension
qui va ajouter la contrainte where
dans le QueryBuilder
sur l'utilisateur connecté.
<?php namespace App\DoctrineExtension; use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Metadata\Operation; use App\Entity\CurrentUserIsAuthorInterface; use Doctrine\ORM\QueryBuilder; use Symfony\Bundle\SecurityBundle\Security; class CurrentUserIsAuthorExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface { public function __construct( private Security $security, ) { } public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, ?Operation $operation = null, array $context = []): void { $this->currentUserIsAuthor($resourceClass, $queryBuilder); } public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, ?Operation $operation = null, array $context = []): void { $this->currentUserIsAuthor($resourceClass, $queryBuilder); } /** * @param string $resourceClass * @param QueryBuilder $queryBuilder * @return void * @throws ReflectionException */ public function currentUserIsAuthor(string $resourceClass, QueryBuilder $queryBuilder): void { $reflectionClass = new \ReflectionClass($resourceClass); if ($reflectionClass->implementsInterface(CurrentUserIsAuthorInterface::class)) { $alias = $queryBuilder->getRootAliases()[0]; $queryBuilder->andWhere("$alias.author = :current_author") ->setParameter('current_author', $this->security->getUser()->getId()); } } }
Maintenant il nous reste à implémenter notre interface sur nos entités :
<?php namespace App\Entity; use ApiPlatform\Metadata\ApiResource; use App\Repository\CourierFavoriteRepository; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: CourierFavoriteRepository::class)] #[ApiResource()] class Book implements CurrentUserIsAuthorInterface { // ...
<?php namespace App\Entity; use ApiPlatform\Metadata\ApiResource; use App\Repository\TodoRepository; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: TodoRepository::class)] #[ApiResource()] class Todo implements CurrentUserIsAuthorInterface { // ...
Et c'est tout. Pour chaque GET item ou collection vous aurez uniquement les entrées avec l'utilisateurs qui est connecté 🚀
Lisez aussi "comment enregistrer automatiquement l'utilisateur connecté" : https://dev.to/aratinau/automatisons-lenregistrement-du-user-sur-nimporte-quelle-entite-4f68
Top comments (0)