Что такое Service Container и Service Provider?php-77

1. Service Container

Определение

Service Container — это мощный инструмент для управления зависимостями и выполнения внедрения зависимостей (DI) в Laravel. По сути, это "коробка", где хранятся все сервисы приложения.

Основные возможности:

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

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

Простая регистрация:

app()->bind('MyService', function($app) {
    return new MyService($app->make('AnotherService'));
});

Автоматическое разрешение:

class UserController {
    public function __construct(protected UserService $service) {}
}

Синглтон-регистрация:

app()->singleton('Analytics', function() {
    return new AnalyticsService();
});

2. Service Provider

Определение

Service Provider — это центральное место для регистрации и настройки сервисов в Laravel. Это "точка входа" для подключения функциональности в приложение.

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

  • register() — регистрация сервисов в контейнере
  • boot() — выполнение после регистрации всех провайдеров

Пример провайдера:

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Services\PaymentGateway;
use App\Services\StripeGateway;

class PaymentServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind(PaymentGateway::class, function($app) {
            return new StripeGateway(config('services.stripe.key'));
        });
    }

    public function boot()
    {
        // Инициализация после регистрации всех сервисов
    }
}

3. Взаимодействие Container и Provider

  1. При запуске приложения:

    • Laravel загружает всех провайдеров из config/app.php
    • Вызывает их методы register()
    • После регистрации всех вызывает boot()
  2. При обращении к сервису:

    • Контейнер ищет зарегистрированную привязку
    • Автоматически разрешает зависимости
    • Возвращает экземпляр (новый или существующий)

4. Продвинутые техники

Контекстное связывание:

$this->app->when(PhotoController::class)
          ->needs(Filesystem::class)
          ->give(function() {
              return Storage::disk('photos');
          });

Тегирование сервисов:

$this->app->tag([ReportA::class, ReportB::class], 'reports');

$this->app->bind('ReportAggregator', function($app) {
    return new ReportAggregator($app->tagged('reports'));
});

Расширение сервисов:

$this->app->extend(Service::class, function($service, $app) {
    return new DecoratedService($service);
});

5. Практические примеры

Регистрация кастомного сервиса:

  1. Создаем провайдера:
php artisan make:provider GeoServiceProvider
  1. Регистрируем сервис:
public function register()
{
    $this->app->singleton('geocoder', function($app) {
        return new GoogleGeocoder(
            config('services.google.maps_key')
        );
    });
}
  1. Используем:
$coordinates = app('geocoder')->addressToCoordinates($address);

6. Отличия и взаимосвязь

Характеристика Service Container Service Provider
Роль Хранилище зависимостей Регистратор сервисов
Использование Автоматическое Явное через методы
Методы bind, singleton, make register, boot
Время работы Весь цикл приложения Загрузка приложения

Резюмируем:

  1. Service Container — это:

    • DI-контейнер для управления зависимостями
    • Автоматический резолвер классов
    • Центральное хранилище сервисов
  2. Service Provider — это:

    • Место для регистрации сервисов
    • "Точка подключения" функциональности
    • Организатор процесса инициализации
  3. Ключевые принципы:

    • Все сервисы регистрируются в контейнере
    • Провайдеры — рекомендуемый способ регистрации
    • Контейнер автоматически разрешает зависимости

Для эффективной работы:

  • Используйте провайдеры для группировки связанных сервисов
  • Применяйте правильные типы связывания (bind/singleton)
  • Используйте интерфейсы для слабой связанности
  • Избегайте сервис-локатора (app()->make()) в контроллерах