phpsymfonysymfony4

Overriding Controller in Symfony 4.4 (Decorates) - "You have requested a non-existent service"


I have a Bundle named Jason/JasonSticksBundle and inside this I have a controller named StickController.

I have a service defined within Jason/JasonSticksBundle/Resources/config/services.yaml

Jason\JasonSticksBundle\Controller\StickController:
        public: true
        arguments: []
        tags: ['controller.service_arguments']

My services.yaml is loaded via JasonSticksExtension->load(), and my bundle is registered in bundles.php.

The bundle works fine as-is.

BUT

For this particular project I want to override some methods within the StickController, so I am trying to "decorate" it.

At the bottom of my regular services.yaml therefore I have the following:

App\Controller\StickController:
    decorates: Jason\JasonSticksBundle\Controller\StickController

but I get this error

You have requested a non-existent service "Jason\JasonSticksBundle\Controller\StickController".

Finally, if I run

php bin/console debug:container

I can see my service

Jason\JasonSticksBundle\Controller\StickController                              Jason\JasonSticksBundle\Controller\StickController   

All I can imagine is that my services.yaml is being registered before my StickBundle is getting registered, thus it doesn't exist at the right time. But I don't know how to change the ordering of this, or if that would even be a viable option?

Any help appreciated.


Solution

  • I have found a workaround, though not solved. This definitely is not the way to do it - decorate exists for a reason, and I am unsure why I can't get that to work so any advice on that would still be appreciated.

    For my workaround:

    I removed my controller definitions from my Bundles services.yaml, and I edited my ConfigTreeBuilder of my bundles Configuration class to include a scalarNode field to allow a class name to be passed - this class name will be the controller to override the bundles.

    Then, to register the controller services without using services.yaml I modified my JasonStickExtension class, and after loading the services.yaml file (still needed for other services) I added the following:

    $stickControllerDefinition = $container->findDefinition('Jason\JasonSticksBundle\Controller\StickController');
    $stickControllerDefinition->addTag("controller.service_arguments");
    $stickDec = $config['stick_controller_class'];
      if($stickDec!=null) {
          $stickControllerDefinition->setClass($stickDec);
       }
    

    This is a way direct way of doing it, and as I say I really don't think it's the proper way.