Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/282.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 通过“向控制器添加服务”;容器。服务“用户”;没有按预期工作_Php_Symfony_Fosrestbundle - Fatal编程技术网

Php 通过“向控制器添加服务”;容器。服务“用户”;没有按预期工作

Php 通过“向控制器添加服务”;容器。服务“用户”;没有按预期工作,php,symfony,fosrestbundle,Php,Symfony,Fosrestbundle,我正在尝试使用控制器上的container.service\u subscriber标记使某些服务可用,而无需通过构造函数注入它们。在我们的项目中,我们不想使用自动布线,也不能使用自动配置选项 控制器的结构如下: 我有一个baseBaseController,它从FOSRestBundle的AbstractFOSRestController扩展而来,FOSRestBundle对我的所有控制器都有一些常用的方法。该服务将用作我的其他控制器的父控制器 服务定义如下所示: WM\ApiBundle\C

我正在尝试使用控制器上的
container.service\u subscriber
标记使某些服务可用,而无需通过构造函数注入它们。在我们的项目中,我们不想使用
自动布线
,也不能使用自动配置选项

控制器的结构如下:

我有一个base
BaseController
,它从FOSRestBundle的
AbstractFOSRestController
扩展而来,FOSRestBundle对我的所有控制器都有一些常用的方法。该服务将用作我的其他控制器的父控制器

服务定义如下所示:

WM\ApiBundle\Controller\BaseController:
    class: WM\ApiBundle\Controller\BaseController
    abstract: true
    arguments:
        - "@service1"
        - "@service2"
        - ...

WM\ApiBundle\Controller\UserController:
    parent: WM\ApiBundle\Controller\BaseController
    public: true
    #autowire: true
    class: WM\ApiBundle\Controller\UserController
    tags:
        - { name: 'container.service_subscriber'}
        - { name: 'container.service_subscriber', key: 'servicexyz', id: 'servicexyz' }
/**
 * User controller.
 */
class UserController extends AbstractCRUDController implements ClassResourceInterface
{

    public static function getSubscribedServices()
    {
        return array_merge(parent::getSubscribedServices(), [
        'servicexyz' => ServiceXYZ::class,
        ]);
    }
   .......
}
该类如下所示:

WM\ApiBundle\Controller\BaseController:
    class: WM\ApiBundle\Controller\BaseController
    abstract: true
    arguments:
        - "@service1"
        - "@service2"
        - ...

WM\ApiBundle\Controller\UserController:
    parent: WM\ApiBundle\Controller\BaseController
    public: true
    #autowire: true
    class: WM\ApiBundle\Controller\UserController
    tags:
        - { name: 'container.service_subscriber'}
        - { name: 'container.service_subscriber', key: 'servicexyz', id: 'servicexyz' }
/**
 * User controller.
 */
class UserController extends AbstractCRUDController implements ClassResourceInterface
{

    public static function getSubscribedServices()
    {
        return array_merge(parent::getSubscribedServices(), [
        'servicexyz' => ServiceXYZ::class,
        ]);
    }
   .......
}
我遇到的问题是,如果我设置了
autowire:false
,它总是自动设置完整的容器,并带有相应的弃用消息(因为我不是自己设置的):

不推荐用户:自Symfony 4.2以来,不推荐自动注入“WM\APIBULND\Controller\UserController”的容器。将其配置为服务

设置
autowire:true
Symfony确实尊重
container.service\u订户
标记,并且只设置部分容器(ServiceLocator),这也将解决弃用消息。在这种情况下,我希望自动布线不会有任何区别,因为我明确地告诉服务应该有哪些其他服务。

我是否使用了错误的标记,或者在理解如何向控制器订阅服务时遇到了一般性问题?

基本问题是内置服务订户功能只会将服务定位器注入构造函数。扩展AbstractController的传统控制器使用autoconfigure基本上覆盖了这一点,并使用setContainer代替构造函数

# ApiBundle/Resources/config/services.yaml
services:
  _defaults:
    autowire: false
    autoconfigure: false

  Api\Controller\UserController:
    public: true
    tags: ['container.service_subscriber']
结果:

    API Index Controller Symfony\Component\DependencyInjection\Argument\ServiceLocator
指示服务定位器(与正在注入的全局容器相反)

您还可以将服务配置为使用setContainer方法,并消除对构造函数的需要。任何一种方法都会奏效

  Api\Controller\UserController:
    public: true
    tags: ['container.service_subscriber']
    calls: [['setContainer', ['@Psr\Container\ContainerInterface']]]


问题的解决方案是通过调用
setContainer
来扩展控制器的服务定义,以注入
'@Psr\Container\ContainerInterface'
服务:

WM\ApiBundle\Controller\BaseController:
    class: WM\ApiBundle\Controller\BaseController
    abstract: true
    arguments:
        - "@service1"
        - "@service2"
        - ...
    calls: 
        - ['setContainer', ['@Psr\Container\ContainerInterface']]

WM\ApiBundle\Controller\UserController:
    parent: WM\ApiBundle\Controller\BaseController
    public: true
    class: WM\ApiBundle\Controller\UserController
    tags:
        - { name: 'container.service_subscriber'}
        - { name: 'container.service_subscriber', key: 'servicexyz', id: 'servicexyz' }
这将为我提供一个
ServiceLocator
容器,它只包含已注册的服务,而不包含完整的容器,而不使用
autowire
选项。
旁注:设置
@service\u容器将注入完整的容器


为了完整起见,symfony项目中已经有一个讨论过这一点的项目。

感谢您的时间和回复。但这不正是与事实相反吗?它甚至说如果我不想使用自动配置,我应该使用标签。还测试了仅启用了autoconfigure而不会改变行为的情况,使其达到预期效果(或至少据我所知)的唯一方法是启用autowire。找到了问题的解决方案。实际上,symfony项目中已经有了。我缺少的是对
['setContainer',['@Psr\Container\ContainerInterface']]
的调用,这将为我提供
服务定位器。我曾经用
服务容器
试过一次,但它总是包含完整的容器,所以这可能会让我感到困惑。酷。我试图找出如何使用呼叫,但从未尝试使用Psr ContainerInterface。我把它作为答案的一个选项。