I have created a custom Symfony 5.3
bundle to share code between different projects. In src/controller/SomeController.php
the bundle implements a controller class which extends from Symfony\Bundle\FrameworkBundle\Controller\AbstractController
.
When accessing this controller via a route in my Symfony project I get the following error:
"XY\CommensBundle\Controller\SomeController" has no container set, did you forget to define it as a service subscriber?
AbstractController
has a setContainer
method which is used to inject the service container. On controllers implemented directly in my Symfony project this method is called automatically by autowire / autoconfigure.
However, regarding to the Symfony docs autowire / autoconfigure should not be used for bundle services. Instead, all services should be defined explicitly. So I added this to the bundles services.yaml
:
# config/services.yaml
services:
xy_commons.controller.some_controller:
class: XY\CommensBundle\Controller\SomeController
public: false
calls:
- [ setContainer, [ '@service_container' ]]
After adding the bundle to my Symfony project using Composer the console shows, that the controller is correctly added as a service. Everything seems fine.
php bin/console debug:container 'xy_commons.controller.some_controller'
Information for Service "xy_commons.controller.some_controller"
=============================================================
---------------- -------------------------------------------------------
Option Value
---------------- -------------------------------------------------------
Service ID xy_commons.controller.some_controller
Class XY\CommensBundle\Controller\SomeController
Tags -
Calls setContainer
Public no
Synthetic no
Lazy no
Shared yes
Abstract no
Autowired no
Autoconfigured no
---------------- -------------------------------------------------------
However, the error is still the same. So how to configure controllers / services in Bundles correctly?
EDIT:
SomeController
is just a very basic subclass of AbstractController
:
class SomeController extends AbstractController {
public function some(): Response {
return new Response("<html><body>OK</body></html>");
}
}
Fully-qualified class name as Service ID
Usually I use FQCNs as Service ID. However, in this case I followed the advise from the Symfony docs (linked above) which explicitly say not to do so:
If the bundle defines services, they must be prefixed with the bundle alias instead of using fully qualified class names like you do in your project services. For example, AcmeBlogBundle services must be prefixed with acme_blog. The reason is that bundles shouldn’t rely on features such as service autowiring or autoconfiguration to not impose an overhead when compiling application services.
In addition, services not meant to be used by the application directly, should be defined as private.
This is way I used a snake name as ID and made the service private. The controller is not really used as service but only created automatically by Symfony when accessing / calling it via a route.