为了确保每个用户只获取属于其帐户的数据,我尝试创建一个教义过滤器,使用 setter (setSecurity) 和 #[Required] 属性向其注入安全服务,然后在 addFilterConstraint 方法中,我得到用户并创建所需的约束 SQL,但不幸的是由于某种原因 setter 注入不起作用并且 setSecurity 从未执行!
我正在使用 Symfony 6.3.4
<?php
namespace App\Doctrine\Filter;
use App\Entity\User;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\Filter\SQLFilter;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Contracts\Service\Attribute\Required;
class AccountFilter extends SQLFilter
{
private ?Security $security = null;
#[Required]
public function setSecurity(Security $security)
{
$this->security = $security;
}
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias): string
{
// check if the entity has the account field
if (!$targetEntity->hasAssociation('account')) {
return '';
}
$accountColumnName = $targetEntity->getSingleAssociationJoinColumnName('account');
if ($this->security === null) {
return '';
}
$user = $this->security->getUser();
if (!$user instanceof User) {
return '';
}
return sprintf('%s.%s = %s', $targetTableAlias, $accountColumnName, $user->getAccount()->getId());
}
}
可悲的是,处理过滤器并由可能的学说实例化的FilterCollection仅接收过滤器的类名,并在启用时实例化它(这可能会自动发生)。
据我所知,学说和 symfony 仅使用 one 实体管理器,并且显然过滤器集合保留在查询之间,因此您可以通过从内核事件侦听器中的实体管理器获取过滤器来注入您的安全性(其中您可以通过标准依赖项注入或其他方式请求安全服务,然后显式设置安全性。
$entityManager->getFilters()->getFilter([your filter name])->setSecurity($security);
但是,当过滤器disabled时,根据源代码,当再次enabled时,它将被完全删除并再次实例化。如果您想“禁用”多个查询的过滤器,则必须使用暂停/恢复。这可能与您相关或不相关。