Вопрос проверяет понимание контейнера зависимостей Laravel и умение настраивать внедрение интерфейсов и их реализаций.
В Laravel привязка интерфейса к реализации выполняется через контейнер зависимостей с помощью методов bind(), singleton() и похожих. Чаще всего это делается в сервис-провайдерах, в методе register(). Благодаря этому Laravel автоматически подставляет нужную реализацию, когда интерфейс используется в конструкторе класса. Это позволяет легко менять реализацию без правок бизнес-кода.
Контейнер зависимостей — один из ключевых механизмов Laravel, и привязка интерфейсов к реализациям является его основной задачей.
Определение: Binding — это правило в контейнере, которое говорит Laravel, какой конкретный класс нужно создать, когда запрашивается интерфейс или абстракция.
Перед примерами важно понимать, что привязки обычно делаются в register() сервис-провайдера.
bind
Создаёт новый объект при каждом запросе из контейнера.
$this->app->bind(
\App\Contracts\Mailer::class,
\App\Services\SmtpMailer::class
);
singleton
Создаёт один объект и переиспользует его во всём приложении.
$this->app->singleton(
\App\Contracts\Clock::class,
\App\Services\SystemClock::class
);
bind с замыканием
Используется, если объект нужно создавать вручную или передавать параметры.
$this->app->bind(\App\Contracts\Report::class, function () {
return new \App\Services\PdfReport(/* зависимости */);
});
Когда интерфейс указан в конструкторе, Laravel сам находит нужную реализацию:
class UserService
{
public function __construct(
\App\Contracts\Mailer $mailer
) {}
}
Контроллер или сервис не знает, какой именно класс будет использоваться — это решает контейнер.
Ослабляет связность кода
Упрощает тестирование (легко подменить реализацию)
Делает код гибким к изменениям
Привязку интерфейсов к реализациям стоит всегда делать через контейнер (bind / singleton) в сервис-провайдерах, чтобы бизнес-код зависел от абстракций, а не от конкретных классов.