Введение
Фасады предоставляют «статический» интерфейс к классам, доступным в контейнере IoC. Laravel поставляется со множеством фасадов и вы, вероятно, использовали их, даже не подозревая об этом. «Фасады» Laravel служат «статическими прокси» для классов в IoC-контейнере, обеспечивая преимущества краткого выразительного синтаксиса, и поддерживая большую тестируемость и гибкость, чем традиционные статические методы.
Иногда вам может понадобиться создать собственные фасады для вашего приложения и пакетов, поэтому давайте изучим идею, разработку и использование этих классов.
Внимание: перед погружением в фасады настоятельно рекомендуется как можно детальнее изучить контейнер IoC.
Описание
В контексте приложения на Laravel, фасад — это класс, который предоставляет доступ к объекту в контейнере. Весь этот механизм реализован в классе PHPFacade
. Фасады как Laravel, так и ваши собственные, наследуют этот базовый класс.
Ваш фасад должен определить единственный метод: PHPgetFacadeAccessor()
. Его задача — определить, что вы хотите получить из контейнера. Класс PHPFacade
использует магический метод PHP __callStatic() для перенаправления вызовов методов с вашего фасада на полученный объект.
Таким образом, когда вы делаете вызов фасада PHPCache::get
, Laravel извлекает класс управления кэшем из IoC-контейнера и вызывает метод PHPget
на класс. С технической точки зрения, фасады Laravel — удобный синтаксис для использования IoC-контейнера Laravel в качестве локатора служб.
Практическое использование
В примере ниже делается обращение к механизму кэширования Laravel. На первый взгляд может показаться, что метод PHPget()
принадлежит классу PHPCache
:
$value = Cache::get('key');
Однако, если вы посмотрите в исходный код класса PHPIlluminate\Support\Facades\Cache
, то увидите, что он не содержит метода PHPget()
:
class Cache extends Facade {
/**
* Получить зарегистрированное имя компонента.
*
* @return string
*/
protected static function getFacadeAccessor() { return 'cache'; }
}
Класс PHPCache
наследует класс PHPFacade
и определяет метод PHPgetFacadeAccessor()
. Как вы помните, его задача — вернуть имя привязки (типа) в контейнере IoC.
Когда вы обращаетесь к любому статическому методу фасада PHPCache
, Laravel получает объект cache из IoC и вызывает на нём требуемый метод (в этом случае — PHPget()
).
Таким образом, вызов PHPCache::get()
может быть записан так:
$value = $app->make('cache')->get('key');
Создание фасадов
Создать фасад в вашем приложении или пакете довольно просто. Вам нужны только три вещи:
- Связка в IoC.
- Класс-фасад.
- Настройка для псевдонима фасада.
Посмотрим на следующий пример. Здесь определён класс PHPPaymentGateway\Payment
.
namespace PaymentGateway;
class Payment {
public function process()
{
//
}
}
Этот класс может находиться в вашем каталоге app/models или в любом другом каталоге, который добавлен в автозагрузку Composer.
Нам нужно, чтобы этот класс извлекался из контейнера IoC, так что давайте добавим для него привязку (binding):
App::bind('payment', function () {
return new \PaymentGateway\Payment;
});
Самое лучшее место для регистрации этой связки — новый поставщик услуг, который мы назовём PHPPaymentServiceProvider
и в котором мы создадим метод PHPregister()
, содержащий код выше. После этого вы можете настроить 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 — тогда мы сможем вызывать метод PHPprocess()
на классе PHPPayment
:
Payment::process();
Об автозагрузке псевдонимов
В некоторых случаях классы в массиве aliases не доступны из-за того, что PHP не загружает неизвестные классы в подсказках типов. Если PHP\ServiceWrapper\ApiTimeoutException
имеет псевдоним PHPApiTimeoutException
, то блок PHPtry ... catch (ApiTimeoutException $e)
, помещённый в любое пространство имён, кроме PHPServiceWrapper
, никогда не «поймает» это исключение, даже если оно было возбуждено внутри него. Аналогичная проблема возникает в моделях, которые содержат подсказки типов на неизвестные (неопределённые) классы. Единственное решение — не использовать псевдонимы и вместо них в начале каждого файла писать PHPuse ... as
для классов, которые вы хотите использовать в подсказках типов.
Фасады-заглушки
Юнит-тесты играют важную роль в том, почему фасады делают именно то, что они делают. На самом деле возможность тестирования — основная причина, по которой фасады вообще существуют. Эта тема подробнее раскрыта в соответствующем разделе документации.
Соответствие фасадов и классов
В таблице ниже перечислены все фасады и соответствующие им классы. Это полезный инструмент для быстрого начала работы с документацией по API данного корня фасадов. Также указаны ключи привязки IoC, где это нужно.
Комментарии (2)
App::bind('payment', function () {
return new \PaymentGateway\Payment;
});
Вам лучше задавать вопросы на форуме.