已弃用:检索功能系统 - ZF2 中的服务定位器


Deprecated: Retrieve service locator in functional system - ZF2

我正在开发一个 ZF2 系统,它运行良好,但是在我在其他计算机上克隆存储库后,出现了此已弃用的错误:

您正在从类模块''控制器''控制器中检索服务定位器。请注意,ServiceLocatorAwareInterface 已弃用,并将在 3.0 版中与 ServiceLocatorAwareInitializer 一起删除。您需要更新类以在创建时通过构造函数参数或 setter 接受所有依赖项,并使用工厂执行注入。在/home/path/project/vendor/zendframework/zend-mvc/src/Controller/AbstractController.php 第 258 行

作曲家.json:

"require": {
    "php": ">=5.5",
    "ext-curl": "*",
    "ext-json": "*",
    "ext-mbstring": "*",
    "zendframework/zendframework": "~2.5",
    "doctrine/doctrine-orm-module": "0.*",
    "hounddog/doctrine-data-fixture-module": "0.0.*",
    "imagine/Imagine": "~0.5.0"

当我在控制器中检索服务(扩展 Zend''Mvc''Controller''AbstractActionController)时出现错误:

$this->getServiceLocator()->get("Module'Service'Service");

在Zend''Mvc''Controller''AbstractController的Zend核心中是这样的:

public function getServiceLocator()
{
    trigger_error(sprintf(
        'You are retrieving the service locator from within the class %s. Please be aware that '
        . 'ServiceLocatorAwareInterface is deprecated and will be removed in version 3.0, along '
        . 'with the ServiceLocatorAwareInitializer. You will need to update your class to accept '
        . 'all dependencies at creation, either via constructor arguments or setters, and use '
        . 'a factory to perform the injections.',
        get_class($this)
    ), E_USER_DEPRECATED);
    return $this->serviceLocator;
}

以前只有这个:

public function getServiceLocator()
{
    return $this->serviceLocator;
}

什么都试过了,有人知道我该怎么做吗?

您还不需要执行任何操作。升级到 ZF3 时,必须更改控制器类接收其依赖项的方式。

ZF2 支持两种依赖注入模式:按服务定位器和按构造函数。ZF3 删除了"按服务位置"并要求"按构造函数"。所有这些实际上都改变了依赖关系的解析方式,将分辨率从"及时"转移到"施工时"。

您不是能够从任何地方获得服务,而是在施工时获得它们。按照以下行更新代码:

namespace Module'Controller;
class Controller {
    public function __construct('Module'Service'Service $service) {
        $this->service = $service;
    }
}

在类的方法中需要的地方使用$this->service

然后使用控制器工厂创建控制器,如下所示:

function ($controllers) { 
    $services = $controllers->getServiceLocator();
    return new 'Module'Controller'Controller($services->get('Module'Service'Service')); 
} 

问题 5168 中讨论了此更改,这篇博客文章讨论了为什么使用服务定位器进行服务注入是一种反模式。

你可以创建一个控制器插件 service()(但这是一个不好的做法,更喜欢 FactoryInterface)

模块配置.php

'controller_plugins' => [
    'factories' => [
        'service' => YourNamespace'Mvc'Controller'Plugin'Service'ServiceFactory::class,
    ],
],

YourNamespace''Mvc''Controller''Plugin''Service''ServiceFactory.php

<?php
namespace YourNamespace'Mvc'Controller'Plugin'Service;
use Interop'Container'ContainerInterface;
use YourNamespace'Mvc'Controller'Plugin'Service;
use Zend'ServiceManager'Factory'FactoryInterface;
class ServiceFactory implements FactoryInterface
{
    /**
     * @param  ContainerInterface $container
     * @param  string $requestedName
     * @param  array $options
     * @return Service
     */
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $plugin = new Service();
        $plugin->setServiceLocator($container);
        return $plugin;
    }
}

您的命名空间''MVC''控制器''插件''服务.php

<?php
namespace YourNamespace'Mvc'Controller'Plugin;
use Interop'Container'ContainerInterface;
use Zend'Mvc'Controller'Plugin'AbstractPlugin;
/**
 * Plugin: $this->service();
 */
class Service extends AbstractPlugin
{
    /**
     * @var ContainerInterface
     */
    protected $serviceLocator;
    /**
     * @return ContainerInterface
     */
    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }
    /**
     * @param  ContainerInterface $serviceLocator
     * @return Service
     */
    public function setServiceLocator(ContainerInterface $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
        return $this;
    }
    /**
     * @param  string $name
     * @return object|bool
     */
    public function __invoke($name = null)
    {
        $sl = $this->getServiceLocator();
        if (!$name) {
            return $sl;
        }
        if (!$sl->has($name)) {
            return false;
        }
        return $sl->get($name);
    }
}