无法在控制器构造函数中加载 DI

问题描述 投票:0回答:1

我正在尝试遵循构建您自己的框架教程。当我想在控制器中使用 DI 时,我遇到了困难。

我在堆栈溢出上发现了这个问题(控制器(服务)没有在 Symfony 项目上注入依赖项),这让我到目前为止,但仍然无法解决以下问题:

这是我的控制器

<?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);
    }
}

它们都在 ./src/controllers 和 ./src/models 中

这是我的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'

我得到的错误是:

Fatal error: Uncaught ReflectionException: Class "" does not exist in C:\Users\.......\vendor\symfony\dependency-injection\ContainerBuilder.php:1131 Stack

我不知道该怎么办了。我已从 services.yaml 中删除了该模型。尝试通过注册手动加载它们,但没有任何效果,总是出现此错误。

php symfony dependency-injection frameworks symfony-dependency-injection
1个回答
0
投票

基本问题是您尝试从配置文件加载服务,但仍然缺少某些内容。这有效:

$container = new ContainerBuilder();
//$loader = new YamlFileLoader($container, new FileLocator(__DIR__));
//$loader->load('services.yml');

$container->register(LeapYear::class,LeapYear::class);

$container->register(LeapYearController::class, LeapYearController::class)
    ->setArguments([
        new Reference(LeapYear::class)
    ]);

我知道您最终可能会想要使用服务配置文件,但也许不会。您的目标似乎是一个最小的框架,因此也许您想避免额外的配置。

Symfony 框架本身使用 Kernel(不是 HttpKernel)类来启动自身并执行各种面向容器的操作。这是使用扩展和不使用扩展来处理配置内容的地方。我手边没有简单的独立示例。

© www.soinside.com 2019 - 2024. All rights reserved.