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)