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

Deprecated: Retrieve service locator in functional system - ZF2

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

You are retrieving the service locator from within the class Module\Controller\Controller. 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. in /home/path/project/vendor/zendframework/zend-mvc/src/Controller/AbstractController.php on line 258

composer.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 时,您将不得不更改 控制器 class 接收其依赖项的方式。

ZF2 支持两种依赖注入模式:通过服务定位器和通过构造函数。 ZF3 删除 "by service location" 并需要 "by constructor"。所有这一切实际上是改变了依赖关系的解决方式,将解决方案从 "just in time" 移动到 "at construction"。

您无法从任何地方获得服务,而是在施工获得服务。按照以下几行更新您的代码:

namespace Module\Controller;

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

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

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

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

Issue 5168, and this blog post 中讨论了更改,讨论了为什么使用服务定位器进行服务注入是一种反模式。

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

module.config.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;
    }
}

YourNamespace\Mvc\Controller\Plugin\Service.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);
    }
}