что такое контейнер laravel
Laravel Framework Russian Community
Prologue
Getting Started
Architecture Concepts
The Basics
Frontend
Security
Digging Deeper
Database
Eloquent ORM
Testing
Official Packages
Сервис-контейнер
Введение
Сервис-контейнер в Laravel — это мощное средство для управления зависимостями классов и внедрения зависимостей. Внедрение зависимостей — это распространенный термин, который означает добавление других классов в этот класс через конструктор или, в некоторых случаях, метод-сеттер.
Давайте взглянем на простой пример:
В этом примере UserController должен получить пользователей из хранилища данных. Поэтому мы будем внедрять сервис, который может получить пользователей. В данном контексте наш UserRepository скорее всего использует Eloquent для получения информации пользователя из базы данных. Однако, так как внедряется репозиторий, мы можем легко подменить его с другой реализацией. Также можно легко создать «заглушку» или фиктивную реализацию UserRepository при тестировании нашего приложения.
Глубокое понимание сервис-контейнера Laravel важно для создания мощного, высокопроизводительного приложения, а также для работы с самим ядром Laravel.
Связывание
Основы связывания
Поскольку почти все ваши привязки сервис-контейнеров будут зарегистрированы в сервис-провайдерах, то все следующие примеры демонстрируют использование контейнеров в данном контексте.
Если классы не зависят от каких-либо интерфейсов, то нет необходимости связывать их в контейнере. Не нужно объяснять контейнеру, как создавать эти объекты, поскольку он автоматически извлекает такие объекты при помощи рефлексии.
Простые связывания
Обратите внимание, что мы получаем сам контейнер в виде аргумента ресолвера. Затем мы можем использовать контейнер, чтобы получать под-зависимости создаваемого объекта.
Привязка синглтона
Метод singleton привязывает класс или интерфейс к контейнеру, который должен быть создан только один раз, и все последующие обращения к нему будут возвращать этот созданный экземпляр:
Привязка экземпляра
Связывание примитивов
Иногда у вас может быть класс, который получает некие внедрённые классы, но которому также требуется внедрение примитивных значений, таких как целые числа. Вы можете легко использовать контекстную привязку для внедрения любых значений, которые могут понадобиться вашему классу:
Связывание интерфейса с реализацией
Контекстное связывание
Тегирование
Теперь вы можете получить их по тегу методом tagged :
Применение на практике
Метод make
Вы можете использовать метод make для получения экземпляра класса из контейнера. Метод make принимает имя класса или интерфейса, который вы хотите получить:
В некоторых зависимостях вашего класса, которые нельзя получить через контейнер, можно внедрять их, передавая их в качестве ассоциативного массива в метод makeWith :
Автоматическое внедрение
И, наконец, самое главное, вы можете просто указать тип зависимости в конструкторе класса, который имеется в контейнере, включая контроллеры, слушателей событий, очереди задач, посредников и др. Это те способы, с помощью которых получаются большинство объектов из контейнера на практике.
Например, вы можете указать тип репозитория, определённого вашим приложением в конструкторе контроллера. Репозиторий будет автоматически получен и внедрён в класс:
События контейнера
Контейнер создаёт событие каждый раз, когда из него извлекается объект. Вы можете слушать эти события, используя метод resolving :
Как видите, объект, получаемый из контейнера, передаётся в функцию обратного вызова, что позволяет вам задать любые дополнительные свойства для объекта перед тем, как отдать его тому, кто его запросил.
PSR-11
Сервис-контейнер Laravel реализует интерфейс PSR-11. Поэтому вы можете использовать интерфейс контейнера PSR-11 в качестве подсказки типа для получения экземпляра контейнера Laravel:
Вызов метода get выбросит исключение, если идентификатор не был явно привязан к контейнеру.
Laravel Framework Russian Community
Prologue
Getting Started
Architecture Concepts
The Basics
Frontend
Security
Digging Deeper
Database
Eloquent ORM
Testing
Official Packages
Сервис-контейнер
Введение
Сервис-контейнер в Laravel — это мощное средство для управления зависимостями классов и внедрения зависимостей. Внедрение зависимостей — это распространенный термин, который означает добавление других классов в этот класс через конструктор или, в некоторых случаях, метод-сеттер.
Давайте взглянем на простой пример:
В этом примере UserController должен получить пользователей из хранилища данных. Поэтому мы будем внедрять сервис, который может получить пользователей. В данном контексте наш UserRepository скорее всего использует Eloquent для получения информации пользователя из базы данных. Однако, так как внедряется репозиторий, мы можем легко подменить его с другой реализацией. Также можно легко создать «заглушку» или фиктивную реализацию UserRepository при тестировании нашего приложения.
Глубокое понимание сервис-контейнера Laravel важно для создания мощного, высокопроизводительного приложения, а также для работы с самим ядром Laravel.
Связывание
Основы связывания
Поскольку почти все ваши привязки сервис-контейнеров будут зарегистрированы в сервис-провайдерах, то все следующие примеры демонстрируют использование контейнеров в данном контексте.
Если классы не зависят от каких-либо интерфейсов, то нет необходимости связывать их в контейнере. Не нужно объяснять контейнеру, как создавать эти объекты, поскольку он автоматически извлекает такие объекты при помощи рефлексии.
Простые связывания
Обратите внимание, что мы получаем сам контейнер в виде аргумента ресолвера. Затем мы можем использовать контейнер, чтобы получать под-зависимости создаваемого объекта.
Привязка синглтона
Метод singleton привязывает класс или интерфейс к контейнеру, который должен быть создан только один раз, и все последующие обращения к нему будут возвращать этот созданный экземпляр:
Привязка экземпляра
Связывание примитивов
Иногда у вас может быть класс, который получает некие внедрённые классы, но которому также требуется внедрение примитивных значений, таких как целые числа. Вы можете легко использовать контекстную привязку для внедрения любых значений, которые могут понадобиться вашему классу:
Связывание интерфейса с реализацией
Контекстное связывание
Тегирование
Теперь вы можете получить их по тегу методом tagged :
Применение на практике
Метод make
Вы можете использовать метод make для получения экземпляра класса из контейнера. Метод make принимает имя класса или интерфейса, который вы хотите получить:
В некоторых зависимостях вашего класса, которые нельзя получить через контейнер, можно внедрять их, передавая их в качестве ассоциативного массива в метод makeWith :
Автоматическое внедрение
И, наконец, самое главное, вы можете просто указать тип зависимости в конструкторе класса, который имеется в контейнере, включая контроллеры, слушателей событий, очереди задач, посредников и др. Это те способы, с помощью которых получаются большинство объектов из контейнера на практике.
Например, вы можете указать тип репозитория, определённого вашим приложением в конструкторе контроллера. Репозиторий будет автоматически получен и внедрён в класс:
События контейнера
Контейнер создаёт событие каждый раз, когда из него извлекается объект. Вы можете слушать эти события, используя метод resolving :
Как видите, объект, получаемый из контейнера, передаётся в функцию обратного вызова, что позволяет вам задать любые дополнительные свойства для объекта перед тем, как отдать его тому, кто его запросил.
PSR-11
Сервис-контейнер Laravel реализует интерфейс PSR-11. Поэтому вы можете использовать интерфейс контейнера PSR-11 в качестве подсказки типа для получения экземпляра контейнера Laravel:
Вызов метода get выбросит исключение, если идентификатор не был явно привязан к контейнеру.
Laravel Framework Russian Community
Введение
Вот простой пример:
Использование
Связывание (Binding, регистрация)
Регистрация обычного класса
Регистрация класса-синглтона
Иногда вам нужно, чтобы объект создавался один раз, а все остальные разы, когда вы запрашиваете его, вам возвращался тот же созданный экземпляр. В этом случае вместо bind используйте singleton :
Добавление существующего экземпляра класса в контейнер
Вы можете добавить в контейнер существующий экземпляр класса:
Получение из контейнера
Есть несколько способов получить (resolve) содержимое контейнера. Во-первых, вы можете использовать метод make() :
Во-вторых, вы можете обратиться к контейнеру как к массиву:
И, наконец, в-третьих (и в главных) вы можете явно указать тип аргумента в конструкторе класса и фреймворк сам возьмёт его из контейнера (в примере ниже это UserRepository ):
Связывание интерфейса с реализацией
Инъекции зависимостей
От класса к интерфейсу
Для того, чтобы «изолировать» класс CreateOrderHandler от постоянно меняющегося внешнего мира, определим некий постоянный интерфейс, с реализациями которого наш класс будет теперь работать.
Теперь, с какой бы реализацией работы реалтаймовых сообщений мы бы ни работали, изменять код в CreateOrderHandler нам не потребуется.
Контекстное связывание
Иногда у вас может быть несколько реализаций одного интерфейса и вы хотите внедрять их каждый в свой класс. Например, когда делается новый заказ, вам нужно отправлять сообщение в PubNub вместо Pusher. Вы можете сделать это следующим образом:
Тэгирование
Теперь вы можете получить их все сразу по тэгу:
Использование на практике
Другие примеры
Разумеется, контроллеры не единственные классы, которые фреймворк берет из сервис-контейнера. Вы можете использовать этот же принцип в обработчиках маршрутов, событий, очередей и т.д. Примеры использования сервис-контейнера приведены в соответствующих разделах документации.
События контейнера
Регистрация события на извлечение объекта из контейнера
Сервис-контейнер запускает событие каждый раз, когда объект извлекается из контейнера. Можно ловить все события, можно только те, которые привязаны к конкретному ключу.
Объект, получаемый из контейнера, передается в функцию-коллбэк.
Laravel 8 · Контейнер служб
Введение
Контейнер служб Laravel – это мощный инструмент для управления зависимостями классов и выполнения внедрения зависимостей. Внедрение зависимостей – это причудливая фраза, которая по существу означает следующее: зависимости классов «вводятся» в класс через конструктор или, в некоторых случаях, через методы «сеттеры».
Давайте посмотрим на простой пример:
Глубокое понимание контейнера служб Laravel необходимо для создания большого, мощного приложения, а также для внесения вклада в само ядро Laravel.
Неконфигурируемое внедрение
Если класс не имеет зависимостей или зависит только от других конкретных классов (не интерфейсов), контейнер не нужно инструктировать о том, как создавать этот класс. Например, вы можете поместить следующий код в свой файл routes/web.php :
В этом примере, при посещении / вашего приложения, маршрут автоматически получит класс Service и внедрит его в обработчик вашего маршрута. Это меняет правила игры. Это означает, что вы можете разработать свое приложение и воспользоваться преимуществами внедрения зависимостей, не беспокоясь о раздутых файлах конфигурации.
К счастью, многие классы, которые вы будете писать при создании приложения Laravel, автоматически получают свои зависимости через контейнер, включая контроллеры, слушатели событий, посредники и т.д. Кроме того, вы можете объявить зависимости в методе handle заданиям в очередях. Как только вы почувствуете всю мощь автоматического неконфигурируемого внедрения зависимостей, вы почувствуете невозможность разработки без нее.
Когда использовать контейнер
Благодаря неконфигурируемому внедрению, вы часто будете объявлять типы зависимостей в маршрутах, контроллерах, слушателях событий и других местах, не взаимодействуя с контейнером напрямую. Например, вы можете указать объект Illuminate\Http\Request в определении вашего маршрута, чтобы вы могли легко получить доступ к текущему запросу. Несмотря на то, что нам никогда не нужно взаимодействовать с контейнером для написания этого кода, он управляет внедрением этих зависимостей за кулисами:
Во многих случаях, благодаря автоматическому внедрению зависимостей и фасадам, вы можете строить приложения Laravel без необходимости когда-либо вручную связывать или извлекать что-либо из контейнера. Итак, когда бы вы могли вручную взаимодействовать с контейнером?. Давайте рассмотрим две ситуации.
Во-первых, если вы пишете класс, реализующий интерфейс, и хотите объявить тип этого интерфейса в конструкторе маршрута или класса, вы должны сообщить контейнеру, как получить этот интерфейс. Во-вторых, если вы пишете пакет Laravel, которым планируете поделиться с другими разработчиками Laravel, вам может потребоваться связать службы вашего пакета в контейнере.
Связывание
Основы связываний
Простое связывание
Почти все ваши связывания в контейнере служб будут зарегистрированы в поставщиках служб, поэтому в большинстве этих примеров будет продемонстрировано использование контейнера в этом контексте.
Обратите внимание, что мы получаем сам контейнер в качестве аргумента. Затем мы можем использовать контейнер для извлечения под-зависимостей объекта, который мы создаем.
Как уже упоминалось, вы обычно будете взаимодействовать с контейнером внутри поставщиков служб; однако, если вы хотите взаимодействовать с контейнером вне поставщика услуг, вы можете сделать это через фасад App :
Нет необходимости привязывать классы в контейнере, если они не зависят от каких-либо интерфейсов. Контейнеру не нужно указывать, как создавать эти объекты, поскольку он может автоматически извлекать эти объекты с помощью рефлексии.
Связывание одиночек
Метод singleton связывает класс или интерфейс в контейнере, который должен быть извлечен только один раз. После получения одиночки, тот же экземпляр объекта будет возвращен из контейнера и при последующих вызовах:
Связывание экземпляров
Связывание интерфейсов и реализаций
Контекстная привязка
Связывание примитивов
Иногда, у вас может быть класс, который получает некоторые внедренные классы, но также нуждается в примитиве, таком как целое число. Вы можете легко использовать контекстную привязку, чтобы внедрить любое значение, которое может понадобиться вашему классу:
Если вам нужно внедрить значение из одного из конфигурационных файлов вашего приложения, то вы можете использовать метод giveConfig :
Связывание типизированных вариаций
Иногда у вас может быть класс, который получает массив типизированных объектов с использованием переменного количества аргументов (прим. перев.: далее «вариации») конструктора:
Используя контекстную привязку, вы можете внедрить такую зависимость, используя метод give с замыканием, которое возвращает массив внедряемых экземпляров Filter :
Для удобства вы также можете просто передать массив имен классов, которые будут предоставлены контейнером всякий раз, когда для Firewall нужны экземпляры Filter :
Метки вариативных зависимостей
Добавление меток
После того, как службы помечены, вы можете легко все их получить с помощью метода tagged :
Расширяемость связываний
Метод extend позволяет модифицировать извлеченные службы. Например, когда служба получена, вы можете запустить дополнительный код для декорирования или конфигурирования службы. Метод extend принимает замыкание, которое должно возвращать измененную службу в качестве единственного аргумента. Замыкание получает службу для извлечения и экземпляр контейнера:
Извлечение
Метод make
Вы можете использовать метод make для извлечения экземпляра класса из контейнера. Метод make принимает имя класса или интерфейса, который вы хотите получить:
Если вы хотите, чтобы сам экземпляр контейнера Laravel был внедрен в класс, извлекаемый контейнером, вы можете указать класс Illuminate\Container\Container в конструкторе вашего класса:
Автоматическое внедрение зависимостей
В качестве альтернативы, что важно, вы можете объявить тип зависимости в конструкторе класса, который извлекается контейнером, включая контроллеры, слушатели событий, посредники и т.д. Кроме того, вы можете объявить зависимости в методе handle заданиям в очередях. На практике именно так контейнер должен извлекать большинство ваших объектов.
Например, вы можете объявить репозиторий, определенный вашим приложением, в конструкторе контроллера. Репозиторий будет автоматически получен и внедрен в класс:
События контейнера
Контейнер служб инициирует событие каждый раз, когда извлекает объект. Вы можете прослушать это событие с помощью метода resolving :
Как видите, извлекаемый объект будет передан в замыкание, что позволит вам установить любые дополнительные свойства объекта до того, как он будет передан его получателю.
PSR-11
Контейнер служб Laravel реализует интерфейс PSR-11. Поэтому вы можете объявить тип интерфейса контейнера PSR-11, чтобы получить экземпляр контейнера Laravel:
Laravel Framework Russian Community
Пролог
Начало работы
Основы архитектуры
Основы
Фронтенд
Безопасность
Копаем глубже
База данных
Eloquent ORM
Тестирование
Официальные пакеты
Сервис-контейнер
Введение
Сервис-контейнер в Laravel — это мощное средство для управления зависимостями классов и внедрения зависимостей. Внедрение зависимостей — это распространенный термин, который означает добавление других классов в этот класс через конструктор или, в некоторых случаях, метод-сеттер.
Давайте взглянем на простой пример:
В этом примере UserController должен получить пользователей из хранилища данных. Поэтому мы будем внедрять сервис, который может получить пользователей. В данном контексте наш UserRepository скорее всего использует Eloquent для получения информации пользователя из базы данных. Однако, так как внедряется репозиторий, мы можем легко подменить его с другой реализацией. Также можно легко создать «заглушку» или фиктивную реализацию UserRepository при тестировании нашего приложения.
Глубокое понимание сервис-контейнера Laravel важно для создания мощного, высокопроизводительного приложения, а также для работы с самим ядром Laravel.
Связывание
Основы связывания
Поскольку почти все ваши привязки сервис-контейнеров будут зарегистрированы в сервис-провайдерах, то все следующие примеры демонстрируют использование контейнеров в данном контексте.
Если классы не зависят от каких-либо интерфейсов, то нет необходимости связывать их в контейнере. Не нужно объяснять контейнеру, как создавать эти объекты, поскольку он автоматически извлекает такие объекты при помощи рефлексии.
Простые связывания
Обратите внимание, что мы получаем сам контейнер в виде аргумента ресолвера. Затем мы можем использовать контейнер, чтобы получать под-зависимости создаваемого объекта.
Привязка синглтона
Метод singleton привязывает класс или интерфейс к контейнеру, который должен быть создан только один раз, и все последующие обращения к нему будут возвращать этот созданный экземпляр:
Привязка экземпляра
Связывание примитивов
Иногда у вас может быть класс, который получает некие внедрённые классы, но которому также требуется внедрение примитивных значений, таких как целые числа. Вы можете легко использовать контекстную привязку для внедрения любых значений, которые могут понадобиться вашему классу:
Связывание интерфейса с реализацией
Контекстное связывание
Тегирование
Теперь вы можете получить их по тегу методом tagged :
Применение на практике
Метод make
Вы можете использовать метод make для получения экземпляра класса из контейнера. Метод make принимает имя класса или интерфейса, который вы хотите получить:
В некоторых зависимостях вашего класса, которые нельзя получить через контейнер, можно внедрять их, передавая их в качестве ассоциативного массива в метод makeWith :
Автоматическое внедрение
И, наконец, самое главное, вы можете просто указать тип зависимости в конструкторе класса, который имеется в контейнере, включая контроллеры, слушателей событий, очереди задач, посредников и др. Это те способы, с помощью которых получаются большинство объектов из контейнера на практике.
Например, вы можете указать тип репозитория, определённого вашим приложением в конструкторе контроллера. Репозиторий будет автоматически получен и внедрён в класс:
События контейнера
Контейнер создаёт событие каждый раз, когда из него извлекается объект. Вы можете слушать эти события, используя метод resolving :
Как видите, объект, получаемый из контейнера, передаётся в функцию обратного вызова, что позволяет вам задать любые дополнительные свойства для объекта перед тем, как отдать его тому, кто его запросил.