Russian (Pусский) translation by Sergey Zhuk (you can also view the original English article)
Лучше всего шаблоны проектирования были описаны Мартином Фаулером:
Шаблоны предоставляют механизм реализации дизайна в формате совета. Дизайн программного обеспечения это огромная тема, и когда сталкиваешься с проблемой дизайна, следует максимально сфокусироваться на решении этой проблемы.
Код, который использует шаблоны проектирования легко понять, поддерживать и расширять. Цель этого руководства - ознакомить вас с фасадами в Laravel.
Что представляет собой шаблон Фасад?
По определению Банды Четырех шаблон проектирования фасад - это структурный шаблон, который предоставляет упрощенный интерфейс с более сложной подсистеме. Шаблон строится на создании простого интерфейса фасада, за которым стоит набор необходимой логики и методов. При этом фасад сам управляет своими зависимостями.
Фасад очень похож на шаблоны адаптер и декоратор. Адаптер работает как мост между двумя несовместимыми интерфейсами, в то время как декоратор является более сложными и используется для динамического изменения поведения объектов.
Чем Являются Фасады Laravel?
Приятный синтаксис, который используется в Laravel, делает написание кода чистым и легким в понимании. Фасады Laravel фактически являются синтаксическим сахаром для сервисов.
Давайте на примере рассмотрим фасад Laravel и то, как он работает. Фасад Cache
в Laravel выглядит следующим образом:
Cache::get('key');
Хотя может показаться, что здесь используются статические методы, в действительности же Laravel предоставляет интерфейс для классов, которые доступны через контейнер зависимостей приложения. Как вы уже возможно знаете, код, представленный выше, эквивалентен следующему:
$app = app(); $app->make('cache')->get('key');
Фасады Laravel расположены в директории vendor/Laravel/framework/src/Illuminate/Support/Facades
, сам фасад Cache находится в файле Cache.php
:
namespace Illuminate\Support\Facades; class Cache extends Facade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'cache'; } }
Когда мы используем выражение cache::get('key')
, то в действительности будет вызван класс, описанный выше. Убедитесь, что вы прописали псевдоним для класса в конфигурационном файле config/app.php
:
'aliases' => [ //... 'Cache'=>Illuminate\Support\Facades\Cache::class,
Псевдонимы устанавливаются автоматически автозагрузчиком Laravel. Устанавливая классу псевдоним Cache, мы создаем связь с фасадом. Это несомненно поможет людям, которые используют фасады, чувствовать себя комфортнее с вашим кодом.
Следующие три метода имеют огромное значение при создании фасада:
- Магический метод __callStatic(), который определен как метод
getFacadeAccessor
в дочернем классе. - Facade Root представляет собой класс, лежащий в основе фасада, и методы которого будут в действительности вызываться.
- Метод
resolveFacadeInstance
отвечает за получение нужного объекта сервиса.
Реализация методов фасада:
//... public static function __callStatic($method, $args) { $instance = static::getFacadeRoot(); switch (count($args)) { case 0: return $instance->$method(); case 1: return $instance->$method($args[0]); case 2: return $instance->$method($args[0], $args[1]); case 3: return $instance->$method($args[0], $args[1], $args[2]); case 4: return $instance->$method($args[0], $args[1], $args[2], $args[3]); default: return call_user_func_array(array($instance, $method), $args); } }
__callStatic
обычно вызывает IoC контейнер для связи с классом. Он так же вызывает его (нестатичный) метод, используя выражение switch и функцию call_user_func_array()
, передавая массив параметров в объект, возвращаемый методом getFacadeRoot()
. Метод getFacadeRoot()
работает следующим образом:
public static function getFacadeRoot() { return static::resolveFacadeInstance( static::getFacadeAccessor() ); }
И resolveFacadeInstance()
:
protected static function resolveFacadeInstance($name) { if (is_object($name)) returns $name; if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } return static::$resolvedInstance[$name] = static::$app[$name]; }
Как показано в последней строчке статьи, в методе resolveFacadeInstance
Laravel возвращает объект сервиса. Так как сервис является просто объектом оригинального класса, можно слетать вывод, что фасад Laravel не попадает под определение фасадов Банды Четырех. Он просто является сервисом. В отличие от фасадов Laravel, настоящие фасады делают написание юнит тестов достаточно трудоемким занятием, а иногда даже невозможным, из-за создания жестко прописанных зависимостей.
Для тех же кто считает, что инъекция зависимостей через конструктор, является лучшим выбором, чем использование фасадов Laravel, я бы хотел сообщить вам, что можно использовать некоторые дополнительные настройки.
Как Создавать Фасады Laravel
Мне нужно создать фасад для проверки файлов, который будет отвечать за проверку того, является ли входной файл формата pdf или нет. Для того чтобы сделать это, сначала необходимо создать класс IsPdf
в App/MyFacade/IsPdf.php
:
namespace App\MyFacade; class IsPdf { private $pdf = "\x25\x50\x44\x46\x2D"; public function check($file) { return (file_get_contents($file, false, null, 0, strlen($this->pdf)) === $this->pdf) ? true : false; } }
Затем нужно связать класс с поставщиком сервиса. Нужно будет создать нового поставщика сервиса в файле App\Providers\IsPdfServiceProvider
:
namespace App\Providers; use Illuminate\Support\Facades\App; use Illuminate\Support\ServiceProvider; class IsPdfServiceProvider extends ServiceProvider { /** * Bootstrap the application services. * * @return void */ public function boot() { // } /** * Register the application services. * * @return void */ public function register() { App::bind('IsPdf', function() { return new \App\MyFacade\IsPdf; }); } }
Затем создать класс фасада как расширение ранее упомянутого класса Illuminate\Support\Facades\Facade
. Создаем класс в файле App\Facades\IsPdfFacade.php
.
namespace App\Facades; use Illuminate\Support\Facades\Facade; class IsPdf extends Facade{ protected static function getFacadeAccessor() { return 'IsPdf'; } }
Последним шагом будет регистрация фасада в config/app.php
:
/* * Application Service Providers... */ App\Providers\IsPdfServiceProvider::class,
И псевдоним:
'IsPdf' => App\Facades\IsPdf::class
Поздравляю! Вы успешно создали фасад Laravel. Не стесняйтесь проверить ваш фасад с помощью кода, например:
Route::get('/', function(){ IsPdf::check('/files/file.pdf'); });
Заключение
Теперь мы знаем, что фасады Laravel позволяют очень легко вызывать методы сервисов и реализовать доступ к зависимостям. Конечно же фасады Laravel имеют свои плюсы и минусы. Выбор правильного решения зависит от программиста.
Для получения дополнительных ресурсов о Laravel, не забудьте проверить предложения.
Кто знает, может эта статья наоборот сподвигнет вас на разработку кода, независимого от фреймворков, и вообще заставит позабыть о фасадах! Удачи!
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weekly