9

我正在开发一个 ZF2 系统,它运行得很好,但是在我在其他计算机上克隆存储库后,出现了这个不推荐使用的错误:

您正在从类 Module\Controller\Controller 中检索服务定位器。请注意,ServiceLocatorAwareInterface 已弃用,将在 3.0 版中与 ServiceLocatorAwareInitializer 一起删除。您将需要更新您的类以在创建时接受所有依赖项,通过构造函数参数或设置器,并使用工厂执行注入。在 /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 核心中 Zend\Mvc\Controller\AbstractController 是这样的:

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

我已经尝试了一切,有人知道我该怎么做吗?

4

2 回答 2

10

你还不需要做任何事情。当您升级到 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')); 
} 

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

于 2016-03-17T13:26:08.897 回答
1

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

模块.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);
    }
}
于 2016-08-04T08:54:48.777 回答