Как определять контроллеры как сервисы

В Symfony контроллер не должен быть зарегистрирован как сервис. Но если вы используете конфигурацию services.yml по умолчанию, то ваши контроллеры уже зарегистрированы как сервисы. Это означает, что вы можете использовать внедрение зависимости, как любой другой обычный сервис.

Ссылание на ваш сервис из маршрутизатора

Регистрация вашего контроллера как сервиса - это отлично, но вы также должны убедиться, что ваш маршрутизатор корректно ссылается на сервис, чтобы Symfony знала, что его надо использовать.

Если id сервиса - полностью квалифицированное имя класса (FQCN) вашего контроллера, то вы закончили! Вы можете использовать обычный синтаксис AppBundle:Hello:index в вашем маршрутизаторе, и он будет находить ваш сервис.

НО, если ваш сервис имеет другой id, вы можете использовать специальный синтаксис SERVICEID:METHOD:

  • YAML
    1
    2
    3
    4
    # app/config/routing.yml
    hello:
        path:     /hello
        defaults: { _controller: app.hello_controller:indexAction }
    
  • Annotations
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    # src/AppBundle/Controller/HelloController.php
    // ...
    
    /**
     * @Route(service="app.hello_controller")
     */
    class HelloController
    {
        // ...
    }
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    <!-- app/config/routing.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
    // app/config/routing.php
    $collection->add('hello', new Route('/hello', array(
        '_controller' => 'app.hello_controller:indexAction',
    )));
    

Note

Вы не можете опустить часть имени метода Action при использовании нотации одного двоеточия.

Вызываемые контроллеры

Если ваш контроллер реализует метод __invoke(), популярный в шаблоне Действие-Домен-Ответ (ADR), вы можете простосослаться на id сервиса (AppBundle\Controller\HelloController или app.hello_controller, например).

Альтернативы базовых методов контроллера

При использовании контроллера, определённого как сервиса, вы всё ещё можете расширить любой из обычных базовых классов контроллера, и использовать их шорткаты. Но, вы не обязаны это делать! Вы можете выбрать не расширять ничего и использовать внедрение зависимоти, чтобы получить доступ к разным сервисам.

Базовый исходный код класса контроллера - это отличный способ увидеть, как можно добиться выполнения общих задач. Например, $this->render() обычно используется для отображения шаблона Twig и возвращения Ответа. Но, вы также можете сделать это напрямую:

В контроллере, определённом как сервис, вы можете вместо этого внедрить сервис templating и использовать его напрямую:

 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/AppBundle/Controller/HelloController.php
namespace AppBundle\Controller;

use Symfony\Component\HttpFoundation\Response;

class HelloController
{
    private $twig;

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

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

        return new Response($content);
    }
}

Вы также можете использовать специальное внедрение зависимости на основе действий, чтобы получаь сервисы в качестве аргументов ваших методов действий контроллера.

Базовые методы контроллера и их сервисные замены

Наилучший способ увидеть, как заменить базовые воспомогательные методы Controller - это посмотреть на ControllerTrait, содержащий его логику.

Если вы хотите узнать, какое типизирование использовать для каждого сервиса, смотрите метод getSubscribedServices() в AbstractController.

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.