Что такое DI (Dependency Injection)?php-32

Dependency Injection (DI) — это паттерн проектирования, реализующий принцип инверсии управления (IoC), где зависимости не создаются внутри класса, а передаются извне. Это фундаментальная практика современного PHP-разработки.

Основные принципы DI

  1. Инверсия контроля: Классы не создают зависимости самостоятельно
  2. Разделение ответственности: Создание объектов выносится за пределы классов
  3. Тестируемость: Легкая замена зависимостей на моки

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

  1. Constructor Injection (наиболее предпочтительный):
class OrderService {
    private $paymentGateway;

    public function __construct(PaymentGateway $gateway) {
        $this->paymentGateway = $gateway;
    }
}
  1. Setter Injection (для опциональных зависимостей):
class Logger {
    private $writer;

    public function setWriter(LogWriter $writer) {
        $this->writer = $writer;
    }
}
  1. Interface Injection (реализация через интерфейсы):
interface LoggerAware {
    public function setLogger(Logger $logger);
}

DI Container

Продвинутая реализация DI, которая:

  • Автоматически разрешает зависимости
  • Управляет жизненным циклом объектов
  • Реализует шаблон Singleton

Пример простого контейнера:

class Container {
    private $services = [];

    public function register(string $class, callable $factory) {
        $this->services[$class] = $factory;
    }

    public function resolve(string $class) {
        if (isset($this->services[$class])) {
            return $this->services[$class]($this);
        }
        return new $class();
    }
}

Практический пример с DI

Без DI:

class OrderProcessor {
    public function process() {
        $validator = new OrderValidator();
        $repository = new OrderRepository();
        // ...
    }
}

С DI:

class OrderProcessor {
    private $validator;
    private $repository;

    public function __construct(
        OrderValidator $validator,
        OrderRepository $repository
    ) {
        $this->validator = $validator;
        $this->repository = $repository;
    }
}

Преимущества DI

  1. Гибкость: Легкая замена реализаций
  2. Тестируемость: Простое внедрение mock-объектов
  3. Чистота кода: Явное объявление зависимостей
  4. Повторное использование: Общие зависимости для разных классов

Популярные DI-контейнеры в PHP

  1. Symfony DependencyInjection
  2. PHP-DI
  3. Laravel Service Container
  4. Auryn

Пример использования PHP-DI:

use DI\ContainerBuilder;

$builder = new ContainerBuilder();
$builder->addDefinitions([
    'Database' => function() {
        return new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
    }
]);
$container = $builder->build();

$db = $container->get('Database');

Лучшие практики

  1. Всегда используйте внедрение через конструктор для обязательных зависимостей
  2. Избегайте сервис-локатора (Service Locator) — это антипаттерн
  3. Разделяйте создание объектов и их использование
  4. Используйте интерфейсы для абстракции зависимостей

Резюмируем:

  • DI — это передача зависимостей извне вместо их создания внутри класса
  • Основные типы: через конструктор, сеттеры и интерфейсы
  • DI-контейнеры автоматизируют управление зависимостями
  • Паттерн значительно улучшает тестируемость и гибкость кода
  • Является ключевым принципом SOLID (D — Dependency Inversion Principle)