【问题标题】:Symfony 4.2 - Services/Autowiring - Method call based on controller valueSymfony 4.2 - 服务/自动装配 - 基于控制器值的方法调用
【发布时间】:2019-01-11 21:10:06
【问题描述】:

在 Symfony 4.2 中,Controller 类已被弃用,您应该切换到 AbstractController,因此除了他们为您定义的一些服务外,您无法再访问 $this->get('service.name') 功能。

我的基本控制器扩展了 Symfony 的控制器并具有利用 $this->get 功能的功能:

public function getRepository($repository){
    $repo = $this->get($repository);
    if($this->authRepository !== null) {
        $repo->setPrefix($this->authRepository);
    }
    return $repo;
}

所以在我的控制器中,我可以说类似$this->getRepository('api.service'); 的内容,然后它会加载我的服务,根据请求设置前缀,然后返回配置的 api.service。

使用新的 AbstractController 和服务的自动装配/自动注入,我如何告诉我的服务不仅调用 setPrefix 方法(我知道我可以这样做),而且告诉它在我的控制器中使用参数?

到目前为止的配置:

api.service:
    class: App\ApiService
    calls:
        - method: setPrefix
          arguments:
              - '??????'

【问题讨论】:

  • 哪个参数?如果您的意思是参数数组的第一个参数,它将是一个类变量,因此您可以使用$this->... 调用它。如果它是一项服务,您可以向setPrefix(Here.. $something) 输入提示,看看是否有效? symfony.com/doc/current/service_container/calls.html
  • 为什么不通过构造函数将authRepository 自动连接到您的存储库?
  • 您可以通过可以访问请求的工厂来执行此操作。
  • 我能够通过设置事件监听器然后使用前缀类的静态变量来实现这一点。不理想,但该值会在每次调用时设置一次,并且每个服务都可以从那时起访问数据。

标签: symfony


【解决方案1】:

所以你上面发布的这个方法:

public function getRepository($repository){
    $repo = $this->get($repository);
    if($this->authRepository !== null) {
        $repo->setPrefix($this->authRepository);
    }
    return $repo;
}

可以使用新的 DependecyInjection 像这样实现:

class TestController extends AbstractController
{
    /**
     * @Route("/test", name="test")
     */
    public function test(App\ApiService $service)
    {
        $service->maybeSetPrefix($service);
        $service->call(...
    }

    // this can go into your own BaseController
    public function maybeSetPrefix($service)
    {
        if ($this->authRepository !== null) {
            $service->setPrefix($this->authRepository);
        }
    }
}

您将不需要需要服务定义,因为 Symfony DependencyInjection 应该已经自动装配它,但手动它看起来像这样:

App\ApiService:
    autowire: true
    autoconfigure: true
    public: false

所以现在我们不再使用像 api.service 这样的服务 ID,而是使用完整的类名 App\ApiService

如果您仍想通过api.service 使服务可引用,您可以另外添加别名服务定义:

api.service:
    alias: App\ApiService
    public: true

但也许在您的情况下,您可以让您的App\ApiService 决定如何根据请求而不是控制器来初始化自身,如下所示:

class ApiService
{
    public function __construct(RequestStack $requestStack, AuthRepository $authRepository)
    {
        $request = $requestStack->getCurrentRequest();

        if ($request->get('option') === 'test') {
            $this->setPrefix($authRepository);
        }
    }

如果这没有帮助,可能会发布更多详细信息或当前控制器逻辑的示例代码。

【讨论】:

  • 我喜欢这个,这可能是我需要做的......但实际上每个函数调用都会调用设置前缀,这就是我试图避免的。跨度>
  • 听起来你真的很想让ApiService 像我上一个例子一样初始化自己,甚至创建一个工厂来创建你的服务。
猜你喜欢
  • 1970-01-01
  • 2018-08-05
  • 2018-11-02
  • 2023-03-27
  • 2019-07-15
  • 1970-01-01
  • 2017-08-09
  • 2019-01-21
  • 1970-01-01
相关资源
最近更新 更多