Laravel: Сервис Контейнер — что нужно знать новичкам
теоретических слов. Давайте приступим к практике, и я покажу основные практические примеры, которые вам нужно знать.
Первое: в большинстве случаев вам никогда не придётся работать напрямую с Сервис Контейнером. Для новичков достаточно понять, что Сервис Контейнер — это внутренний механизм Laravel, который позволяет делать определённые инъекции классов авто-магически
, вот и всё.
Другими словами, вам нужно забыть о Сервис Контейнере
и вместо этого изучить практические примеры его использования. Итак, приступим к ним.
Простой пример: Класс Запроса Формы
Позвольте мне показать, что вы, вероятно, уже использовали Сервис Контейнер, даже не подозревая об этом. Посмотрите на этот пример:
// UserController.php:
public function store(StoreUserRequest $request) {
User::create($request->validated());
// ...
}
Видите этот StoreUserRequest
, как объявление типа в методе? Это типичный класс Запроса Формы Заметили, что мы не инициализируем экземпляр этого класса? Laravel сделает это за нас, если мы укажем его как объявление типа в методе.
Другими словами, нам не нужно делать это вручную внутри метода:
$request = new StoreUserRequest();
Так что это делает Сервис Контейнер, он разрешает
экземпляр этого класса и автоматически создаёт объект для нас.
Другой типичный пример: Внедрение метода контроллера
Мы часто хотим использовать внешние классы в наших контроллерах. В курсе о структуре проекта Laravel я обсуждал различные используемые классы: Сервисы, Action и т.д. Возьмём в качестве примера Сервисы.
Вопрос: как инициализировать сервисный класс, чтобы использовать его внутри нашего контроллера?
Самый простой способ:
// UserController.php:
public function store(StoreUserRequest $request) {
$userService = new UserService();
$userService->create($request->validated());
}
Но что, если я вам скажу, что не нужно инициализировать сервис с помощью new UserService()
? И, может быть, вы догадались, чем именно Сервис Контейнер может нам помочь?
Вот ответ:
public function store(StoreUserRequest $request, UserService $userService) {
$userService->create($request->validated());
}
Да, мы просто добавляем класс, который хотим использовать внутри метода, с указанием типа, и Laravel автоматически создаст свою переменную для использования внутри метода.
И вы можете сделать это в любом методе в ваших контроллерах.
Сервис Контейнер работает только для методов? Что насчёт конструкторов?
Я рад, что вы спросили. Довольно часто вам нужно использовать класс в нескольких методах контроллера.
Итак, неудобный способ:
public function store(StoreUserRequest $request, UserService $userService) {
$userService->create($request->validated());
}
public function update(User $user, UpdateUserRequest $request, UserService $userService) {
$userService->update($user, $request->validated());
}
Можем ли мы инициализировать UserService
для всего контроллера? Конечно!
public function __construct(public UserService $userService)
{
}
public function store(StoreUserRequest $request) {
$this->userService->create($request->validated());
}
public function update(User $user, UpdateUserRequest $request) {
$this->userService->update($user, $request->validated());
}
Обратите внимание: мы используем одну из функций PHP 8 - объявление свойств в конструкторе, поэтому конструктор пуст.
Сервис Контейнер работает только в контроллерах?
Согласно официальной документации, нет:
Вы можете объявить тип зависимости в конструкторе класса, которая решается контейнером, включая контроллеры, слушатели событий, посредники и т.д. Кроме того, вы можете объявить тип зависимости в методе
handle
обработки заданий поставленных в очередь.
Не уверен, что означает это и т.д.
, но вы можете попробовать использовать Сервис Контейнер в любом другом классе Laravel и посмотреть работали он.
Теперь, если у вас есть свой собственный PHP класс и вы попытаетесь использовать этот трюк
, это не сработает, потому что Laravel не узнает об этом.
Например, если у вас есть Сервисный PHP класс:
class UserService {
public function __construct(SomeOtherService $someService) {}
}
Это не сработает.
Продвинутый уровень: Ручная привязка и другое
В принципе, приведённой выше информации достаточно для начинающих, чтобы знать её на практическом уровне. Вам необязательно знать как работает Сервис Контейнер внутри, или как связать/разрешить зависимые классы в более сложных случаях.
Но если вы хотите узнать об этом… вы можете, конечно, прочитать всю страницу официальной документации.