что такое сервис провайдер laravel
Сервис-провайдеры в laravel для самых маленьких
Laravel отличный инструмент. Современный, быстроразвивающийся, функциональный, только не всегда понятный. И речь не про то, что доки на нерусском, а то, что они даже на родном для фреймворка английском не всегда показательны.
Лично я потратил 2 дня за курением доков на русском, английском, несколько туториалов переведенных с совсем нерусского на менее нерусский, это когда чуваки пишут русскими буквами, но в русские несмогли. Попадались несколько на немецком и парочка на испанском, там только смотреть на код можно, благо код — интернациональен! Проблема всех официальных и около оффициальных мануалов — они копируют друг друга. И задача в тысяче источников рассматривается однобоко. А ещё я посмотрел несколько видео обучалок, ненавижу видео-туторы, это полчаса времени про то, что можно в 5 абзацев вместить. Это я и попробую сделать.
Понятийный аппарат
Главная проблема — нифига не понятно кто это такие Сервис-провайдеры и как сними работать.
Тут надо уяснить простую вещь. Сервис провайдеры — это не функциональные блоки, т.е. какую-то логику класть в них как минимум странно. По сути это функции-посредники, необходимые, чаще всего, чтобы закидывать некоторые сервисы в некое «быстрое хранилище» Сервис-контейнер.
А вот и ещё одно прикольное понятие Сервис-контейнер. Попробую на пальцах — это «ящик», в котором хранятся все зарегистрированные сервисы, чтобы быстро к ним доступаться это раз, а самое главное:
Сервис-контейнер в Laravel — это мощное средство для управления зависимостями классов и внедрения зависимостей.
Так нам рассказывает официальная документация. Если не совсем понятно, то лучше бы тебе, милый дружок, почитать обзорные статьи на понятия контейнер внедрения зависимостей. Если очень грубо: иногда наш объект должен иметь доступ к чему-то из вне. Например, есть объект пользователь, который учится в школе. Можно все поля связанные со школой уместить внутрь пользователя. Но это, очевидно, будет избыточно, 2 разных пользователя могут учиться в одной школе, поэтому создаем отдельный объект школа. А чтобы пользователь мог получить инфу о школе, мы в конструктор передаем зависимость от некоего хранилища школы, интерфейс, который по запросу может вернуть объект школы. Т.е. теперь при создании пользователя он сможет дергать внешнее хранилище и получать требуемые данные. Таким образом объект замкнут сам в себе. Понимаешь?! Это как нарисовать сову! Ой, всё! Давай потом на эту тему поговорим.
Вернемся к нашему предмету.Сервис-контейнер хранит внутри себя некие сервисы. А что такое сервис? А вот это как раз тот самый функциональный блок, который нам нужен. Отправка смс, вывод статистики по чему-либо и т.д. Все зарегистрированные сервисы кэшируются в /var/www/bootstrap/cache/services.php, можно глянуть кто и что туда добавились
Нафига это надо? Можно ж по старинке всё делать, нужен класс, дернул, не нужен не дернул. Так-то оно так, но одно дело когда перфоратор у тебя на балконе лежит, ты пошел и взял, а другое дело, когда он в гараже, у отца, в другом городе, в Белоруссии, а ты в Гремании. Ну ты понял. Скорость и удобство.
Кодовое выражение
Допустим, мы поняли что такое сервис-провайдеры. А как с ними жить и как это выражается в печатных символах в любимой IDE’шке?
Есть короткий ответ, вот так:
Именно так написано в документации. И ты такой: «Аааа! Тут же вон оно… И чё?» А я был готов к этому вопросу, не зря ж уже 2ю неделю пишу этот опус.
Собственно, мы говорим: Мне нужно, чтобы в сервис контейнере лежал экземпляр класса Riak\Connection (за это отвечает строка — return new Connection(config(‘riak’))) с именем равным исходному имени класса (а за это отвечает Connection::class) и я хочу чтобы это был единственный инстанс ($this->app->singleton). И теперь, если в любом месте приложения я попытаюсь дернуть что-то с именем Connection, то мне вернется уже созданный объект из контейнера зависимостей.
Всё это прекрасно, но главная боль всё ещё в силе — ЗАЧЕМ?
Зачем?
Это хороший вопрос, если скорость доступа уже не будоражит, то вот тебе ещё один отличный пример.
Как бы я сейчас это реализовал. Для начала опишем контракт, которому должны следовать все создаваемые системы оповещения. По сути, если снизойти до понятий php, контракт это всего лишь интерфейс, да, вот так просто. Но контракт — звучит гордо.
Конечно, в большинстве своем, это просто договорённость, ты можешь не наследоваться, но интерфейс обяжет тебя создавать все методы которые могут быть вызваны извне. В нашем случае нам очень нужен метод send().
Добавим пару реализаций, как огоговаривалось выше — EmailAlarm, PhoneAlarm, ну и какой-нибудь экзотический ArmyAlarm, это если бы мы жили в америке, то к тебе приехал бы офицер национальной гвардии и дал команду на эвакуацию.
Так.. И как я это хочу подвязать к сервис-провайдеру? Немного увлекся. Ах вот! Теперь мы создаем наш сервис провайдер, который… А лучше я сначала напишу, а оптом объясню
Пояснения нужны? Ну лааадно уж. В зависимости от силы урагана будет создан тот или иной инстанс по оповещению, если всё слабенько, то по почте, если сильно — по телефону, при этом в коде мы будем везде вызывать ContractAlarm->send(). Ну круто же! Теперь нашему приложению совершенно пофигу что там и как реализуется, оно просто дергает некий абстрактный ContractAlarm, который имеем нужный метод send (кстати, имя можно было дать и более приличное, типа Alarmer, но это по желанию, говорят, что принято имя в контейнере и имя исходного класса лучше делать одинаковыми) Поэтому и удобно все реализации наследовать от контракта, чтобы всё было хорошо.
Надо ещё не забыть в config/app.php в секцию providers добавить наш новый сервис провайдер.
Выводы
Все эти штуки, дело сугубо добровольное. Никто тебя палками бить не будет если тебе впадлос юзать общепринятые решения. Хочешь, откажись от ООП вообще, сейчас это модно всякие извращения, можешь вообще всё внутри одной функции писать, чего ж нет? Типа очень жесткий Front Controller, который реально «Всё в одном месте» =) Но на счет «палками бить», ты подумай, а то вдруг всё же кто-то придет
Update
Как мне справедливо накидали какашулей в комментариях, нужно признать, что я привёл не достаточно жизнеспособный пример.
Регистрация сервис-провайдеров происходит через файл конфига config/app.php, т.е. нет никакой явной передачи параметров. И вообще, как говорит документация и редит, в методе register должна быть исключительно привязка реализации к интерфейсу.
Первое что мне пришло в голову, это в другом сервисе, или даже в этом же сделать отдельную инициализацию объекта Hurricane. Но в этом случае фреймворк не гарантирует, что всё будет ок, потому что загрузка сервисов происходит в произвольном порядке. И не факт, что при инициализации ContractAlarm Ураган будет определён. Но (!) у сервис провайдера есть метод boot(), и вот этот метод однозначно гарантирует, что все другие сервисы уже инициированы. Поэтому весь код по определению Hurricane нужно из register() перенести в boot(). А Hurricane инициировать отдельным сервис-провайдером.
Правда, если включить голову, то становится понятно, что всё это избыточно и многословно. Сейчас я бы явно создал экземпляр внутри метода register(), т.е. прям DB::get. Либо же через файлы конфига достать нужные значения. Последнее это каноничное решение.
Итого: Передавать параметры в метод register() не надо. Нужны параметры, либо залезай в конфиги, либо в базу напрямую. Посылаю голову пеплом, спасибо за конструктив
Как зарегистрировать и использовать сервис провайдеры Laravel
Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)
Если вы когда-либо сталкивались с фреймворком Laravel, маловероятно, что вы не слышали о сервис контейнерах и поставщиках сервисов. Фактически, они являются основой фреймворка Laravel и делают весь тяжелый старт, когда вы запускаете экземпляр любого приложения Laravel.
В этой статье мы увидим, что такое контейнер служб, и после этого мы подробно обсудим сервис провайдеров В ходе этой статьи я также продемонстрирую, как создать свой пользовательский сервис провайдер в Laravel. Когда вы создаете сервис провайдера, вам также необходимо зарегистрировать его в своем приложении Laravel, чтобы можно было его использовать, поэтому мы это тоже рассмотрим.
Существует два важных метода: boot и register, которые может реализовать ваш сервис провайдер, и в последнем разделе этой статьи мы подробно их обсудим.
Прежде чем перейти к обсуждению поставщика услуг, я попытаюсь представить контейнер сервисов, поскольку он будет активно использоваться в вашей реализации сервис провайдера
Понимание сервисных контейнеров и сервис провайдеров
Что такое контейнер сервисов?
По словам официальной документации Laravel:
Таким образом, всякий раз, когда вам нужно встроить какой-либо компонент или службу, вы можете указать его в своем конструкторе или методе, и он будет автоматически встраиваться из контейнера служб, поскольку он содержит все, что вам нужно! Разве это не круто? Это избавляет вас от ручной компоновки компонентов и, таким образом, позволяет избежать жесткой связи в вашем коде.
Давайте посмотрим на быстрый пример, чтобы понять это.
Как вы можете видеть, SomeClass нуждается в экземпляре FooBar для создания экземпляра. Таким образом, в основном, у него есть зависимость, которую нужно встроить. Laravel делает это автоматически, просматривая контейнер и встраивая соответствующую зависимость.
Таким образом, сервис провайдер регистрирует все привязки контейнера, и это делается с помощью метода register реализации сервис провайдера.
Итак, это был контейнер в вашем распоряжении. В следующем разделе мы сосредоточимся на сервис провайдере, который является основной темой этой статьи!
Что такое сервис провайдер?
Давайте быстро взглянем на одного из основных сервис провайдеров, чтобы понять, что он делает. Откройте файл vender/laravel/framework/src/Illuminate/Cache/CacheServiceProvider.php.
И это была история о сервис провайдере. В следующем разделе мы обсудим, как создать специализированного сервис провайдера, чтобы вы могли зарегистрировать свои пользовательские сервисы в контейнере Laravel.
Создание собственного сервис провайдера
Как мы обсуждали ранее, существует два метода: register и booy, с которыми вы будете иметь дело большую часть времени, когда работаете с вашим пользовательским сервис провайдером.
Зарегистрируйте свой пользовательский сервис провайдер
Таким образом, вы создали своей собственный сервис провайдер. Замечательно! Затем вам нужно сообщить Laravel о своем специализированном сервис провайдере, чтобы он мог загрузить его вместе с другими провайдерами во время начальной загрузки.
Пройдемся по методам regsiter и boot
Здесь есть два важных момента:
И вот код где-то в вашем контроллере, где будет введена зависимость.
Это очень простой пример привязки класса. Фактически, в приведенном выше примере нет необходимости создавать сервис провайдер и внедрять метод register, как это было сделано, поскольку Laravel может автоматически разрешать его с помощью отражения.
Очень важное замечание из документации Laravel:
Нет необходимости связывать классы в контейнер, если они не зависят от каких-либо интерфейсов. Контейнеру не нужно указывать, как создавать эти объекты, поскольку он может автоматически разрешать эти объекты с помощью отражения.
С другой стороны, это было бы очень полезно, если бы вы связали интерфейс с определенной реализацией. Давайте рассмотрим пример, чтобы понять это.
Давайте создадим очень простой интерфейс в app/Library/Services/Contracts/CustomServiceInterface.php.
Теперь вместо привязки класса мы свяжем интерфейс. Снова откройте EnvatoCustomServiceProvider.php и измените код, как показано ниже.
Давайте быстро пересмотрим код контроллера.
Найдите следующую строку:
Аналогичным образом найдите это:
Это должно быть заменено на:
Тот же подход можно использовать, если вы хотите заменить любую основную реализацию своей собственной. И это не только метод bind, который вы могли бы использовать для привязки сервиса к контейнеру; Контейнер Laravel предоставляет различные способы привязки. Пожалуйста, ознакомьтесь с официальной документацией Laravel для полной справки.
Давайте рассмотрим несколько примеров, требующих реализации метода boot.
Вы хотите добавить свой собственный инструмент проверки поля формы в Laravel.
Если вы хотите зарегистрировать компоновщик отображений, то это идеальное место для этого! Фактически, можно сказать, что метод boot часто используется для добавления компоновщиков отображений!
Конечно, вам нужно в первую очередь импортировать фасад Illuminate\Support\Facades\View в своем сервис провайдере.
На этой же территории вы можете делиться данными и по нескольким представлениям!
Он также может использоваться для определения явных привязок к модели.
Это было несколько примеров, чтобы продемонстрировать использование метода boot. Чем больше вы погружаетесь в Laravel, тем больше причин вы найдете для его реализации!
И вот мы дошли до конца этой статьи. Надеюсь, вам понравились темы, которые в ней обсуждались.
Заключение
Именно обсуждение сервис провайдеров было главной достопримечательностью этой статьи, хотя мы начали нашу статью с контейнера для сервисов, поскольку это было важным компонентом для понимания работы сервис провайдера.
После этого мы разработали свой собственный сервис провайдер, а во второй половине статьи мы рассмотрели несколько практических примеров.
Для тех из вас, кто только начинает работать с Laravel или хочет расширить свои знания, сайт или приложение с расширениями, у нас есть множество вещей, которые вы можете изучать на Envato Market.
Если у вас есть какие-либо вопросы или комментарии, то обязательно оставляйте их в обратной связи ниже!
Laravel: сервис-контейнеры и сервис-провайдеры. Что это и зачем?
Недавно перешел с фреймворка CodeIgniter (в котором была простая схема MVC) на изучение Laravel. Фреймворк очень понравился, но есть некоторые моменты, которые я никак не могу понять, сколько бы не читал документацию. В частности что такое сервис-контейнеры и сервис-провайдеры и зачем они нужны. Прошу помочь разобраться.
2 ответа 2
Ну что-ж, попробую объяснить. С Богом!
Все возможности я не опишу, просто попытаюсь дать представление и возможно (скорее всего) не совсем точно.
Введение:
Вообще эти штуки нужны, в первую очередь, для удобства, как плюс — они реализуют паттерн Dependency Injection. С него и начнём.
Красиво. Нет! Почему? А в друг нам понадобится, чтобы при создании класс myClassB принимал аргументы в свой конструктор? Придётся переписывать. Вы скажете: «перепишу, ничего страшного«, но если таких классов myClassA много, то тут уже косяк — надо разруливать, для этого и придумали паттерн, глянем на то, как надо:
Сложно описать, давайте покажем, переведем наш класс myClassA в контроллер:
Но нужно теперь и MyClassB создать. Сразу вспомним начало, нам нужно учитывать что класс должен что-то принимать. Создаем папочку app\MyClass и там файлик MyClassB.php с текстом:
Из документации видно, что внутри метода register() как раз и должны быть наши связывания, простенькие примеры:
Стоит также одним глазком глянуть в документацию на строчку:
Если вы откроете файл config/app.php, поставляемый с Laravel, то увидите массив providers. В нём перечислены все классы сервис-провайдеров, которые загружаются для вашего приложения.
Наш MyProvider тоже должен быть в этом списке.
Дочитали до конца? Бонусы:
Laravel 8 · Поставщики служб
Введение
Поставщики служб – это центральное место начальной загрузки всех приложений Laravel. Ваше собственное приложение, а также все основные службы Laravel загружаются через поставщиков.
Но, что мы подразумеваем под «начальной загрузкой»? В общем, мы имеем в виду регистрацию элементов, включая регистрацию связываний контейнера служб, слушателей событий, посредников и даже маршрутов. Поставщики служб являются центральным местом для конфигурирования приложения.
В этой документации вы узнаете, как писать собственных поставщиков служб и регистрировать их в приложении Laravel.
Если вы хотите узнать больше о том, как Laravel обрабатывает запросы и работает изнутри, ознакомьтесь с нашей документацией по жизненному циклу запроса Laravel.
Написание поставщиков служб
Чтобы сгенерировать нового поставщика, используйте команду make:provider Artisan:
Метод register
Этот поставщик службы определяет только метод register и использует этот метод для определения реализации App\Services\Riak\Connection в контейнере служб. Если вы еще не знакомы с контейнером служб Laravel, ознакомьтесь с его документацией.
Свойства bindings и singletons
Если ваш поставщик службы регистрирует много простых связываний, вы можете использовать свойства bindings и singletons вместо ручной регистрации каждого связывания контейнера. Когда поставщик службы загружается фреймворком, он автоматически проверяет эти свойства и регистрирует их связывания:
Метод boot
Внедрение зависимости в методе boot
Вы можете указывать тип зависимостей в методе boot поставщика службы. Контейнер служб автоматически внедрит любые необходимые зависимости:
Регистрация поставщиков
Чтобы зарегистрировать поставщика, добавьте его в массив:
Отложенные поставщики
Если ваш поставщик регистрирует только связывания в контейнере служб, вы можете отложить его регистрацию до тех пор, пока одно из зарегистрированных связываний не понадобится. Отсрочка загрузки такого поставщика повысит производительность вашего приложения, так как он не загружается из файловой системы при каждом запросе.
Laravel составляет и сохраняет список всех служб, предоставляемых отложенными поставщиками служб, а также имя класса поставщика службы. Laravel загрузит поставщика службы только при необходимости в одной из этих служб.
Архитектура
Жизненный цикл
Одной из важнейших задач бутстраппинга в ядре является загрузка сервис-провайдеров, определенных в config/app.php в массиве providers. В каждом провайдере вызывается метод register (регистрирующий провайдера), а затем метод boot (собственно, загрузка провайдера). Сервис-провайдеры отвечают за загрузку всех компонентов фреймворка: базы данных, очередей задач, валидации, маршрутизации и т.д. Кастомные сервис-провайдеры, как уже было отмечено, располагаются в каталоге app/Providers. Главным из них является AppServiceProvider. По умолчанию он практически пустой, мы вольны добавит в него свой собственный бутстраппинг и привязать собственные сервис-провайдеры.
Как только приложение загружено и все сервис-провайдеры зарегистрированы, запрос передается маршрутизатору (роутеру). Роутер прогоняет запрос через все middleware, определенные для этого роута (если таковые имеются) и отдает на обработку соответствующему контроллеру.
Сервис-контейнер
Пример. Есть у нас класс.
Как видим, в этом классе используется свойство bar, являющееся экземпляром класса Bar. Т.е. чтобы получить экземпляр Foo, нужно вызвать
И так каждый раз, когда нам нужно получить экземпляр этого класса.
А теперь представим, что у класса Bar тоже есть зависимость (класс Baz). Тогда нам нужно создавать экземпляр Foo так
А теперь представим, что у класса Baz тоже есть зависимость.
Стоп. Полагаю, эта кроличья нора слишком глубока для нас.
Теперь, чтобы получить экземпляр Foo, достаточно где угодно в приложении вызвать
Есть еще три способа привязки зависимостей.
Синглтон. Фактически то же самое, но экземпляр Foo будет создан лишь однажды; при последующих попытках создания будет возвращен тот же экземпляр.
Экземпляр. Фактически то же самое, что и привязка синглтона, но вместо создания экземпляра используется уже существующий (созданный ранее) экземпляр.
Примитив. Помимо классов, внедрять можно и примитивы (числа, строки и т.п.).
Связывание интерфейса с реализацией
Контекстное связывание
Тэгирование
Предположим, что мы пишем агрегатор отчетов, принимающий массив различных реализаций интерфейса Report. После регистрации реализаций можно применить им всем один тэг reports.
Теперь привязываем их одним махом с помощью метода tagged.
Расширение привязки
Замечу, что я пока не понял, зачем это может понадобиться. Вернемся к нашему классу Foo c внедренным в него Bar. Предположим, что функциональность класса Bar требует расширения. Но при этом ни сам класс, ни привязку его мы почему-то изменить не можем. Но можем, например, сделать декоратор DecoratedBar с конструктором, принимающим в качестве аргумента экземпляр Bar. И там, где нужно, вызвать метод extend.
Резолвинг
Метод make и хелпер resolve уже были описаны выше. Кроме make есть еще makeWith, позволяющий передать в конструктор параметры, которые нельзя передать через сервис-контейнер.
Ну а основным способом внедрения зависимостей является автоматическое внедрение. Его мы можем использовать практически везде в приложении: в контроллерах, обработчиках событий, очередях заданий, middleware и т.д., и т.п. Здесь просто достаточно прописать зависимость аргументом в конструктор (как мы делали с нашим классом Foo, внедряя в него зависимость Bar).
События контейнера
Сервис-контейнер генерирует событие каждый раз при резолвинге. Обработать это событие можно методом resolving.
PSR-11
Напоследок замечу, что сервис-контейнер Ларавела реализует интерфейс PSR-11. Поэтому для получения экземпляра контейнера (если возникнет такая необходимость) нужно прописать Psr\Container\ContainerInterface. Например
Сервис-провайдеры
Под бутстраппингом мы понимаем регистрацию. Регистрацию зарегистрированных привязок сервис-контенйера; обработчиков событий; посредников; маршрутов.
Как мы помним, в config/app.php есть массив providers. Это и есть все сервис-провайдеры (классы) нашего приложения. Сюда же мы будем добавлять свои собственные сервис-провайдеры. Большинство из них загружается лишь по требованию, т.е. если мы реально не используем некий сервис-провайдер в приложении, то он и не загружается.
Далее попробуем создать свой сервис-провайдер.
Все серсис-провайдеры наследют класс Illuminate\Support\ServiceProvider. Большинство из них содержат методы register и boot.
В консоли новый сервис-провайдер создается командой make:provider:
После выполнения этой команды наш новосозданный провайдер находится в app/Providers/RiakServiceProvider. Как и большинство сервис-провайдеров, он содержит методы register и boot.
Метод register
Метод register должен лишь привязать провайдера к сервис-контейнеру. Нельзя регистрировать здесь обработчики событий, маршруты и прочее, иначе мы можем случайно попытаться использовать сервис, который еще не был загружен.
Из любого метода сервис-провайдера мы имеем доступ к свойству $app, предоставляющему, в свою очередь, доступ к сервис-контейнеру.
Изменим наш сервис-провайдер, чтоб он выглядел так.
Этот сервис-провайдер лишь определяет метод register и использует его для реализации класса Riak\Connection в сервис-контейнере.
Для таких сервис-провайдеров, которые мы лишь регистрируем в сервис-контейнере, желательно сделать загрузку по требованию (отложенную загрузку), чтобы провайдер загружался лишь тогда, когда он нужен (когда мы к нему обращаемся), и лишь если он нужен, а не при каждом запросе. Laravel сохраняет список всех сервисов, предоставляемых отложенными сервис-провайдерами, вместе с названием класса сервис-провайдера. Чтобы отложить загрузку сервис-провайдера, достаточно объявить свойство defer как true и определить метод provides, возвращающий все зарегистрированные в провайдере привязки.
Если же нам требуется зарегистрировать много простых привязок, то лучше объявить свойства bindings и singletons вместо того чтобы прописывать их все вручную.
Метод boot
Если же нам нужно зарегистрировать что-нибудь в нашем сервис-провайдере, то делаем это в методе boot. Этот метод вызывается после регистрации всех сервис-провайдеров, а значит здесь мы уже имеем доступ ко всем сервисам, используемым во фреймворке. Зарегистрируем, например, вью-композер (мы потом еще познакомимся с ним поближе).
Можно указать зависимости для нашего сервис-провайдера: сервис-контейнер позаботится об их внедрении.
Фасады
Фасады предоставляют из себя статические интерфейсы к классам, доступным в сервис-контейнере. Laravel поставляется со множеством фасадов, предоставляющих доступ почти ко всем фичам фреймворка. Фасады служат «статическими прокси» к нижележащим классам в сервис-контейнере, предоставляя краткий, выразительный, запоминающийся синтаксис; при этом имеют большую тестируемость и гибкость, чем традиционные статические методы.
Вск фасады определены в пространстве Illuminate\Support\Facades. Соответственно, мы легко получаем доступ к ним вот так
Зачем нужны фасады? Во-первых, они позволяют не запоминать длинные названия классов, которые нужно внедрить или настраить вручную. Во-вторых, их легко тестировать.
При разработке сторонних пакетов, взаимодействующих с Laravel, лучше использовать контракты (о них ниже), поскольку за пределами Laravel у нас не будет доступа к ларавеловским хелперам тестирования.
Кроме фасадов, в Laravel есть также множество глобальных функций (хелперов), которые выполняют те же задачи, что и соответствующие фасады. Например, этот код
делают одно и то же. На самом деле, хелпер внутри себя вызывает соответствующий метод нижележащего за фасадом класса.
Все фасады (и те, что предоставляет Laravel из коробки, и те, что мы будем делать сами) наследуют класс Illuminate\Support\Facades\Facade. Этот класс используеи «магический» метод __callStatic() для переназначения вызовов из фасада к объекту, извлеченному из сервис-контроллера. В следующем примере вызов делается к системе кэширования Laravel.
Здесь мы используем фасад Cache, который предоставляет доступ к нижележащей реализации интерфейса Illuminate\Contracts\Cache\Factory. Если мы посмотрим в класс Illuminate\Support\Facades\Cache, то не найдем там статического метода get. Фасад, как уже было сказано, наследует базовый класс Facade, и определяет метод getFacadeAccessor(), который возвращает название соответствующей привязки к сервис-контейнеру. В данном случае при вызове любого статического метода фасада Cache, Laravel извлекает из сервис-контейнера привязку cache, и вызывает запрошенный метод ( в данном случае get) из этого объекта.
Фасады реального времени
Используя фасады реального времени, мы можем обратиться к любому классу нашего приложения как к фасаду.
Предположим, у нас есть модель Podcast, содержащая метод publish. Но для публикации подкаста, мы должны внедрить реализацию класса Publisher. Это позволит нам легко тестировать этот метод, используя в качестве реализации Publisher заглушку.
Контракты
Пример использования контракта. Сделаем обработчик события, срабатывающий при формировании нового заказа. Этот обработчик должен закешировать информацию о заказе.
В этом обработчике используется реализация базы данных Redis.