Версія фреймворка: 8.x

Фасади

Вступ

Фасади забезпечують "статичний" інтерфейс для класів, доступних у програміслужбовий контейнер. Судна Laravel мають безліч фасадів, що забезпечують доступ майже до всіх функцій Laravel. Фасади Laravel служать "статичними проксі" основних класів у службовому контейнері, забезпечуючи перевагу стислого, виразного синтаксису, зберігаючи при цьому більшу перевірочність і гнучкість, ніж традиційні статичні методи.

Усі фасади Laravel визначені вIlluminate\Support\Facadesпростір імен. Отже, ми можемо легко отримати доступ до фасаду так:

use Illuminate\Support\Facades\Cache;

Route::get('/cache', function () {
    return Cache::get('key');
});

У документації Laravel багато прикладів використовуватимуть фасади, щоб продемонструвати різні особливості фреймворку.

Коли використовувати фасади

Фасади мають багато переваг. Вони забезпечують стислий запам’ятовуваний синтаксис, що дозволяє використовувати функції Laravel, не пам’ятаючи довгих назв класів, які потрібно вводити або конфігурувати вручну. Крім того, завдяки унікальному використанню динамічних методів PHP, їх легко перевірити.

Однак слід дотримуватися певної обережності при використанні фасадів. Основною небезпекою фасадів є повзучість класу. Оскільки фасади настільки прості у використанні і не потребують впорскування, можна легко дозволити вашим класам продовжувати рости та використовувати багато фасадів в одному класі. Використовуючи ін’єкцію залежностей, цей потенціал пом’якшується за допомогою візуального зворотного зв’язку, який великий конструктор дає вам, що ваш клас стає занадто великим. Тож, використовуючи фасади, звертайте особливу увагу на розмір вашого класу, щоб сфера його відповідальності залишалася вузькою.

При створенні стороннього пакету, який взаємодіє з Laravel, краще вводитиКонтракти Laravelзамість використання фасадів. Оскільки пакети створюються за межами самої Laravel, ви не матимете доступу до помічників тестування фасадів Laravel.

Фасади проти Ін’єкція залежності

<<<<<<< HEAD

Однією з основних переваг введення залежностей є можливість обміну реалізаціями введеного класу. Це корисно під час тестування, оскільки ви можете ввести макет або заглушку та стверджувати, що на заглушці були викликані різні методи.

=======

Однією з основних переваг введення залежностей є можливість обміну реалізаціями введеного класу. Це корисно під час тестування, оскільки ви можете ввести макет або заглушку та стверджувати, що на заглушці були викликані різні методи.

2684557fed6a6d955a2a144612b53ef3b2ac155e Як правило, неможливо знущатись чи заглушати дійсно статичний метод класу. Однак, оскільки фасади використовують динамічні методи для виклику методів проксі до об'єктів, вирішених із контейнера служби, ми фактично можемо тестувати фасади так само, як і тестований ін'єкційний клас. Наприклад, враховуючи такий маршрут:
use Illuminate\Support\Facades\Cache;

Route::get('/cache', function () {
    return Cache::get('key');
});

Ми можемо написати наступний тест, щоб переконатися, щоCache::getметод був викликаний з аргументом, який ми очікували:

use Illuminate\Support\Facades\Cache;

/**
 * A basic functional test example.
 *
 * @return void
 */
public function testBasicExample()
{
    Cache::shouldReceive('get')
         ->with('key')
         ->andReturn('value');

    $response = $this->get('/cache');

    $response->assertSee('value');
}

Фасади проти Допоміжні функції

На додаток до фасадів, Laravel включає в себе безліч "допоміжних" функцій, які можуть виконувати загальні завдання, такі як генерація поглядів, активація подій, відправлення завдань або надсилання відповідей HTTP. Багато з цих допоміжних функцій виконують ту саму функцію, що і відповідний фасад. Наприклад, цей фасадний виклик та допоміжний виклик еквівалентні:

return View::make('profile');

return view('profile');

Практичної різниці між фасадами та допоміжними функціями немає абсолютно. Використовуючи допоміжні функції, ви все одно можете протестувати їх точно так само, як і відповідний фасад. Наприклад, враховуючи такий маршрут:

Route::get('/cache', function () {
    return cache('key');
});

Під капотомcacheпомічник збирається зателефонуватиgetметод для класу, що лежить в основіCacheфасад. Отже, незважаючи на те, що ми використовуємо допоміжну функцію, ми можемо написати наступний тест, щоб переконатися, що метод був викликаний з аргументом, який ми очікували:

use Illuminate\Support\Facades\Cache;

/**
 * A basic functional test example.
 *
 * @return void
 */
public function testBasicExample()
{
    Cache::shouldReceive('get')
         ->with('key')
         ->andReturn('value');

    $response = $this->get('/cache');

    $response->assertSee('value');
}

Як працюють фасади

<<<<<<< HEAD

У програмі Laravel Facade- це клас, який забезпечує доступ до об’єкта з контейнера. Машина, яка робить цю роботу, знаходиться вFacadeклас. Фасади Laravel та будь-які спеціальні фасади, які ви створюєте, розширять основуIlluminate\Support\Facades\Facadeклас.

=======

У програмі Laravel Facade- це клас, який забезпечує доступ до об’єкта з контейнера. Машина, яка робить цю роботу, знаходиться вFacadeклас. Фасади Laravel та будь-які спеціальні фасади, які ви створюєте, розширять основуIlluminate\Support\Facades\Facadeклас.

2684557fed6a6d955a2a144612b53ef3b2ac155e Facadeбазовий клас використовує__callStatic()magic-метод для відкладання викликів з вашого фасаду до об'єкта, вирішеного з контейнера. У наведеному нижче прикладі здійснюється виклик кеш-системи Laravel. Поглянувши на цей код, можна припустити, що статичний методgetвикликається наCacheклас:
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;

class UserController extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        $user = Cache::get('user:'.$id);

        return view('profile', ['user' => $user]);
    }
}

Зверніть увагу, що вгорі файлу ми "імпортуємо" файлCacheфасад. Цей Facadeслужить проксі для доступу до базової реалізаціїIlluminate\Contracts\Cache\Factoryінтерфейс. Будь-які дзвінки, які ми робимо за допомогою фасаду, будуть передані базовому екземпляру кеш-служби Laravel.

Якщо ми подивимось на цеIlluminate\Support\Facades\Cacheклас, ви побачите, що не існує статичного методуget:

class Cache extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor() { return 'cache'; }
}

Натомість,CacheFacadeпродовжує основуFacadeклас і визначає методgetFacadeAccessor(). Завдання цього методу - повернути ім’я Binding контейнера служби. Коли користувач посилається на будь-який статичний метод наCacheфасаду, Laravel вирішуєcacheприв'язка зслужбовий контейнері запускає запитаний метод (у цьому випадкуget) проти цього об’єкта.

Фасади в режимі реального часу

Використовуючи фасади в режимі реального часу, ви можете поводитися з будь-яким класом у вашій програмі так, ніби це фасад. Щоб проілюструвати, як це можна використовувати, давайте розглянемо альтернативу. Наприклад, припустимо нашPodcastмодель маєpublishметод. Однак, щоб опублікувати подкаст, нам потрібно ввести aPublisherпримірник:

<?php

namespace App\Models;

use App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * Publish the podcast.
     *
     * @param  Publisher  $publisher
     * @return void
     */
    public function publish(Publisher $publisher)
    {
        $this->update(['publishing' => now()]);

        $publisher->publish($this);
    }
}

Введення реалізації видавця в метод дозволяє нам легко протестувати метод ізольовано, оскільки ми можемо знущатись над введеним видавцем. Однак це вимагає від нас, щоб ми завжди передавали екземпляр видавця кожного разу, коли ми телефонуємо доpublishметод. Використовуючи фасади в режимі реального часу, ми можемо підтримувати однакову перевірочність, не вимагаючи явного проходження аPublisherекземпляр. Щоб сформувати Facadeу реальному часі, додайте до простору імен імпортованого класу префіксFacades:

<?php

namespace App\Models;

use Facades\App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * Publish the podcast.
     *
     * @return void
     */
    public function publish()
    {
        $this->update(['publishing' => now()]);

        Publisher::publish($this);
    }
}

Коли використовується Facadeу реальному часі, реалізація видавця буде вирішена з контейнера служби за допомогою частини інтерфейсу або імені класу, що з'являється післяFacadesпрефікс. Під час тестування ми можемо використовувати вбудовані помічники фасадного тестування Laravel для глузування над цим викликом методу:

<?php

namespace Tests\Feature;

use App\Models\Podcast;
use Facades\App\Contracts\Publisher;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class PodcastTest extends TestCase
{
    use RefreshDatabase;

    /**
     * A test example.
     *
     * @return void
     */
    public function test_podcast_can_be_published()
    {
        $podcast = Podcast::factory()->create();

        Publisher::shouldReceive('publish')->once()->with($podcast);

        $podcast->publish();
    }
}

Class Reference фасадів

Facade Class Service Container Binding
App Illuminate\Foundation\Application app
Artisan Illuminate\Contracts\Console\Kernel artisan
Auth Illuminate\Auth\AuthManager auth
Auth (Instance) Illuminate\Contracts\Auth\Guard auth.driver
Blade Illuminate\View\Compilers\BladeCompiler blade.compiler
Broadcast Illuminate\Contracts\Broadcasting\Factory  
Broadcast (Instance) Illuminate\Contracts\Broadcasting\Broadcaster  
Bus Illuminate\Contracts\Bus\Dispatcher  
Cache Illuminate\Cache\CacheManager cache
Cache (Instance) Illuminate\Cache\Repository cache.store
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 db.connection
Event Illuminate\Events\Dispatcher events
File Illuminate\Filesystem\Filesystem files
Gate Illuminate\Contracts\Auth\Access\Gate  
Hash Illuminate\Contracts\Hashing\Hasher hash
Http Illuminate\Http\Client\Factory  
Lang Illuminate\Translation\Translator translator
Log Illuminate\Log\LogManager log
Mail Illuminate\Mail\Mailer mailer
Notification Illuminate\Notifications\ChannelManager  
Password Illuminate\Auth\Passwords\PasswordBrokerManager auth.password
Password (Instance) Illuminate\Auth\Passwords\PasswordBroker auth.password.broker
Queue Illuminate\Queue\QueueManager queue
Queue (Instance) Illuminate\Contracts\Queue\Queue queue.connection
Queue (Base Class) Illuminate\Queue\Queue  
Redirect Illuminate\Routing\Redirector redirect
Redis Illuminate\Redis\RedisManager redis
Redis (Instance) Illuminate\Redis\Connections\Connection redis.connection
Request Illuminate\Http\Request request
Response Illuminate\Contracts\Routing\ResponseFactory  
Response (Instance) Illuminate\Http\Response  
Route Illuminate\Routing\Router router
Schema Illuminate\Database\Schema\Builder  
Session Illuminate\Session\SessionManager session
Session (Instance) Illuminate\Session\Store session.store
Storage Illuminate\Filesystem\FilesystemManager filesystem
Storage (Instance) Illuminate\Contracts\Filesystem\Filesystem filesystem.disk
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