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
相关产品推荐
相关产品推荐

