> Что такое Dependency Injection (DI) (PHP)
Уровень: junior · Роль: backend · Язык: PHP · Категория: Технические вопросы
Компании: Travelata, vanta
Стек: PHP
> Пример ответа
Короткий ответ
Dependency Injection - это паттерн проектирования, при котором объект получает свои зависимости извне, а не создаёт их сам. Вместо new внутри класса зависимости передаются через конструктор, сеттер или специальный контейнер. Это делает код слабосвязанным, тестируемым и гибким. В PHP часто используется с PSR-11 контейнерами, например, в Laravel или Symfony.
Подробное объяснение
Основная идея DI - инверсия управления (IoC): класс не управляет созданием своих зависимостей, а получает готовые экземпляры. Это позволяет:
- заменять реализации без изменения класса (например, mock на тестах);
- переиспользовать объекты и управлять их жизненным циклом;
- явно видеть зависимости класса через сигнатуру конструктора.
Различают три способа внедрения:
- Constructor injection - зависимости передаются через конструктор. Самый распространённый и предпочтительный, так как гарантирует наличие всех зависимостей.
- Setter injection - зависимости устанавливаются через методы-сеттеры. Удобен для опциональных зависимостей.
- Property injection - прямое присваивание публичных свойств. Используется редко, так как нарушает инкапсуляцию.
В PHP DI обычно реализуется через service container - объект, который хранит конфигурацию создания сервисов и автоматически разрешает зависимости. Например, в Laravel это app() или Illuminate\Container\Container, в Symfony - ServiceContainer.
Важно отличать DI от Service Locator: DI передаёт зависимости внутрь, а Service Locator - объект сам запрашивает их из контейнера. DI предпочтительнее, так как не скрывает зависимости.
На практике
В реальном PHP-проекте DI применяется повсеместно:
- Контроллеры получают репозитории и сервисы через конструктор.
- Сервисы зависят от других сервисов (например,
UserServiceзависит отUserRepositoryиMailer). - Тестирование: в unit-тестах вместо реальных классов подставляются mock-объекты, что возможно только при внедрении через конструктор.
Пример из Laravel: в routes/web.php или контроллере вы не создаёте new UserRepository(), а просто указываете тип в параметре метода - контейнер сам разрешит зависимость.
Пример кода
PHP<?phpinterface MailerInterface{public function send(string $to, string $message): bool;}class SmtpMailer implements MailerInterface{public function send(string $to, string $message): bool{// реальная отправкаreturn true;}}class UserService{public function __construct(private readonly UserRepository $repository,private readonly MailerInterface $mailer) {}public function register(string $email, string $password): User{$user = $this->repository->create($email, $password);$this->mailer->send($email, 'Welcome!');return $user;}}// Без DI - жёсткая связь$service = new UserService(new UserRepository(), new SmtpMailer());// С DI-контейнером (Laravel)$service = app(UserService::class);
Как отвечать на собеседовании
Начните с короткого определения: "DI - это передача зависимостей извне". Затем приведите пример из реального кода: контроллер, который получает репозиторий через конструктор. Упомяните преимущества: тестируемость, слабая связанность, переиспользование. Если спросят про контейнер - объясните, что контейнер автоматически создаёт и внедряет зависимости, но DI - это сам паттерн, а контейнер - инструмент.
Для уровня junior достаточно показать понимание constructor injection и зачем это нужно. Не углубляйтесь в детали реализации контейнеров, если не спрашивают.
Что проверяет интервьюер
Интервьюер оценивает:
- понимание разницы между созданием зависимости внутри класса и получением извне;
- знание способов внедрения и когда какой применять;
- умение объяснить пользу для тестирования и архитектуры;
- базовое понимание service container в PHP-фреймворках.
Для junior важно показать, что вы не просто выучили термин, а понимаете проблему, которую решает DI: жёсткая связанность и невозможность подмены зависимостей.
Типичные ошибки
- Путаница DI и IoC-контейнера: DI - это паттерн, контейнер - реализация. Можно использовать DI без контейнера.
- Внедрение через
newвнутри класса: если вы создаёте зависимость внутри конструктора или метода - это не DI. - Чрезмерное использование setter injection: это делает объект неполностью инициализированным и усложняет тестирование.
- Непонимание, зачем DI в тестах: без DI невозможно подменить реальный сервис на mock.
- Ответ "DI - это когда передаёшь объект в конструктор" без объяснения пользы - слишком поверхностно для собеседования.
> Похожие задачи по PHP
> Похожие задачи по backend
Что происходит при выполнении функции main с набором принтов и что выводится в консоли
Что может выступать корневым элементом для сборщика мусора
Что такое inline функция
Что такое кроссфункциональная команда
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью