I am trying to follow the Build you own framework tutorial. I get stuck when I want to use DI inside my controller.
I have found this question (Controller (Service) not having dependencies injected on Symfony project) on stack overflow that got me as far as I am now but still cannot resolve the following issue:
This is my controller
<?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.');
}
}
This is my model:
<?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);
}
}
They are both in ./src/controllers and ./src/models
This is my 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;
And this is my front controller 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();
my services.yaml is:
services:
App\Models\LeapYear:
arguments:
App\Controllers\LeapYearController:
arguments:
$model: '@App\Models\LeapYear'
The error I get is:
Fatal error: Uncaught ReflectionException: Class "" does not exist in C:\Users\.......\vendor\symfony\dependency-injection\ContainerBuilder.php:1131 Stack
I am not sure what to do anymore. I have removed the model from the services.yaml. Tried to load them manually by registering, but nothing works, always get this error.
The rather obscure
Class "" does not exist
comes from the fact that you are not specifying the class parameter when defining your services. The Symfony framework has a bit of magic to overcome this but standalone means it is up to you.This was my original workaround which involves skipping the config file completely. You might still want to consider using it just to streamline your framework even further. No need for symfony/config or symfony/yaml with this approach.