How do I accurately define a controller as a service using annotations?

This seems to be the fastest and easiest way to use the controller as a service, but I still skip the 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
}

      

Using:

// Test\TestBundle\Controller\UseController.php

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

      

When I do this, I get the error

You have requested a nonexistent 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?

+3


source to share


3 answers


From Controller as Service in SensioFrameworkExtraBundle :

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

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

      

The attribute service

in the annotation is only to tell Symfony to use the specified service instead of instantiating the controller using a statement new

. 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 register the controller as a service with 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 class Controller

.

See How to Define Controllers as Services and Controller as Service in SensioFrameworkExtraBundle .

+7


source


For future people, if you decide to use the controller as a service, you should be better off injecting your services into the controller through the constructor instead of getting them through the service locator. The former is considered an antipattern, while the latter allows easy unit testing and is simply more verbose.

So instead of:

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

      



You must:

private $yourService;

public function __construct(YourService $yourService)
{
    $this->yourService = $yourService;
}

public function useAction()
{
    $this->yourService->use(...);
}

      

Don't create shortcuts, write solid, maintainable code.

+3


source


For Symfony 3.4, we don't need to register controllers as services since they are already registered as services with standard configuration services.yml

.

You just need to write this:

// current controller

public function myAction() {
  $test = $this->get(SomeController::class)->someAction($param);
}

      

0


source







All Articles