Как реализуется инъекция зависимостей в бизнес-логике с использованием Laravel?

Как использовать тайп хинты и автоматическое создание классов в PHP для правильной передачи зависимостей в конструкторах контроллеров и бизнес-классов? Какая последовательность должна быть при передаче зависимостей в конструкторах для корректной работы приложения?
  • 4 января 2024 г. 18:28
Ответы на вопрос 2
В Laravel инъекция зависимостей реализуется с помощью сервис-контейнера, который является мощной инструментом для управления классами и зависимостями между ними.

Вот как можно использовать инъекцию зависимостей в бизнес-логике:

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

```php
interface PaymentGatewayInterface {
    public function charge($amount);
}
```

2. Реализация интерфейса:
Теперь нужно реализовать интерфейс в одном или нескольких классах.

```php
class StripePaymentGateway implements PaymentGatewayInterface {
    public function charge($amount) {
        // Реализация для Stripe
    }
}

class PaypalPaymentGateway implements PaymentGatewayInterface {
    public function charge($amount) {
        // Реализация для PayPal
    }
}
```

3. Привязка интерфейса к реализации:
Далее вы привязываете интерфейс к конкретной реализации, используя сервис-провайдер. Это делается в методе `register` сервис-провайдера.

```php
public function register() {
    $this->app->bind(PaymentGatewayInterface::class, StripePaymentGateway::class);
}
```

4. Инъекция зависимости с помощью тайп-хинтинга:
Теперь можно внедрить зависимость в конструктор любого класса (например, контроллера), и Laravel автоматически разрешит эту зависимость через сервис-контейнер.

```php
class PaymentController extends Controller {
    protected $paymentGateway;

    public function __construct(PaymentGatewayInterface $paymentGateway) {
        $this->paymentGateway = $paymentGateway;
    }

    public function charge() {
        $this->paymentGateway->charge(100);
        //...
    }
}
```

При вызове методов класса `PaymentController`, Laravel поймет, что ему нужно предоставить экземпляр класса, который реализует `PaymentGatewayInterface`, и если в сервис-контейнере привязана конкретная реализация, то он передаст ее в конструктор.

При передаче зависимостей в конструкторах важно следовать следующей последовательности:

1. Сначала идут зависимости, которые разрешаются сервис-контейнером, и которые задекларированы через тайп-хинтинг.
2. Потом можно указывать примитивные типы данных или значения по умолчанию.

Пример:

```php
public function __construct(PaymentGatewayInterface $paymentGateway, $taxRate = 0.2) {
    // ...
}
```

Такой порядок важен, потому что Laravel не решает автоматически зависимости для аргументов, которые не имеют тайп-хинтинга или которым не привязаны реализации в сервис-контейнере.
Похожие вопросы