Найти в Дзене
Topsite Web

Мастерство Dependency Injection (DI) в Drupal: Практическое руководство

Внедрение зависимостей (Dependency Injection, DI) — это шаблон проектирования, при котором объект получает свои зависимости из внешних источников, а не создаёт их самостоятельно. Основная идея заключается в том, чтобы отделить создание зависимостей объекта от его основной функциональности. Это способствует модульности, гибкости, тестируемости и слабой связанности различных частей программы.

Ключевые концепции внедрения зависимостей:

1. Зависимости: Объекты или сервисы, от которых зависит другой объект для выполнения своей функции. Например, класс может зависеть от подключения к базе данных или от сервиса логирования.

2. Внедрение: Вместо того чтобы создавать зависимости внутри класса, они передаются (внедряются) извне, как правило, через:

Конструктор: Зависимости передаются через конструктор класса.

Сеттеры: Зависимости передаются через методы-сеттеры.

Интерфейсы: Зависимости передаются путём реализации интерфейса, который требует внедрения.

3. Инверсия управления (IoC): Внедрение зависимостей — это форма инверсии управления, при которой управление созданием объектов передаётся из класса во внешний источник, обычно в контейнер внедрения зависимостей (DI-контейнер) или контейнер сервисов. Этот контейнер разрешает и внедряет зависимости.

Пример внедрения зависимостей:

Ниже приведён пример, показывающий, как работает внедрение зависимостей в PHP с использованием внедрения через конструктор.

Без внедрения зависимостей:

-2

В этом примере класс UserService создаёт экземпляр Database самостоятельно, что делает его жёстко связанным с этим классом. Если вы захотите использовать другой класс для работы с базой данных, вам придётся изменять класс UserService.

С внедрением зависимостей:

-3

Теперь класс UserService не создаёт собственный экземпляр Database, а получает его извне. Это делает класс более гибким, так как вы можете внедрить разные типы объектов Database по мере необходимости.

Преимущества внедрения зависимостей:

1. Слабая связанность: Зависимый класс не нуждается в знании о том, как создаются его зависимости. Это приводит к более гибкому и поддерживаемому коду.

2. Тестируемость: Внедрение зависимостей позволяет легко заменять реальные зависимости на тестовые заглушки или мок-объекты во время тестирования, что упрощает написание юнит-тестов.

3. Принцип единственной ответственности (SRP): Классы не отвечают за создание и управление своими зависимостями, что соответствует принципу SRP. Они сосредотачиваются на своей основной функциональности.

4. Гибкость: Внедрение зависимостей позволяет изменять или заменять зависимости без изменения зависимого класса, что способствует повторному использованию и гибкости кода.

Контейнер внедрения зависимостей (DI-контейнер):

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

Пример с DI-контейнером (на основе контейнера сервисов Symfony):

-4

Контейнер автоматически создаёт экземпляр Database и внедряет его в класс UserService.

Типы внедрения зависимостей:

1. Внедрение через конструктор: Зависимости передаются через конструктор класса. Это наиболее распространённый тип, так как он гарантирует наличие зависимостей при создании объекта.

2. Внедрение через сеттеры: Зависимости передаются через методы-сеттеры. Это позволяет использовать необязательные зависимости, но может привести к тому, что объект будет создан без всех необходимых зависимостей, что потенциально может вызвать проблемы.

3. Внедрение через интерфейс: Класс реализует интерфейс, который требует метода для внедрения зависимостей. Это менее распространённый подход, так как он считается более сложным.

Использование DI в реальном мире:

• Фреймворки, такие как Symfony, Laravel и Zend, активно используют DI для управления сервисами и компонентами.

Тестирование и мокирование: DI облегчает замену реальных сервисов на тестовые во время тестирования.

Внедрение зависимостей в Drupal:

В Drupal внедрение зависимостей (DI) стало ключевой концепцией, начиная с версии 8, так как Drupal построен на основе фреймворка Symfony. Drupal использует контейнер сервисов для управления зависимостями и их автоматического внедрения в различные классы и сервисы, что повышает гибкость, тестируемость и поддерживаемость вашего кода.

Основные концепции внедрения зависимостей в Drupal:

1. Контейнер сервисов: Централизованный контейнер, в котором хранятся доступные сервисы (объекты, выполняющие определённые задачи). Контейнер автоматически разрешает и внедряет зависимости по мере необходимости.

2. Сервисы: Повторно используемые объекты, выполняющие конкретные задачи (например, логирование, подключение к базе данных или рендеринг). Эти сервисы определяются в контейнере и внедряются по мере необходимости.

3. Внедрение через конструктор: В Drupal наиболее распространённый способ внедрения зависимостей — через конструктор. Зависимости передаются в класс через его конструктор.

Пример внедрения зависимостей в Drupal:

Предположим, что вам нужно внедрить сервис в собственный блок или контроллер.

Шаг 1: Создание сервиса:

Сначала определите сервис, который вы хотите внедрить.

my_module.services.yml:

-5

Сервис my_module.custom_service определяется в файле services.yml. Он ссылается на класс CustomService, а его зависимость (сервис логирования) передаётся как аргумент (@logger.channel.default).

Шаг 2: Создание класса сервиса:

src/Service/CustomService.php:

-6

Этот класс сервиса зависит от сервиса логирования, который внедряется через конструктор.

Шаг 3: Внедрение сервиса в блок:

Теперь создадим блок, который использует этот сервис.

src/Plugin/Block/MyCustomBlock.php:

-7

Основные моменты:

• create(ContainerInterface $container): Этот статический метод использует контейнер сервисов для получения зависимостей. В данном случае он получает my_module.custom_service.

Внедрение через конструктор: Объект CustomService передаётся через конструктор класса блока, что позволяет его использовать в методе build().

Как работает внедрение зависимостей в Drupal:

Контейнер сервисов: Drupal использует контейнер сервисов Symfony. Сервисы определяются в файлах *.services.yml и автоматически внедряются туда, где они нужны.

ContainerFactoryPluginInterface: При создании блоков, форм, контроллеров или других типов плагинов в Drupal вы можете реализовать этот интерфейс для использования внедрения зависимостей.

Дополнительные примеры внедрения зависимостей в Drupal:

1. Внедрение сервисов в контроллер:

-8

2. Внедрение сервисов в формы:

Вы также можете внедрять сервисы в формы, реализуя интерфейс FormInterface и используя ContainerFactoryPluginInterface для внедрения зависимостей.

Преимущества использования внедрения зависимостей в Drupal:

1. Слабая связанность: Классы и сервисы не зависят друг от друга напрямую, что делает код более модульным и легко поддерживаемым.

2. Тестируемость: DI упрощает тестирование классов, так как можно передавать мок-объекты во время тестов, не полагаясь на реальные реализации сервисов.

3. Повторное использование: Сервисы могут быть повторно использованы в разных частях приложения, что улучшает повторное использование кода.

4. Гибкость: Зависимости можно легко заменять, что даёт большую гибкость коду. Например, можно внедрять разные сервисы в зависимости от окружения (например, для разработки или для продакшена).

Наиболее часто внедряемые сервисы в Drupal:

Сервис логирования: @logger.channel.default для логирования сообщений.

Менеджер типов сущностей: @entity_type.manager для работы с сущностями.

Подключение к базе данных: @database для взаимодействия с базой данных.

Фабрика конфигураций: @config.factory для получения конфигураций.

Messenger: @messenger для отображения сообщений пользователям.

Заключение:

В Drupal внедрение зависимостей улучшает модульность и гибкость приложения, позволяя внедрять сервисы по мере необходимости. Оно использует контейнер сервисов Symfony для разрешения зависимостей и их внедрения в блоки, контроллеры, формы и любые другие классы. Этот шаблон способствует использованию лучших практик, таких как слабая связанность и тестируемость кода.


Нужен профессиональный сайт на Drupal?
Ищете разработчиков для создания сайта на Drupal? Мы предлагаем профессиональные услуги по
разработке сайтов на Drupal любой сложности