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, and your controllers extend the AbstractController class, they are automatically registered as services. This means you can use dependency injection like any other normal service.

Symfony では、コントローラーをサービスとして登録する必要はありません。ただし、デフォルトの services.yaml 構成を使用していて、コントローラーが AbstractController クラスを拡張している場合、それらは自動的にサービスとして登録されます。これは、他の通常のサービスと同じように依存性注入を使用できることを意味します。

If your controllers don't extend the AbstractController class, you must explicitly mark your controller services as public. Alternatively, you can apply the controller.service_arguments tag to your controller services. This will make the tagged services public and will allow you to inject services in method parameters:

コントローラーが AbstractController クラスを拡張しない場合は、コントローラー サービスを明示的にパブリックとしてマークする必要があります。または、コントローラー サービスに controller.service_arguments タグを適用することもできます。これにより、タグ付けされたサービスが公開され、メソッド パラメータにサービスを挿入できるようになります。
  • YAML
    YAML
1
2
3
4
5
6
7
# config/services.yaml

# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
   resource: '../src/Controller/'
   tags: ['controller.service_arguments']

If you prefer, you can use the #[AsController] PHP attribute to automatically apply the controller.service_arguments tag to your controller services:

必要に応じて、#[AsController] PHP 属性を使用して、コントローラー サービスに controller.service_arguments タグを自動的に適用できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// src/Controller/HelloController.php
namespace App\Controller;

use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Annotation\Route;

#[AsController]
class HelloController
{
    #[Route('/hello', name: 'hello', methods: ['GET'])]
    public function index()
    {
        // ...
    }
}

Registering your controller as a service is the first step, but you also need to update your routing config to reference the service properly, so that Symfony knows to use it.

コントローラーをサービスとして登録することが最初のステップですが、Symfony がそれを使用することを認識できるように、ルーティング構成を更新してサービスを適切に参照する必要もあります。

Use the service_id::method_name syntax to refer to the controller method. If the service id is the fully-qualified class name (FQCN) of your controller, as Symfony recommends, then the syntax is the same as if the controller was not a service like: App\Controller\HelloController::index:

service_id::method_name 構文を使用して、コントローラー メソッドを参照します。Symfony が推奨するように、サービス ID がコントローラーの完全修飾クラス名 (FQCN) である場合、構文は、コントローラーが次のようなサービスではない場合と同じです。 : App\Controller\HelloController::index:
  • Attributes
    属性
  • YAML
    YAML
  • XML
    XML
  • PHP
    PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
// src/Controller/HelloController.php
namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;

class HelloController
{
    #[Route('/hello', name: 'hello', methods: ['GET'])]
    public function index()
    {
        // ...
    }
}

Invokable Controllers

Controllers can also define a single action using the __invoke() method, which is a common practice when following the ADR pattern (Action-Domain-Responder):

コントローラーは、__invoke() メソッドを使用して単一のアクションを定義することもできます。これは、ADR パターン (Action-Domain-Responder) に従う場合の一般的な方法です。
  • Attributes
    属性
  • YAML
    YAML
  • XML
    XML
  • PHP
    PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/Controller/Hello.php
namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

#[Route('/hello/{name}', name: 'hello')]
class Hello
{
    public function __invoke($name = 'World')
    {
        return new Response(sprintf('Hello %s!', $name));
    }
}

Alternatives to base Controller Methods

When using a controller defined as a service, you can still extend the AbstractController base controller and use its shortcuts. But, you don't need to! You can choose to extend nothing, and use dependency injection to access different services.

サービスとして定義されたコントローラを使用する場合でも、AbstractController ベース コントローラを拡張し、そのショートカットを使用できます。しかし、あなたはする必要はありません!何も拡張しないことを選択し、依存性注入を使用してさまざまなサービスにアクセスできます。

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:

基本コントローラー クラスのソース コードは、一般的なタスクを実行する方法を確認するのに最適な方法です。たとえば、$this->render() は通常、Twigtemplate をレンダリングして Response を返すために使用されます。ただし、これを直接行うこともできます。

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

サービスとして定義されたコントローラーでは、代わりに twigservice を注入して直接使用できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// src/Controller/HelloController.php
namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;
use Twig\Environment;

class HelloController
{
    private $twig;

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

    public function index($name)
    {
        $content = $this->twig->render(
            'hello/index.html.twig',
            ['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 AbstractController class that holds its logic.

基本コントローラーの便利なメソッドを置き換える方法を確認する最善の方法は、そのロジックを保持する AbstractController クラスを調べることです。

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

各サービスに使用する型ヒントを知りたい場合は、AbstractController の getSubscribeServices() メソッドを参照してください。