
Сервіси в 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 - це не що інше, як набір сервісів. А бандли - це те, що фактично готує сервіси і додає їх в контейнер.
Сподіваюся, після цієї статті картина стала більш зрозумілою. При цьому як зазвичай, рекомендую ретельно вивчити офіційну документацію, оскільки деякі важливі теми не були розглянуті в даній статті (явна конфігурація сервісів і параметрів, прив'язка аргументів за ім'ям або типом, публічні і приватні сервіси і т.д.)
Успіхів!