Skip to content
Advertisement

Symfony6 changing the controller manually using the “kernel.controller” event. How to inject the service container?

The application that I am building is not going to work in a traditional way. All the routes ar going to be stored in the database. And based on the route provided I need to get the correct controller and action to be executed.

As I understand this can be achieved using the “kernel.controller” event listener: https://symfony.com/doc/current/reference/events.html#kernel-controller

I am trying to use the docs provided, but the example here does not exacly show how to set up a new callable controller to be passed. And I have a problem here, because I dont know how to inject the service container to my newly called controller.

At first the setup:

services.yaml

JavaScript

The listener:

RequestListener.php

JavaScript

So this is the most basic example. I get the route from the database, if it a “homepage” route, I create the new HomepageController and set the action. However I am missing the container interface that I dont know how to inject. I get this error:

Call to a member function has() on null

on line: vendorsymfonyframework-bundleControllerAbstractController.php:216

which is:

JavaScript

The controller is as basic as it gets:

HomepageController.php

JavaScript

So basically the container is not set. If I dump the $event->getController() I get this:

JavaScript

I need to set the container by doing $controller->setContainer(), but what do I pass?

Advertisement

Answer

Do not inject the container, controllers are services too and manually instanciating them is preventing you from using constructor dependency injection. Use a service locator which contains only the controllers:

Declared in config/services.yaml:

JavaScript

Then in the event listener, add the service locator argument and fetch the fully configured controllers from it:

JavaScript

If you dump any controller you will see that the container is set. Same will go for additionnal service that you autowire from the constructor.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement