10
我想知道什麼是在EntityRepository類中的EventDispatcher注入的最佳做法。在EntityRepository中注入EventDispatcher的最佳方式是什麼?
我想知道什麼是在EntityRepository類中的EventDispatcher注入的最佳做法。在EntityRepository中注入EventDispatcher的最佳方式是什麼?
首先,使用global
是very 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
方法t你的倉庫。
的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();
我CAM這裏有同樣的問題,而你的答案是有道理的。但是,現在經理有2個職責,代理庫和提高事件。這是一個非常「迂腐」的問題,但是你在哪裏停止重構來獲取SRP? – JorgeeFG
@JorgeeFG IMO,你可以通過在你的管理器中給出一個'OptionsResolver :: resolve($ options)'和'ResultHandler :: handle($ results)'(它們都會調用一個事件)來再次重構它。然後經理將作爲一個簡單的Facade來連接所有三個組件。然而,我真的覺得添加這兩個接口會開始變得越來越多,因爲通過改變它們的行爲幾乎沒有任何改進/改變,因爲它們中的大多數可以在事件處理程序中完成。 – Touki