Фасады
11.x
.
Почему это важно?
Введение
Фасады предоставляют “статический” интерфейс (Foo::bar()
) к классам, доступным в IoC-контейнере. Laravel поставляется со множеством фасадов и вы, вероятно, использовали их, даже не подозревая об этом.
Иногда вам может понадобиться создать собственные фасады для вашего приложения и пакетов (packages), поэтому давайте изучим идею, разработку и использование этих классов.
Примечание: перед погружением в фасады настоятельно рекомендуется как можно детальнее изучить IoC-контейнер Laravel.
Описание
В контексте приложения на Laravel, фасад – это класс, который предоставляет доступ к объекту в контейнере. Весь этот механизм реализован в классе Facade
. Фасады как Laravel, так и ваши собственные, наследуют этот базовый класс.
Ваш фасад должен определить единственный метод: getFacadeAccessor
. Его задача – определить, что вы хотите получить из контейнера. Класс Facade
использует магический метод PHP __callStatic()
для перенаправления вызовов методов с вашего фасаде на полученный объект.
Например, когда вы вызываете Cache::get()
, Laravel получает объект CacheManager
из IoC-контейнера и вызывает метод get
этого класса. Другими словами, фасады Laravel предоставляют удобный синтаксис для использования IoC-контейнера в качестве сервис-локатора (service locator).
Практическое использование
В примере ниже делается обращение к механизму кэширования Laravel. На первый взгляд может показаться, что метод get
принадлежит классу Cache
.
$value = Cache::get('key');
Однако, если вы посмотрите в исходный код класса Illuminate\Support\Facades\Cache
, то увидите, что он не содержит метода get
:
class Cache extends Facade {
/**
* Получить зарегистрированное имя компонента.
*
* @return string
*/
protected static function getFacadeAccessor() { return 'cache'; }
}
Класс Cache наследует класс Facade
и определяет метод getFacadeAccessor()
. Как вы помните, его задача – вернуть строковое имя (ключ) привязки объекта в контейнере IoC.
Когда вы обращаетесь к любому статическому методу фасада Cache
, Laravel получает объект cache
из IoC и вызывает на нём требуемый метод (в этом случае – get
).
Таким образом, вызов Cache::get
может быть записан так:
$value = $app->make('cache')->get('key');
Создание фасадов
Создать фасад в вашем приложении или пакете (package) довольно просто. Вам нужны только три вещи:
- Биндинг (привязка) в IoC.
- Класс-фасад.
- Настройка для псевдонима фасада.
Посмотрим на следующий пример. Здесь определён класс PaymentGateway\Payment
.
namespace PaymentGateway;
class Payment {
public function process()
{
//
}
}
Этот класс может находиться в app/models
или в любой другой директории, где у composer настроена автозагрузка классов.
Нам нужно, чтобы этот класс извлекался из контейнера IoC, так что давайте добавим для него привязку (binding):
App::bind('payment', function()
{
return new \PaymentGateway\Payment;
});
Самое лучшее место для регистрации этой связки – новый сервис-провайдер который мы назовём PaymentServiceProvider
и в котором мы создадим метод register
, содержащий код выше. После этого вы можете настроить Laravel для загрузки этого поставщика в файле app/config/app.php
.
Дальше мы можем написать класс нашего фасада:
use Illuminate\Support\Facades\Facade;
class Payment extends Facade {
protected static function getFacadeAccessor() { return 'payment'; }
}
Наконец, по желанию можно добавить алиас (alias, псевдоним) для этого фасада в массив aliases
файла настроек app/config/app.php
– тогда мы сможем вызывать метод process
на классе Payment
.
Payment::process();
Об автозагрузке алиасов
В некоторых случаях классы в массиве aliases
не доступны из-за того, что PHP не загружает неизвестные классы в подсказках типов. Если \ServiceWrapper\ApiTimeoutException
имеет псевдоним ApiTimeoutException
, то блок catch(ApiTimeoutException $e)
, помещённый в любое пространство имён, кроме \ServiceWrapper
, никогда не “поймает” это исключение, даже если оно было возбуждено внутри него. Аналогичная проблема возникает в моделях, которые содержат подсказки типов на неизвестные (неопределённые) классы. Единственное решение – не использовать алиасы и вместо них в начале каждого файла писать use
для ваших классов.
Фасады для тестирования
Юнит-тесты играют важную роль в том, почему фасады делают именно то, то они делают. На самом деле возможность тестирования – основная причина, по которой фасады вообще существуют. Эта тема подробнее раскрыта в соответствующем разделе документации – фасады-заглушки.
Facade Class Reference
Ниже представлена таблица соответствий фасадов Laravel и классов, лежащих в их основе.