You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony6自定义服务获取失败,原Symfony4方法失效求助

Symfony6服务调用失败问题排查与解决

问题背景

从Symfony4升级到Symfony6后,原有的控制器中通过$this->container->get()调用自定义服务的方式失效,报错提示控制器内的容器是小型服务定位器,无法找到目标服务。

相关配置与代码

services.yaml配置

services:
  # default configuration for services in *this* file

  _defaults:
    autowire: true      # Automatically injects dependencies in your services.
    autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

  # makes classes in src/ available to be used as services
  # this creates a service per class whose id is the fully-qualified class name
  App\:
    resource: '../src/'
    exclude:
      - '../src/DependencyInjection/'
      - '../src/Entity/'
      - '../src/Kernel.php'
      - '../src/EventListener'
  app.our.useful.thing:
    class: App\OurUsefulThing
    public: true

自定义服务类 src/OurUsefulThing.php

<?php

namespace App;

class OurUsefulThing
{
    public function sayHello()
    {
        return "Hello Service";
    }
}

控制器调用代码

public function someActionName(Request $request) {
    $value = $this->container->get('app.our.useful.thing')->sayHello();
}

错误信息

未找到服务"app.our.useful.thing":尽管该服务存在于应用容器中,但"App\Controller\CategoriesController"内的容器是一个小型服务定位器,仅知晓"form.factory"、"http_kernel"、"parameter_bag"、"request_stack"、"router"、"security.authorization_checker"、"security.csrf.token_manager"、"security.token_storage"、"serializer"和"twig"服务。建议使用依赖注入替代。

原因与解决方案

Symfony从5.3版本开始,默认控制器采用服务定位器模式,控制器本身不再持有完整的服务容器引用,仅能访问预定义的核心服务,这是为了优化性能并遵循依赖注入的最佳实践。

有两种解决方式:

方式一:构造函数注入(推荐)

直接在控制器构造函数中注入OurUsefulThing服务,Symfony会通过Autowire自动完成依赖注入:

<?php

namespace App\Controller;

use App\OurUsefulThing;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class CategoriesController extends AbstractController
{
    private $usefulThing;

    public function __construct(OurUsefulThing $usefulThing)
    {
        $this->usefulThing = $usefulThing;
    }

    public function someActionName(Request $request)
    {
        $value = $this->usefulThing->sayHello();
        // 后续业务逻辑
    }
}

方式二:允许控制器使用完整服务容器(不推荐)

如果需要临时兼容旧代码,可在services.yaml中配置控制器使用完整容器:

App\Controller\CategoriesController:
    calls:
        - method: setContainer
          arguments: ['@service_container']

或者在Symfony 6.2+版本中,给控制器类添加注解:

use Symfony\Component\DependencyInjection\Attribute\AsController;

#[AsController(service: true)]
class CategoriesController extends AbstractController
{
    // 原有代码逻辑
}

这种方式违背依赖注入的设计原则,会降低代码的可测试性与清晰度,仅建议作为临时过渡方案使用。

内容的提问来源于stack exchange,提问作者craphunter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 22:40:24