学说覆盖所有实体的默认查找器方法

doctrine override default finder methods for all entity

有一种方法可以覆盖所有实体存储库的默认查找器方法 例如,这是 Doctrine\ORM\EntityRepository

中的默认方法 findBy
 public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
    {
        $persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);
        return $persister->loadAll($criteria, $orderBy, $limit, $offset);
    }    

但是我的需求是这样的

 public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
    {
        $persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);
        $criteria['foo'] = 'bar';
        return $persister->loadAll($criteria, $orderBy, $limit, $offset);
    }   

我想创建一个服务来通过修改条件数组并在需要时添加一些自定义条件属性来覆盖此方法。 我知道我可以覆盖每个实体的存储库,但我的项目已经扩大,现在我想要一个实用的解决方案来避免更改所有实体存储库。

您可以创建一个扩展 ServiceEntityRepository 的 class,并在其中 class 定义您希望覆盖的所有 class。最后,您将需要更新所有存储库以扩展这个新的 class 而不是 ServiceEntityRepository。

你不应该这样做。拥抱Doctrine Filters。使用一个,您可以在全局范围内为所有查询引入任何类型的逻辑。

参考@emix的回答这是更详细的解决方法

现在让我们创建注释。这将添加到 class 以指示将按学说过滤哪些字段。

/**
 * @Annotation
 * @Target("CLASS")
 */
final class CenterSelector
{
    public $centerFieldName;
}

并在您的 class

中使用它
 /**
 * @CenterSelector(centerFieldName="you-name-field")
 */
class CommercialPiece{
   protected $you-name-field;
}

创建从 SQLFilter

扩展的过滤器 class
class CenterFilter extends SQLFilter
{
    protected $reader;

    public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
    {

        if (empty($this->reader)) {
            return '';
        }

        // The Doctrine filter is called for any query on any entity
        // Check if the current entity is (marked with an annotation)
        $centerSelector = $this->reader->getClassAnnotation(
            $targetEntity->getReflectionClass(),
            CenterSelector::class
        );

        if (!$centerSelector) {
            return '';
        }

        // FieldName parameter in annotation
        $fieldName = $centerSelector->centerFieldName;

        try {
            $mySelector= $this->getParameter('my-selector');
        } catch (\InvalidArgumentException $e) {
            // No my-selector has been defined
            return '';
        }

        if (empty($fieldName) || empty($mySelector)) {
            return '';
        } else{
            var_dump($mySelector);
            // Add the Where clause in the request
            $query = sprintf('%s.%s = %s', $targetTableAlias, $fieldName, $mySelector);
        }

        return $query;
    }

    public function setAnnotationReader(Reader $reader)
    {
        $this->reader = $reader;
    }
}

并且我在 KernelRequest 上创建了一个监听器

  public function __construct(
        ObjectManager $em, 
        SessionInterface $session, 
        Reader $reader)
    {
        $this->em = $em;
        $this->session = $session;
        $this->reader = $reader;
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        $globalSelector = $this->session->get('my-global-selector');           
        $filter = $this->em->getFilters()->enable('center_filter');
        $filter->setParameter('my-selector', $globalSelector );
        $filter->setAnnotationReader($this->reader);
    }

最后不要忘记在config.yml

中添加这个
orm:
    entity_managers:
        default:
            auto_mapping: true
            filters:
                center_filter:
                    class: your-name-space\Filter\CenterFilter
                    enabled: true