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

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

OS: Ubuntu 20.04.2 LTS
PHP: 8.0.0
Laravel: 8.33.1

Мы часто сталкиваемся с различными фасадами "из коробки", такими как DB, Cache, Validator и т.д. (полный список можно найти здесь), но что, если нам в силу тех или иных причин надо создать фасад для своего класса?

Предположим, у нас есть класс ProductService, который мы поместили в директории app/Services. Дабы не усложнять пример, возьмём что-нибудь элементарное:

<?php

namespace App\Services;

class ProductService
{
    public function popularProducts()
    {
        return 'List of the most popular products';
    }
}

  

Чтобы не засорять AppServiceProvider, создадим провайдер для фасадов:

php artisan make:provider FacadeServiceProvider

 

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

<?php

namespace App\Providers;

use App\Services\ProductService;
use Illuminate\Support\ServiceProvider;

class FacadeServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind('product.service', fn () => new ProductService());
    }
}

 

Зарегистрируем созданный провайдер в config/app.php:

'providers' => [
    ...

    /*
     * Application Service Providers...
     */
    ...
    App\Providers\FacadeServiceProvider::class,

],

 

Далее создаём непосредственно сам класс фасада, который разместим в директорию для фасадов app/Facades:

<?php

namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class ProductServiceFacade extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'product.service';
    }
}

 

Готово. Теперь в любой части приложения сделав следующий вызов:

...
use App\Facades\ProductServiceFacade;

...
ProductServiceFacade::popularProducts();

 

...получим строку "List of the most popular products". Следует отметить, что можно было бы также добавить и псевдоним для фасада в config/app.php, в секцию алиасов, но можно обойтись и без этого.

Казалось бы на этом можно ставить точку, но есть и ещё одна фишка - real-time фасады. Допустим, у нас есть CustomerService:

<?php

namespace App\Services;

class CustomerService
{
    public function customersList()
    {
        return 'Customers list';
    }
}

 

Всё, что нужно для генерации фасада в реальном времени - добавить префикс перед неймспейсом класса в директиве use, т.е.:

...
use Facades\App\Services\CustomerService;

...
CustomerService::customersList();

 

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

На этом на сегодня всё. Успехов!