
Сервисы в Symfony: коротко, просто и понятно
03.05.2019 19:50 | Symfony
Довольно просто и доступно о том, что из себя представляют сервисы и как они работают в Symfony 4 (по материалам symfonycasts).
OS: Ubuntu 18.04, Framework: Symfony 4.2.5
Итак, что такое сервис? На самом деле, за этим термином стоит довольно простая идея: сервис - это любой объект, который выполняет какую-то работу. Например, отправляет сообщения, сохраняет данные в базу, парсит RSS и т.д.
Как использовать сервисы? Просто внутри контроллера добавьте в метод дополнительный аргумент и дайте ему подсказку типа, например, LoggerInterface
и назовите его как хотите, например $logger
:
public function index(LoggerInterface $logger)
{
// do something
$logger->info('Some message');
}
Как это работает? Перед тем, как запустить контроллер, Symfony проверяет каждый аргумент, смотрит на подсказку типа и понимает, что нам нужен тот или иной объект. И, кстати, порядок аргументов вовсе не важен.
Symfony поставляется с огромным количеством сервисов. Как узнать, какие сервисы доступны? Войдите в корневую директорию проекта и выполните команду:
bin/console debug:autowiring
Можно также выполнить поиск по ключевому слову:
bin/console debug:autowiring [<keyword>]
Ок, а что такое autowiring
? Это автоматическое подключение, которое позволяет управлять сервисами с минимумом конфигурации. Речь об этом уже была выше - Symfony читает подсказку типа и передаёт нужный объект. Как насчёт пользовательского кода? Откройте файл config/services.yaml
и обратите внимание на следующие строки:
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
Это означает, что любой класс (подробнее ниже) автоматически зарегистрирован как сервис и автоматически подключен. Другими словами, созданные классы можно сразу же использовать как сервисы, вообще не задумываясь о конфигурации.
Стоп! Неужели вообще любой класс зарегистрирован как сервис? Вообще-то нет. Опять обратимся к файлу config/services.yaml
:
services:
...
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
Т.е. все классы в директории src
, кроме тех, которые находятся в поддиректориях перечисленных в exclude
, будут доступны как сервисы.
Откуда берутся объекты сервисов? Каждый сервис, хранится внутри другого объекта, который называется контейнером (также называемый сервис-контейнером или контейнером инъекции зависимостей). Важный момент: объект сервиса создаётся только тогда, когда Вы его запрашиваете. Если этого не происходит то и сервис не будет создан, что способствует экономии памяти и скорости. Кроме того сервис создаётся только один раз, т.е. каждый раз Symfony будет возвращать один и тот же экземпляр сервиса.
Но как сервисы попадают в контейнер, кто их туда кладёт? Ответ: бандлы. Бандлы подобны плагинам в других программном обеспечении. Ключевое отлие в том, что в Symfony всё является бандлами, включая как ядро фреймворка, так и код написанный для Вашего приложения.
И напоследок: Symfony - это не что иное, как набор сервисов. А бандлы - это то, что фактически готовит сервисы и помещает их в контейнер.
Надеюсь, после этой статьи картина стала понятнее. При этом как обычно, рекомендую тщательно изучить официальную документацию, поскольку некоторые важные моменты не были затронуты в данной статье (явная конфигурация сервисов и параметров, привязка аргументов по имени или типу, публичные и приватные сервисы и т.д.)
Успехов!