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