douti6740 2013-02-16 15:36
浏览 24
已采纳

ZF2何时使用getServiceLocator()而何时不使用

I am really confused on when to use getServiceLocator and when not to. As an example:

+ Module
-+ Helloworld
--+ src
---+ Controller
----+ IndexController.php
----+ IndexControllerFactory.php

---+ Service
----+ LogginService.php
----+ GreetingService.php
----+ GreetingServiceFactory.php

GreetingServiceFactory.php has the content:

<?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;
    }
}

And IndexControllerFactory.php has the content:

<?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;
    }
}

As you can see, I need $serviceLocator->getServiceLocator() in my ControllerFactory but not in my ServiceFactory. Why? Both use the same interface ServiceLocatorInterface which does not even define the getServiceLocator() method.

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'
    ),
)

I'd appreciate any clarification :)

Have a nice day!

  • 写回答

4条回答 默认 最新

  • douliaotong4944 2013-02-16 21:11
    关注

    The method getServiceLocator is defined on the AbstractPluginManager, since it implements the ServiceLocatorAwareInterface. As Maks3w pointed out, it is not part of the ServiceLocatorInterface, so avoid using it when implementing a service factory.

    You can anyway define your factory as closure and still use it:

    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;
                    },
                ),
            );
        }
    }
    

    While in this example $pm is indeed a ServiceLocatorInterface instance, you will still need to get a reference to the "main" service manager to access the 'greetingService'.

    ZF2 uses different service managers or plugin managers for controllers, services, view helpers, controller plugins, etc... That is mainly for type-hinting (look at the interface of the AbstractPluginManager to understand how type strictness is achieved) and for security.

    In this case, the security issue is disallowing access to services that are not controllers, especially with routes with a dynamic controller parameter. That's why controllers are kept in a separate plugin manager.

    Since the controller plugin manager is created from the "main" service manager, it also is initialized thanks to the ServiceLocatorAwareInterface.

    To make this more clear, I've added a graph of the relations (does not include the factory and don't take it as valid UML):

    Pseudo-UML

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 BP神经网络控制倒立摆
  • ¥20 要这个数学建模编程的代码 并且能完整允许出来结果 完整的过程和数据的结果
  • ¥15 html5+css和javascript有人可以帮吗?图片要怎么插入代码里面啊
  • ¥30 Unity接入微信SDK 无法开启摄像头
  • ¥20 有偿 写代码 要用特定的软件anaconda 里的jvpyter 用python3写
  • ¥20 cad图纸,chx-3六轴码垛机器人
  • ¥15 移动摄像头专网需要解vlan
  • ¥20 access多表提取相同字段数据并合并
  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角
  • ¥20 Java-Oj-桌布的计算