自制框架中控制器构造函数无法注入依赖(DI)问题排查
依赖注入LeapYear模型时触发ReflectionException错误
在跟随《Build your own framework》教程开发自制PHP框架时,尝试在控制器构造函数中通过依赖注入引入LeapYear模型,出现以下错误:
Fatal error: Uncaught ReflectionException: Class "" does not exist in C:\Users\.......\vendor\symfony\dependency-injection\ContainerBuilder.php:1131 Stack
尝试过移除services.yaml中的模型配置、手动注册服务,均无法解决问题,相关代码如下:
控制器代码
<?php namespace App\Controllers; use App\Models\LeapYear; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; class LeapYearController { private LeapYear $model; public function __construct(LeapYear $model) { $this->model = $model; } public function index(int $year): JsonResponse { if ($this->model->isLeapYear($year)) { return new JsonResponse('Yep, this is a leap year!'); } return new JsonResponse('Nope, this is not a leap year.'); } }
模型代码
<?php namespace App\Models; class LeapYear { public function isLeapYear(int $year = null): bool { if (null === $year) { $year = date('Y'); } return 0 === $year % 400 || (0 === $year % 4 && 0 !== $year % 100); } }
容器配置文件(container.php)
<?php use App\Controllers\LeapYearController; use App\Models\LeapYear; use GGPHP\Framework; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver; use Symfony\Component\HttpKernel\Controller\ControllerResolver; use Symfony\Component\HttpKernel\EventListener\ResponseListener; use Symfony\Component\HttpKernel\EventListener\RouterListener; use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\RequestContext; $container = new ContainerBuilder(); $loader = new YamlFileLoader($container, new FileLocator(__DIR__)); $loader->load('services.yml'); $container->register('context', RequestContext::class); $container->register('matcher', UrlMatcher::class) ->setArguments([$routes, new Reference('context')]); $container->register('request_stack', RequestStack::class); $container->register('controller_resolver', ContainerControllerResolver::class) ->setArguments([$container]); $container->register('argument_resolver', ArgumentResolver::class); $container->register('listener.router', RouterListener::class) ->setArguments([new Reference('matcher'), new Reference('request_stack')]); $container->register('listener.response', ResponseListener::class) ->setArguments(['UTF-8']); $container->register('dispatcher', EventDispatcher::class) ->addMethodCall('addSubscriber', [new Reference('listener.router')]) ->addMethodCall('addSubscriber', [new Reference('listener.response')]); $container->register('framework', Framework::class) ->setArguments([ new Reference('dispatcher'), new Reference('controller_resolver'), new Reference('request_stack'), new Reference('argument_resolver'), ]); return $container;
前端控制器(index.php)
<?php require_once dirname(__DIR__).'/vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; $request = Request::createFromGlobals(); $routes = include dirname(__DIR__).'/routes.php'; $container = include dirname(__DIR__).'/container.php'; $response = $container->get('framework')->handle($request); $response->send();
services.yaml配置
services: App\Models\LeapYear: arguments: App\Controllers\LeapYearController: arguments: $model: '@App\Models\LeapYear'
问题排查与解决方案
1. 修复services.yaml的无效配置
错误的核心原因是services.yaml中App\Models\LeapYear的arguments字段为空且格式错误,Symfony DI容器会尝试解析这个空配置,导致反射空类名的异常。
修改后的services.yaml(推荐方式,因LeapYear无构造参数):
services: App\Models\LeapYear: ~ App\Controllers\LeapYearController: arguments: $model: '@App\Models\LeapYear'
也可显式声明空参数数组:
services: App\Models\LeapYear: arguments: [] App\Controllers\LeapYearController: arguments: $model: '@App\Models\LeapYear'
2. 验证自动加载配置
确保composer.json中的PSR-4自动加载规则正确指向App命名空间:
{ "autoload": { "psr-4": { "App\\": "src/App/" } } }
执行composer dump-autoload刷新自动加载缓存,确保类能被正确加载。
3. 确认容器中$routes变量的有效性
检查routes.php返回的路由集合是否正确,确保index.php中$routes变量能被container.php正确继承使用,避免路由匹配器初始化失败。
内容的提问来源于stack exchange,提问作者whodis
相关产品推荐
相关产品推荐

