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

自制框架中控制器构造函数无法注入依赖(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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 05:43:09