Search code examples
symfonyserviceannotations

How exactly can I define a controller as service using annotations?


This seems to be the fastest and simpliest way to use a controller as service, but I am still missing a step because it doesn't work.

Here is my code:

Controller/service:

// Test\TestBundle\Controller\TestController.php

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

/**
 * @Route(service="test_service")
 */
class TestController extends Controller {
  // My actions
}

Use :

// Test\TestBundle\Controller\UseController.php

// ...
public function useAction() {
  $testService = $this->get('test_service');
}

When I do that, I get the error

You have requested a non-existent service "test_service".

When I check the list of services with app/console container:debug, I don't see my newly created service.

What am I missing?


Solution

  • From Controller as Service in SensioFrameworkExtraBundle:

    The @Route annotation on a controller class can also be used to assign the controller class to a service so that the controller resolver will instantiate the controller by fetching it from the DI container instead of calling new PostController() itself:

    /**
     * @Route(service="my_post_controller_service")
     */
    class PostController
    {
        // ...
    }
    

    The service attribute in the annotation is just to tell Symfony it should use the specified service, instead of instantiating the controller with the new statement. It does not register the service on its own.

    Given your controller:

    use Symfony\Bundle\FrameworkBundle\Controller\Controller;
    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
    
    /**
     * @Route(service="test_service")
     */
    class TestController
    {
        public function myAction()
        {
        }
    }
    

    You need to actually register the controller as a service with the test_service id:

    services:
        test_service:
            class: Test\TestBundle\Controller\TestController
    

    The advantage of this approach is that you can inject your dependencies into the constructor by specifying them in the service definition, and you don't need to extend the base Controller class.

    See How to define controllers as services and Controller as Service in SensioFrameworkExtraBundle.