Symfony Bundle服务构造方法数组参数配置异常排查
背景
我正在为多个Symfony项目开发一个Bundle,其中包含一个PropertyService,它的构造方法仅接收一个数组类型参数。使用该Bundle的开发者需要在config/properties.yaml文件中声明这个数组。我采用Symfony 6的AbstractBundle类来加载配置文件中的数组。
Bundle核心代码
class LongitudeOnePropertyBundle extends AbstractBundle { public function getPath(): string { return \dirname(__DIR__); } public function configure(DefinitionConfigurator $definition): void { $definition->rootNode() ->children() ->arrayNode('extendable_entities') ->defaultValue([]) ->scalarPrototype()->end() ->end() ->end() ->end(); } public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void { $loader = new PhpFileLoader($builder, new FileLocator(__DIR__ . '/Resources/config/')); $loader->load('services.php'); $container->services() ->get('longitude-one.property_bundle.property_service') ->arg(0, $config['extendable_entities']); } }
PropertyService代码
//src/Service.php namespace LongitudeOne\PropertyBundle\Service; class PropertyService { /** * @var string[] list of all extendable classes */ private array $classes; /** * @param string[] $classes list of all extendable classes */ public function __construct(array $classes) { die('constructor is called'); } }
Bundle内服务配置(services.php)
//src/Resources/config/services.php return static function (ContainerConfigurator $container) { $container->services() ->set('longitude-one.property_bundle.property_service', PropertyService::class) ->class(PropertyService::class) ->autoconfigure() ->autowire() ->public() ->arg(0, param('lopb.extendable_entities')); dump($container->services()->get(PropertyService::class)); };
错误信息
当测试应用的控制器通过依赖注入调用该服务时,抛出以下错误:
Cannot resolve argument $propertyService of "App\Controller\Admin\DashboardController::list()": Cannot autowire service "LongitudeOne\PropertyBundle\Service\PropertyService": argument "$classes" of method "__construct()" is type-hinted "array", you should configure its value explicitly.
已做的排查操作
- 将开发者配置的数组替换为空数组
[]; - 确认Bundle已正确声明;
- 检查
services.php文件(dump输出显示参数已设为空数组); - 将构造方法改为
setClasses方法并添加call调用,但方法未执行; - 通过
symfony console debug:container longitude-one检查服务; - 将服务设置为public。
服务调试信息
执行symfony console debug:container longitude-one得到如下输出:
/var/www # symfony console debug:container longitude-one Information for Service "longitude-one.property_bundle.property_service" ======================================================================== ---------------- ----------------------------------------------------- Option Value ---------------- ----------------------------------------------------- Service ID longitude-one.property_bundle.property_service Class LongitudeOne\\PropertyBundle\\Service\\PropertyService Tags - Public yes Synthetic no Lazy no Shared yes Abstract no Autowired yes Autoconfigured yes Usages none
问题分析与解决步骤
1. 移除未定义的参数引用
你在services.php中使用了param('lopb.extendable_entities'),但这个参数从未在Bundle配置中注册,容器无法解析它。直接替换为默认空数组:
// 修改services.php中的arg配置 ->arg(0, []);
2. 调整服务参数的修改方式
loadExtension中同时使用ContainerConfigurator和ContainerBuilder可能导致配置覆盖问题,直接操作ContainerBuilder修改服务定义更可靠:
// 修改loadExtension方法 public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void { $loader = new PhpFileLoader($builder, new FileLocator(__DIR__ . '/Resources/config/')); $loader->load('services.php'); // 直接操作ContainerBuilder中的服务定义 $builder->getDefinition('longitude-one.property_bundle.property_service') ->replaceArgument(0, $config['extendable_entities']); }
3. 关闭不必要的自动装配
因为PropertyService的构造参数是数组,自动装配无法自动解析,关闭autowire避免冲突:
// 修改services.php中的服务配置 $container->services() ->set('longitude-one.property_bundle.property_service', PropertyService::class) ->autoconfigure() ->public() ->arg(0, []);
4. 确保项目侧配置正确
使用Bundle的项目需要完成两步配置:
- 在
config/bundles.php中注册Bundle:return [ // ...其他Bundle LongitudeOne\PropertyBundle\LongitudeOnePropertyBundle::class => ['all' => true], ]; - 在
config/packages/目录下创建longitude_one_property.yaml(Symfony会自动识别Bundle配置前缀):longitude_one_property: extendable_entities: - App\Entity\YourEntity1 - App\Entity\YourEntity2
验证
修改完成后,执行以下命令确认服务参数已正确设置:
symfony console debug:container longitude-one.property_bundle.property_service --show-arguments
此时控制器依赖注入PropertyService即可正常工作。
内容的提问来源于stack exchange,提问作者Alexandre Tranchant

