Symfony 4 setter 注入父 class

Symfony 4 setter injection in parent class

只是一个简短的问题。我正在构建一些 API。我正在考虑创建简单的父 class 来处理表单请求。

因此,例如,如果您想轻松处理表单请求,只需扩展此 class 即可访问请求对象、从该对象中提取的请求数据以及为您做一些事情的一堆方法盒子外面。到底是什么和为什么并不重要。

问题是:

  1. 我通过邮递员发送请求。
  2. 我尝试在 class 中使用扩展父 class 的请求对象,但我得到的不是请求,而是 null。

如何设置所有内容?:

现在在 Symfony 中每个控制器都默认注册为一个服务所以我重写这个定义是这样的:

#generic api form controller
    App\Controller\Api\ApiFormController:
      calls:
          - [setDependencies, ['@request_stack', '@App\Service\Serialization\Serializer']] 

如你所见,我正在使用 setter 注入。

我在另一个 class 中延伸到 class 以上。我们称它为 PostController。所以:

<?php

namespace App\Controller\Api;

use Symfony\Component\HttpFoundation\RequestStack;

class ApiFormController
{
    /**
     * @var Request
     */
    public $request;

    /**
     * @param RequestStack $requestStack    
     */
    public function setDependencies(
        RequestStack $requestStack       
    ) {
        $this->request = $requestStack;       
    }
}

现在是 PostController:

 public function get(int $post = null)
 {
   dump($this->request); exit;
 }

我期待获得这样的访问权限,我想我理解为什么我无法访问此对象。我正在寻找一些想法如何以最干净的方式实现这一目标。我期待的不是现成的答案,而是提示。

我在考虑使用事件在后台设置它? 我还认为这与我将控制器作为服务连接的方式有关。

我看到这里有几个问题。

  1. 如果你想以这种方式注入依赖,你应该将控制器定义为服务。您可以阅读更多 here

路由应该是这样的:

# config/routes.yaml
get_something:
    path:     /
    defaults: { _controller: App\Controller\Api\PostController:get }

此外,您应该将 PostController 定义为服务,而不是 ApiFormController。

  1. 您注入了 RequestStack,但属性的类型提示是 Request。

而不是:

$this->request = $requestStack;

您需要使用:

$this->request = $requestStack->getMasterRequest(); 

这一切的核心:Symfony 不会为子classes 选择服务定义。因此,如果您为 class 定义依赖项并在另一个 class 中扩展它,您也必须为第二个 class 定义依赖项。

最简单的方法是为此使用 parent 关键字,因此您的示例将按以下方式工作:

App\Controller\Api\ApiFormController:
  calls:
      - [setDependencies, ['@request_stack', '@App\Service\Serialization\Serializer']]

PostController:
  parent: App\Controller\Api\ApiFormController

如果你正在使用自动装配,你可以使用@required 让 Symfony 自动调用 setter。 https://symfony.com/doc/current/service_container/autowiring.html#autowiring-other-methods-e-g-setters

/**
 * @param RequestStack $requestStack
 * @required   
 */
public function setDependencies(
    RequestStack $requestStack       
) {
    $this->request = $requestStack;       
}

这应该可以解决问题。