在EntityRepository中注入EventDispatcher的最佳方法是什么?

时间:2013-10-15 11:40:21

标签: php symfony doctrine-orm

我想知道EntityRepository类中EventDispatcher注入的最佳实践。

1 个答案:

答案 0 :(得分:20)

首先,使用globalvery bad practice。我强烈建议你不要这样做 其次,将服务注入存储库似乎不是一个好主意。它经常会破坏Single Responsibility Principle等法律。

我将创建一个管理器,它将包装存储库的方法,并将触发您需要的事件。有关详细信息,请参阅how to inject repository to a service

services.yml

services:
    my_manager:
        class: Acme\FooBundle\MyManager
        arguments:
            - @acme_foo.repository
            - @event_dispatcher

    acme_foo.repository:
        class: Acme\FooBundle\Repository\FooRepository
        factory_service: doctrine.orm.entity_manager
        factory_method: getRepository
        arguments:
            - "AcmeFooBundle:Foo"

的Acme \ FooBundle \ MyManager

use Acme\FooBundle\Repository\FooRepository;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

class MyManager
{
    protected $repository;
    protected $dispatcher;

    public function __construct(FooRepository $repository, EventDispatcherInterface $dispatcher)
    {
        $this->repository = $repository;
        $this->dispatcher = $dispatcher;
    }

    public function findFooEntities(array $options = array())
    {
        $event = new PreFindEvent;
        $event->setOptions($options);

        $this->dispatcher->dispatch('find_foo.pre_find', $event);

        $results = $this->repository->findFooEntities($event->getOptions());

        $event = new PostFindEvent;
        $event->setResults($results);

        $this->dispatcher->dispatch('find_foo.post_find', $event);

        return $event->getResults();
    }
}

然后您可以在控制器中使用它,就像服务一样。

$this->get('my_manager')->findFooEntities($options);

但是,如果确实需要将事件调度程序注入您的实体,则可以执行此操作

services.yml

services:
    acme_foo.repository:
        class: Acme\FooBundle\Repository\FooRepository
        factory_service: doctrine.orm.entity_manager
        factory_method: getRepository
        arguments:
            - "AcmeFooBundle:Foo"
        calls:
            - [ "setEventDispatcher", [ @event_dispatcher ] ]

然后您只需将setEventDispatcher方法添加到存储库中。

的Acme \ FooBundle \库\ FooRepository

class FooRepository extends EntityRepository
{
    protected $dispatcher;

    public function setEventDispatcher(EventDispatcherInterface $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }

    public function findFooEntities(array $options = array())
    {
        $dispatcher = $this->dispatcher;

        // ...
    }
}

在控制器中使用它时,只需确保调用服务而不是存储库。

<强> DO

$this->get('acme_foo.repository')->findFooEntities();

<强>不

$this->getDoctrine()->getManager()->getRepository('AcmeFooBundle:Foo')->findFooEntities();