我正在尝试遵循构建您自己的框架教程。当我想在控制器中使用 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 中删除了该模型。尝试通过注册手动加载它们,但没有任何效果,总是出现此错误。
基本问题是您尝试从配置文件加载服务,但仍然缺少某些内容。这有效:
$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)类来启动自身并执行各种面向容器的操作。这是使用扩展和不使用扩展来处理配置内容的地方。我手边没有简单的独立示例。