Версия фреймворка:
5.4 4.2
Прогресс перевода
Перевод немного отстаёт от оригинала. Коммитов не переведено: 1

Фасады

Введение

Фасады предоставляют "статический" интерфейс (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) довольно просто. Вам нужны только три вещи:

  1. Биндинг (привязка) в IoC.
  2. Класс-фасад.
  3. Настройка для псевдонима фасада.

Посмотрим на следующий пример. Здесь определён класс 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 и классов, лежащих в их основе.

Фасад Класс Имя в IoC
App Illuminate\Foundation\Application app
Artisan Illuminate\Console\Application artisan
Auth Illuminate\Auth\AuthManager auth
Auth (Instance) Illuminate\Auth\Guard
Blade Illuminate\View\Compilers\BladeCompiler blade.compiler
Cache Illuminate\Cache\Repository cache
Config Illuminate\Config\Repository config
Cookie Illuminate\Cookie\CookieJar cookie
Crypt Illuminate\Encryption\Encrypter encrypter
DB Illuminate\Database\DatabaseManager db
DB (Instance) Illuminate\Database\Connection
Event Illuminate\Events\Dispatcher events
File Illuminate\Filesystem\Filesystem files
Form Illuminate\Html\FormBuilder form
Hash Illuminate\Hashing\HasherInterface hash
HTML Illuminate\Html\HtmlBuilder html
Input Illuminate\Http\Request request
Lang Illuminate\Translation\Translator translator
Log Illuminate\Log\Writer log
Mail Illuminate\Mail\Mailer mailer
Paginator Illuminate\Pagination\Factory paginator
Paginator (Instance) Illuminate\Pagination\Paginator
Password Illuminate\Auth\Reminders\PasswordBroker auth.reminder
Queue Illuminate\Queue\QueueManager queue
Queue (Instance) Illuminate\Queue\QueueInterface
Queue (Base Class) Illuminate\Queue\Queue
Redirect Illuminate\Routing\Redirector redirect
Redis Illuminate\Redis\Database redis
Request Illuminate\Http\Request request
Response Illuminate\Support\Facades\Response
Route Illuminate\Routing\Router router
Schema Illuminate\Database\Schema\Blueprint
Session Illuminate\Session\SessionManager session
Session (Instance) Illuminate\Session\Store
SSH Illuminate\Remote\RemoteManager remote
SSH (Instance) Illuminate\Remote\Connection
URL Illuminate\Routing\UrlGenerator url
Validator Illuminate\Validation\Factory validator
Validator (Instance) Illuminate\Validation\Validator
View Illuminate\View\Factory view
View (Instance) Illuminate\View\View