Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 不推荐:在功能系统-ZF2中检索服务定位器_Php_Zend Framework_Zend Framework2_Deprecated_Zend Framework3 - Fatal编程技术网

Php 不推荐:在功能系统-ZF2中检索服务定位器

Php 不推荐:在功能系统-ZF2中检索服务定位器,php,zend-framework,zend-framework2,deprecated,zend-framework3,Php,Zend Framework,Zend Framework2,Deprecated,Zend Framework3,我正在开发一个ZF2系统,它工作得很好,但在我在其他计算机中克隆存储库后,出现了此不推荐的错误: 您正在从类Module\Controller\Controller中检索服务定位器。请注意,ServiceLocatorAwareInterface已弃用,将在版本3.0中与ServiceLocatorAwareInitializer一起删除。您需要通过构造函数参数或setter更新类以在创建时接受所有依赖项,并使用工厂执行注入。在第258行的/home/path/project/vendor/ze

我正在开发一个ZF2系统,它工作得很好,但在我在其他计算机中克隆存储库后,出现了此不推荐的错误:

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

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):

Zend core中的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;
}

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

你现在什么都不用做。升级到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')); 
} 

中讨论了此更改,并讨论了为什么使用服务定位器的服务注入是一种反模式。

您可以创建控制器插件服务()(但这是一种不好的做法,首选FactoryInterface)

module.config.php

'controller_plugins' => [
    'factories' => [
        'service' => YourNamespace\Mvc\Controller\Plugin\Service\ServiceFactory::class,
    ],
],
<?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;
    }
}
<?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);
    }
}
YourNamespace\Mvc\Controller\Plugin\Service\ServiceFactory.php

'controller_plugins' => [
    'factories' => [
        'service' => YourNamespace\Mvc\Controller\Plugin\Service\ServiceFactory::class,
    ],
],
<?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;
    }
}
<?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);
    }
}

它就在消息中:
您需要更新您的类,以便在创建时通过构造函数参数或setter接受所有依赖项,并使用工厂执行注入。
我不太理解这条消息,“需要更新您的类”但是什么类别?可能重复的?您能为不同操作需要不同服务的控制器推荐一种解决方案吗?例如,my indexAction需要用户服务,viewAction需要用户服务和产品服务,my AboutAction可能根本不需要服务。我的观点是,对于这样一个控制器,为每个请求实例化并传递构造函数中的所有服务是没有意义的。@helloworld你是对的,注入所有这些服务是没有意义的,我认为这正是这一变化的重点:迫使开发人员考虑适用于控制器的单一责任原则。对我来说,听起来你有一个“胖”控制器,解决方案是为这些动作创建单独的控制器。如果您在[codereview SE](codereview.stackexchange.com)上发布了一个具体的示例,您可以获得更具体的反馈。感谢您的反馈。我将致力于使控制器遵守SRP。与FactoryInterface的关系如何?如
ServiceFactory
,但与
$controller=new YourController()$控制器->设置服务($container)