Познакомимся на примере с фильтрами в доктрине.
Цель: сделать так, чтобы неавторизованный пользователь видел только публичные статьи ( Article ).
Создаем наш фильтр:
<?php
declare(strict_types=1);
namespace App\EntityFilter;
use App\Entity\Article;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\Filter\SQLFilter;
/**
* https://symfonycasts.com/screencast/doctrine-queries/filters
* https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/filters.html
*/
class ArticleFilter extends SQLFilter
{
/**
* По мотивам https://symfonycasts.com/screencast/doctrine-queries/filters
*
* @inheritDoc
*/
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{
if ($targetEntity->getName() === Article::class) {
return $targetTableAlias.'.isShow = 1';
}
return '';
}
}Расскажем доктрине про наш фильтр:
doctrine:
orm:
auto_generate_proxy_classes: true
default_entity_manager: entity_manager_oltp
entity_managers:
entity_manager_oltp:
filters:
article_filter:
class: App\EntityFilter\ArticleFilter
# enabled: true - закммментировали, по умолчанию: falseВключаем фильтр, только если пользователь не авторизован:
<?php
declare(strict_types=1);
namespace App\EventListener;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
class DataAccessListener
{
private ?UserInterface $user;
private EntityManagerInterface $entityManager;
public function __construct(Security $security, EntityManagerInterface $entityManager)
{
$this->user = $security->getUser();
$this->entityManager = $entityManager;
}
public function onKernelController(ControllerEvent $event): void
{
if ($this->user === null) {
$this->entityManager
->getFilters()
->enable('article_filter');
}
}
}Подпишем нашего слушателя на событие:
services:
App\EventListener\DataAccessListener:
tags:
- { name: kernel.event_listener, event: kernel.controller }Готово.
Создаем наш фильтр сразу вместе с Security :
<?php
declare(strict_types=1);
namespace App\EntityFilter;
use App\Entity\Article;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\Filter\SQLFilter;
use Symfony\Component\Security\Core\Security;
/**
* https://symfonycasts.com/screencast/doctrine-queries/filters
* https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/filters.html
*/
class ArticleFilter extends SQLFilter
{
private ?Security $security = null;
public function setSecurity(Security $security)
{
$this->security = $security;
}
/**
* По мотивам https://symfonycasts.com/screencast/doctrine-queries/filters
*
* @inheritDoc
*/
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{
if ($this->security && $this->security->getUser() !== null) {
return '';
}
if ($targetEntity->getName() === Article::class) {
return $targetTableAlias.'.isShow = 1';
}
return '';
}
}Инъектим Security :
App\EntityFilter\ArticleFilter:
calls:
- setSecurity: [ '@security.helper' ]Расскажем доктрине про наш фильтр:
doctrine:
orm:
auto_generate_proxy_classes: true
default_entity_manager: entity_manager_oltp
entity_managers:
entity_manager_oltp:
filters:
article_filter:
class: App\EntityFilter\ArticleFilter
enabled: trueГотово.