ZF2时,当不使用getServiceLocator()和(ZF2 when to use getS

2019-07-20 01:14发布

我在什么时候使用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但不是在我的服务工厂。 为什么? 都使用相同的接口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'
    ),
)

我会很感激任何澄清:)

祝你今天愉快!

Answer 1:

该方法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):



Answer 2:

正如你所看到的,我需要$ serviceLocator-> getServiceLocator()在我的ControllerFactory但不是在我的服务工厂。 为什么?

该控制器工厂是由不同的服务管理器实例(以下简称“ControllerLoader”)的主要原因之一调用。 这是为了让调度员不能在任意类由主服务管理器实例化的结果。

其结果是,控制器工厂的$服务定位不与主服务管理器注册时要检索“GreetingService的”你需要,为“GreetingService的”的人。 从控制器一个让主服务器管理器,您使用getServiceLocator(),你现在主要的服务管理器,从中可以得到的一个实例()“的问候语服务”

这就是所谓的“对等”。 即“ControllerLoader”服务管理器(一个经由在模块类的配置或getControllerConfiguration()的'控制器的键配置的)被设置与主服务管理器作为一个对等体。



Answer 3:

Denitively你shouln't使用getServiceLocator因为该方法没有定义ServiceLocatorInterface改用get()



Answer 4:

我提供这件事为使用基本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的一个,然后为setServiceLocator方法的ServiceManager。

我只是想用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',
    ),
  ),
}

现在,我可以使用类似下面来筛选合适的服务定位...但我需要使用尽可能少的锅炉板的粉丝...

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

  public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName);
} 


文章来源: ZF2 when to use getServiceLocator() and when not to