• Время чтения ~6 мин
  • 27.03.2023

Вы когда-нибудь использовали Auth::user() в Laravel? Так что Auth да, это фасад. Вопрос: нужно ли вам на самом деле знать, как они работают, и нужно ли создавать свои собственные фасады?

Отказ от ответственности: эта статья написана Modestas, больше похожа на мнение. Фасады — одна из тех тем, которые имеют разные мнения о них, поэтому я открыт для дискуссий здесь или в Twitter.


Что такое фасады?

Во-первых, определение.

Читая документацию Laravel о фасадах, вы можете немного запутаться в том, что они собой представляют. В документации говорится:

Фасады предоставляют «статический» интерфейс для классов, доступных в контейнере служб приложения.

Наряду с этим, они также говорят:

Laravel Facades служат «статическими прокси» для базовых классов в сервисном контейнере, обеспечивая преимущество краткого, выразительного синтаксиса, сохраняя при этом большую проверяемость и гибкость, чем традиционные статические методы.

Подождите, что это на самом деле значит?

Ну, вам не нужно будет знать, какой класс находится под фасадом. Вы можете просто вызвать Auth façade и получить доступ к методам из базового класса.

Фасады в действии

В Laravel мы можем вызватьAuth::user(), чтобы извлечь пользователя из сеанса.

То, что мы не видим под капотом, это статический прокси для Illuminate\Auth\AuthManager класса. Класс AuthManager имеет методuser(), который возвращает пользователя из сеанса.

Facade облегчает наш опыт как разработчиков, так как нам нужно только помнить Auth фасад, и мы получаем мгновенный статический доступ к методуuser().

Давайте быстро сравним использование фасада с использованием самого класса, чтобы проиллюстрировать разницу.

Как бы это выглядело без фасадов?

Создание нового экземпляра

use Illuminate\Auth\AuthManager;

public function index()
{
    $auth = new AuthManager();
    $user = $auth->user();
}

класса Или, немного короче, с внедрением зависимостей.

Использование внедрения

use Illuminate\Auth\AuthManager;

public function index(AuthManager $auth)
{
    $user = $auth->user();
}

зависимостей С фасадом под капотом, это всего лишь одна линия.

Использование фасада

public function index()
{
    $user = Auth::user();
}

Короче говоря, фасады — это как ярлык для определенного класса.

Теперь, когда мы знаем, что это такое, давайте подумаем, нужно ли нам их использовать и как.


ИСПОЛЬЗОВАНИЕ фасадов - это здорово

Давайте начнем с того, что я считаю хорошим в использовании фасадов.

Используйте фасады из Framework Core

Удобно использовать фасады из ядра Laravel. Это просто работает, и вам не нужно запоминать какие-либо длинные имена классов.

Отлично подходит для тех, кто учится работать. Отлично подходит для тех, кто быстро разрабатывает системы.

Представьте себе, если бы вам пришлось запомнить все это:

Гораздо лучше быстро запомнить их фасады и использовать их:


Использовать фасады из пакетов

Создатели пакета также могут извлечь выгоду из фасадов по той же причине, что и в самом фреймворке - легче запомнить название фасада, чем название класса. Давайте рассмотрим несколько примеров пакетов:

Spatie Activity Logs

https://spatie.be/docs/laravel-activitylog/v4/advanced-usage/batch-logs

В этом пакете мы можем LogBatch найти Facade, который является ярлыком для Spatie\Activitylog\LogBatch класса.

Ларавель Отладчик

https://github.com/barryvdh/laravel-debugbar Этот пакет также содержит вызываемый Debugbar элемент Facade, который является ярлыком Barryvdh\Debugbar\LaravelDebugbar для класса.

Это просто дает конечному пользователю лучшее взаимодействие для использования некоторых функций в любой точке статически.


СОЗДАНИЕ собственных фасадов: не так здорово

О, круто, поэтому вы могли бы подумать, что можете создать свои собственные «ярлыки» фасадов и использовать их в любом месте вашего приложения Laravel?

И вот та часть, где, я думаю, фасады не так хороши. При неправильном использовании они могут вызвать проблемы с оснасткой или общим опытом.

Проблемы с автозаполнением

При использовании Фасадов у вас нет доступа к методам, доступным в классе. Это может вызвать некоторые проблемы с автозаполнением в среде IDE.

Например, представьте, что у вас есть класс SearchService Service, который имеет метод с именем get():

app/Services/SearchService.php

namespace App\Services\SearchService;

class SearchService
{
    public function get(string $query): array
    {
        // ...
    }
}

Чтобы создать «ярлык» для него, вы создаете Facade с именем Search:

app/Facades/Search.php

namespace App\Services\Facades;

use Illuminate\Support\Facades\Facade;

class Search extends Facade
{
    protected static function getFacadeAccessor()
    {
        return \App\Services\SearchService::class;
    }
}

Так что теперь вы можете использовать Search::get(), верно?

Круто, но ваша среда IDE может не показать, что класс существует или что у него нет никаких методов!

И это правда, потому что в вашем классе Facade нет get() метода.

Вы можете заставить автозаполнение IDE работать, добавив блоки doc в класс Facade:

app/Facades/Search.php

namespace App\Services\Facades;

/**
 * @method static get(string $query)
 */
class Search extends Facade {
    // ...
}

Но вам также придется управлять другим файлом, чтобы убедиться, что все методы добавлены в Facade. Кажется сложным.


Фасады могут переопределять имена классов

При создании фасада не нужно следовать тому же имени класса, которое вы собираетесь вызывать. Это означает, что я могу использовать любое имя, которое я хочу для фасада, и оно все равно будет работать. Давайте рассмотрим пример:

Созданиеконфигурации/приложения Facade

class MyRandomClassName extends Facade
{
    protected static function getFacadeAccessor()
    {
        return \App\Services\SearchService::class;
    }
}

.php

// ...
'aliases' => Facade::defaultAliases()->merge([
    // ...
    'MyRandomClassName' => \App\Services\Facades\MyRandomClassName::class,
])->toArray(),

Использование

\MyRandomClassName::get('query');

фасадаИ теперь я могу использовать MyRandomClassName фасад для вызова Search класса. Импорт не требуется, так как вы можете получить к нему доступ во всем мире.

Еще хуже тот факт, что этот класс может даже не существовать! Как? Ну, мы создаем псевдоним. Давайте изменим config немного:

.php

// ...
'aliases' => Facade::defaultAliases()->merge([
    // ...
    'MadeUpAlias' => \App\Services\Facades\MyRandomClassName::class,
])->toArray(),

Использование

\MadeUpAlias::get('query');

фасадаИ это все равно будет работать! Но если вы попытаетесь искать глобальноMadeUpAlias, результатов не будет. Это потому, что это не настоящий класс. Это просто псевдоним для класса, который существует.

Примечание: Я знаю, что этот пример преувеличен. Но это дает вам отличный пример того, как вы можете использовать фасады неправильным образом, чтобы добавить больше путаницы в вашу кодовую базу.


Фасады могут быть использованы в любом месте

Одна вещь, которую фасады имеют для них, - это возможность использовать их в любом месте, где вы хотите. Отличная вещь, не так ли?

Вам это нужно в представлении, контроллере, службе или где-либо еще? Нет проблем - она есть.

Но это быстрый способ сломать шаблон MVC и запустить сложную логику там, где вам не положено.

Представьте, что вы создали фасад для службы, которая генерирует большую таблицу отчетов. Используйте его в контроллере, и это будет хорошо. Но используйте его в View, и у нас есть проблема.


Учебники по фасадам не показывают реальное использование

Когда вы смотрите на учебники о том, как создавать фасады, они, как правило, очень просты. Они являются просто ярлыком для класса, который возвращает что-то простое.

Но в реальных сценариях Facades предназначены для использования в качестве прокси-класса для получения статического доступа к методам, которые не являются статическими, как в Auth Facade.

Когда он перестанет быть крутым, вы сможете быстро выйти из-под контроля и переместить все в фасады, которые быстро приведут вас к ползучести, и один класс может начать выполнять работу 10 других.


Вывод

я бы сказал, что фасады удобны и просты в использовании, начиная от каркаса и пакетов. Но если мы попробуем создать ваши фасады - эта история изменится. Тогда вы должны действительно знать, что вы делаете.

Было бы лучше подумать о том, как вы можете структурировать проект с различными шаблонами проектирования, чтобы избежать глобального класса (фасада), который можно вызвать в любом месте.

Как ты думаешь? Давайте обсудим в комментариях!

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Об авторе CrazyBoy49z
WORK EXPERIENCE
Контакты
Ukraine, Lutsk
+380979856297