-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
-
https://symfony.com/doc/current/index.html
The documentation is all based on using the framework and I have very limited access to help.
Now I need a little help.
I've followed "Create your own PHP Framework" and implemented the basic web framework, but when I try to get a logger service from the controller, it always throws a runtime exception:
Fatal error: Uncaught RuntimeException: Controller "App\Controller\LuckyController::number()" requires that you provide a value for the "$logger" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.
Controller part of the code:
class LuckyController
{
#[Route('/lucky')]
public function number(Request $request, Logger $logger): Response
{
$logger->critical('Test logger');
return new Response($request->headers->get('user_agent'));
}
}
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 1 comment 2 replies
-
So now you start to get into the fun stuff. Take a step back and ask yourself how the arguments actually get injected into the number action method. It's not normal dependency injection. $request for example is not even a service and of course a controller can have multiple actions each taking a different set of arguments. The answer is that Symfony has an ArgumentResolver class which takes care of figuring out what to inject where. If you take a look at where you configured your framework class you will see that you actually injected an argument_resolver service using the Symfony\Component\HttpKernel\Controller\ArgumentResolver
class.
There are actually multiple resolvers for different types of arguments. By default the ArgumentResolver class uses:
public static function getDefaultArgumentValueResolvers(): iterable
{
return [
new RequestAttributeValueResolver(),
new RequestValueResolver(),
new SessionValueResolver(),
new DefaultValueResolver(),
new VariadicValueResolver(),
];
}
So, for example, the RequestValueResolver checks for any controller action arguments of type Request and, if it finds one, injects $request.
What you need to do is to add the ServiceValueResolver
to the list of resolvers. The ArgumentResolver class is final so you can't just extend it but fortunately you inject an array of resolvers as the second constructor argument instead of using the default list. Which means you have to define services for each of the default resolvers and then define a service for the ServiceValueResolver. Gather them all up in an array and inject them.
At which point, assuming you have also defined a Logger service, your logger should be injected.
Have fun
Beta Was this translation helpful? Give feedback.
All reactions
-
First of all, thank you for your reply, I did the following.
$containerBuilder->register('logger', Logger::class);
$containerBuilder->register('service_value_resolver', ServiceValueResolver::class);
$containerBuilder->register('argument_resolver', ArgumentResolver::class)
->setArguments([null, [new Reference('service_value_resolver')]]);
There is a constructor in ServiceValueResolver::class where he asks to pass in a Container, I didn't know how to get the Container instead, so I didn't pass in the Container via setArguments.
The result is also the same as I expected, he does not work properly.
Too few arguments to function Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver::__construct(), 0 passed and exactly 1 expected in vendor\symfony\http-kernel\Controller\ArgumentResolver\ServiceValueResolver.php:30
Beta Was this translation helpful? Give feedback.
All reactions
-
The container itself is a service with an id of service_container
. The container actually creates this service automatically. Not sure where it is documented except maybe in the code.
Looks like you are making progress. Don't forget to inject the rest of the resolvers as well otherwise your existing code won't work. Especially the request resolver. And I'm pretty sure your logger service is going to need a bit more work as well but one step at a time.
Beta Was this translation helpful? Give feedback.