Symfony 4 was released on November 30th.
Update now to the best Symfony ever!

You are browsing the Symfony 4 documentation, which changes significantly from Symfony 3.x. If your app doesn't use Symfony 4 yet, browse the Symfony 3.4 documentation.

How to Define Controllers as Services

How to Define Controllers as Services

In Symfony, a controller does not need to be registered as a service. But if you're using the default services.yaml configuration, your controllers are already registered as services. This means you can use dependency injection like any other normal service.

Referencing your Service from Routing

Registering your controller as a service is great, but you also need to make sure that your routing references the service properly, so that Symfony knows to use it.

If the service id is the fully-qualified class name (FQCN) of your controller, you're done! You can use the normal App\Controller\HelloController::index syntax in your routing and it will find your service.

But, if your service has a different id, you can use a special service_id:method_name syntax:

  • Annotations
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    // src/Controller/HelloController.php
    
    // You need to use Sensio's annotation to specify a service id
    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
    // ...
    
    /**
     * @Route(service="app.hello_controller")
     */
    class HelloController
    {
        // ...
    }
    
  • YAML
    1
    2
    3
    4
    # config/routes.yaml
    hello:
        path:     /hello
        defaults: { _controller: app.hello_controller:indexAction }
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    <!-- config/routes.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing
            http://symfony.com/schema/routing/routing-1.0.xsd">
    
        <route id="hello" path="/hello">
            <default key="_controller">app.hello_controller:indexAction</default>
        </route>
    
    </routes>
    
  • PHP
    1
    2
    3
    4
    // config/routes.php
    $collection->add('hello', new Route('/hello', array(
        '_controller' => 'app.hello_controller:indexAction',
    )));
    

Note

When using the service_id:method_name syntax, the method name must end with the Action suffix.

Invokable Controllers

If your controller implements the __invoke() method - popular with the Action-Domain-Response (ADR) pattern, you can simply refer to the service id (App\Controller\HelloController or app.hello_controller for example).

Alternatives to base Controller Methods

When using a controller defined as a service, you can still extend any of the normal base controller classes and use their shortcuts. But, you don't need to! You can choose to extend nothing, and use dependency injection to access difference services.

The base Controller class source code is a great way to see how to accomplish common tasks. For example, $this->render() is usually used to render a Twig template and return a Response. But, you can also do this directly:

In a controller that's defined as a service, you can instead inject the templating service and use it directly:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// src/Controller/HelloController.php
namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;

class HelloController
{
    private $twig;

    public function __construct(\Twig_Environment $twig)
    {
        $this->twig = $twig;
    }

    public function index($name)
    {
        $content = $this->twig->render(
            'hello/index.html.twig',
            array('name' => $name)
        );

        return new Response($content);
    }
}

You can also use a special action-based dependency injection to receive services as arguments to your controller action methods.

Base Controller Methods and Their Service Replacements

The best way to see how to replace base Controller convenience methods is to look at the ControllerTrait that holds its logic.

If you want to know what type-hints to use for each service, see the getSubscribedServices() method in AbstractController.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.