ZF2, когда использовать getServiceLocator (), а когда не

Я действительно запутался в том, когда использовать getServiceLocator, а когда нет. В качестве примера:

+ Module -+ Helloworld --+ src ---+ Controller ----+ IndexController.php ----+ IndexControllerFactory.php ---+ Service ----+ LogginService.php ----+ GreetingService.php ----+ GreetingServiceFactory.php 

GreetingServiceFactory.php имеет контент:

 <?php namespace Helloworld\Service; use Zend\ServiceManager\FactoryInterface; use Zend\ServiceManager\ServiceLocatorInterface; class GreetingServiceFactory implements FactoryInterface { public function createService (ServiceLocatorInterface $serviceLocator) { $greetingService = new GreetingService(); $greetingService->setEventManager($serviceLocator->get('eventManager')); $loggingService = $serviceLocator->get('loggingService'); $greetingService->getEventManager()->attach('getGreeting', array( $loggingService, 'onGetGreeting' )); return $greetingService; } } 

И IndexControllerFactory.php имеет содержание:

 <?php namespace Helloworld\Controller; use Zend\ServiceManager\FactoryInterface; use Zend\ServiceManager\ServiceLocatorInterface; class IndexControllerFactory implements FactoryInterface { public function createService (ServiceLocatorInterface $serviceLocator) { $ctr = new IndexController(); $ctr->setGreetingService($serviceLocator->getServiceLocator() ->get('greetingService')); return $ctr; } } 

Как вы можете видеть, мне нужен $ serviceLocator-> getServiceLocator () в моей ControllerFactory, но не в моем ServiceFactory. Зачем? Оба используют один и тот же интерфейс ServiceLocatorInterface, который даже не определяет метод getServiceLocator ().

module.config.php:

 'controllers' => array( 'factories' => array( 'Helloworld\Controller\Index' => 'Helloworld\Controller\IndexControllerFactory' ) ) , 'service_manager' => array( 'invokables' => array( 'loggingService' => 'Helloworld\Service\LoggingService' ), 'factories' => array( 'greetingService'=> 'Helloworld\Service\GreetingServiceFactory' ), ) 

Буду признателен за разъяснения 🙂

Хорошего дня!

Solutions Collecting From Web of "ZF2, когда использовать getServiceLocator (), а когда не"

Метод getServiceLocator определен в AbstractPluginManager , поскольку он реализует ServiceLocatorAwareInterface . Как отметил Maks3w, он не является частью ServiceLocatorInterface , поэтому не используйте его при реализации фабрики услуг.

Вы можете в любом случае определить свою фабрику как закрытие и все еще использовать ее:

 class MyModule { public function getControllerConfig() { return array( 'factories' => array( 'IndexController' => function ( \Zend\ServiceManager\AbstractPluginManager $pm ) { $ctr = new IndexController(); $ctr->setGreetingService( $pm ->getServiceLocator() ->get('greetingService') ); return $ctr; }, ), ); } } 

Хотя в этом примере $pm действительно является экземпляром ServiceLocatorInterface , вам все равно нужно получить ссылку на «главный» диспетчер служб для доступа к 'greetingService' .

ZF2 использует разных менеджеров служб или менеджеров плагинов для контроллеров, служб, помощников просмотра, плагинов контроллеров и т. Д. Это главным образом для типа-намека (посмотрите на интерфейс AbstractPluginManager чтобы понять, как строгости строгости) и для обеспечения безопасности.

В этом случае проблема безопасности запрещает доступ к службам, которые не являются контроллерами, особенно с маршрутами с параметром динамического controller . Вот почему контроллеры хранятся в отдельном диспетчере подключаемых модулей.

Поскольку диспетчер плагинов контроллера создается из «главного» сервис-менеджера, он также инициализируется благодаря ServiceLocatorAwareInterface .

Чтобы это стало яснее, я добавил график отношений (не включает фабрику и не воспринимаю ее как действительный UML):

Псевдо-UML

Как вы можете видеть, мне нужен $ serviceLocator-> getServiceLocator () в моей ControllerFactory, но не в моем ServiceFactory. Зачем?

Заводский контроллер вызывается другим экземпляром служебного менеджера («ControllerLoader») на главный. Это значит, что диспетчер не может создать произвольный класс, созданный главным диспетчером сервиса.

В результате, $ serviceLocator контроллера factory не тот, который вам нужен, когда вы хотите получить «greetingService», поскольку «greetingService» зарегистрирован в главном сервис-менеджере. Чтобы получить главного диспетчера сервера из контроллера один, вы используете getServiceLocator (), и теперь у вас есть экземпляр главного диспетчера служб, из которого вы можете получить () «услугу приветствия»,

Это называется «пиринг». т.е. диспетчер службы «ControllerLoader» (тот, который настроен с помощью ключа «контроллеры» в конфигурации или getControllerConfiguration () в классе модуля) настроен с основным диспетчером службы как одноранговый узел.

В Denitively вы не используете getServiceLocator так как этот метод не определен в ServiceLocatorInterface вместо этого используйте get()

Я предлагаю это в качестве альтернативы, которая использует базовую установку module.config.php

Теперь я делал что-то подобное, но использовал что-то вроде этого.

 class BaseServices extends AbstractActionController implements ServiceLocatorAwareInterface{ ... public function setServiceLocator(ServiceLocatorInterface $serviceLocator){ if($serviceLocator instanceof ControllerManager){ $this->service_locator = $serviceLocator->getServiceLocator(); $this->entities_service = $this->service_locator ->get('entities_service'); $this->session = new Session(array( 'entities_service'=>$this->entities_service, 'service_locator'=>$this->service_locator, )); return $this; } } } ... } 

Теперь то, что меня насторожило, должно было прийти к осознанию того, что мне нужно было использовать только первый локатор сервисов, который используется во время создания любого контроллера, который расширяет этот класс …

При создании экземпляра: этот класс был сначала загружен ControllerManager, а затем ServiceManager для метода setServiceLocator.

Я только хотел использовать ControllerManger и его метод для получения ServiceManager для создания экземпляров моих фабрик;

частичное на моем module.config.php

 module.config.php { ... 'service_manager' => 'abstract_factories' => array( 'Zend\Log\LoggerAbstractServiceFactory', ), 'factories' => array( 'entities_service' => 'Service\Providers\Entities', ), 'invokables' => array( 'post' => 'Service\Controllers\Runtime\Post', ), ), } 

Теперь я мог бы использовать что-то вроде следующего, чтобы отфильтровать правильный ServiceLocator … но я поклонник использования как можно меньше плиты котла по мере необходимости …

 interface AbstractFactoryInterface { public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName); public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName); }