18/10/2018, 00:21

Facades và mối quan hệ giữa Facades với Service Container trong Laravel

Tìm hiểu về Facade trong Laravel Static method Các thuộc tính, phương thức trong lớp khai báo với từ khóa static là một đặc tính hữu dụng trong PHP. Về cơ bản, phương thức / thuộc tính tĩnh (static) thì nó có thể truy cập trực tiếp mà không phải tạo đối tượng của lớp. Ví dụ về static ...

Tìm hiểu về Facade trong Laravel

  1. Static method

Các thuộc tính, phương thức trong lớp khai báo với từ khóa static là một đặc tính hữu dụng trong PHP. Về cơ bản, phương thức / thuộc tính tĩnh (static) thì nó có thể truy cập trực tiếp mà không phải tạo đối tượng của lớp. Ví dụ về static method và non-static method.

class Math
{
    private $firstNumber;

    public function __construct(int $firstNumber)
    {
        $this->firstNumber = $firstNumber;
    }

    public function add(int $secondNumber)
    {
        return $sum = $this->firstNumber + $secondNumber;
    }

    public static function mul(int $firstNumber, int $secondNumber)
    {
        return $firstNumber * $secondNumber;
    }
}

$math = new Math(10);
$addResult = $math->add(5);
//15
$mulResult = Math::mul(10,5);
//50
  1. Magic methods

Trong quá trình code, chúng ta sử dụng rất nhiều lần các phương thức như __construct(), __call(),… Các phương thức này chính là magic method. Vậy magic method là các phương thức đặc biệt để tùy biến các các sự kiện trong php. Có thể hiểu đơn giản là nó cung cấp thêm cách để giải quyết một vấn đề nào đó trong phạm vi class. Magic method được dùng để xử lý các đối tượng trong lập trình hướng đối tượng, dưới đây là ví dụ về 2 magic methods thường dùng

class Math
{
    private $firstNumber;
    
    public function __construct(int $firstNumber)
    {
        $this->firstNumber = $firstNumber;
    }

    public function __destruct()
    {
        echo 'this Object has been destroyed';
    }
}

Trước khi tìm hiểu rõ hơn về Facade, ta hãy tìm hiểu trước về magic method là __callStatic(). Khi gọi đến một static method chưa được khai báo bị lỗi “Call to undefined method”, nhưng nếu ta đã có phương thức __callStatic() trong class, PHP sẽ tự động gọi tới đó (__callStatic() chỉ có áp dụng với các static method), tương tự __call() chỉ áp dụng được với các non-static method.

class Math
{
    private $firstNumber;

    public function __construct(int $firstNumber)
    {
        $this->firstNumber = $firstNumber;
    }

    public function __destruct()
    {
        echo 'this Object has been destroyed';
    }

    public static function __callStatic($name, $arguments)
    {
        echo "Undefined static method called";
    }
}

Math::undefinedMethod();
//Undefined static method called
  1. Facades

Facades là một trong những tính năng rất hữu dụng trong laravel với Facades, chúng ta có thể truy cập đến hầu hết các tính năng của laravel Ví dụ về sử dụng facades: Auth::id(), Auth::user(), Route::get(),… Để hiểu rõ hơn, hãy vào xem file config/app.php

'aliases' => [

        'App' => IlluminateSupportFacadesApp::class,
        'Artisan' => IlluminateSupportFacadesArtisan::class,
        'Auth' => IlluminateSupportFacadesAuth::class,
        'Blade' => IlluminateSupportFacadesBlade::class,
        'Broadcast' => IlluminateSupportFacadesBroadcast::class,
        'Bus' => IlluminateSupportFacadesBus::class,
        'Cache' => IlluminateSupportFacadesCache::class,
        'Config' => IlluminateSupportFacadesConfig::class,
        'Cookie' => IlluminateSupportFacadesCookie::class,
        'Crypt' => IlluminateSupportFacadesCrypt::class,
        'DB' => IlluminateSupportFacadesDB::class,
        'Eloquent' => IlluminateDatabaseEloquentModel::class,
        'Event' => IlluminateSupportFacadesEvent::class,
        'File' => IlluminateSupportFacadesFile::class,
        'Gate' => IlluminateSupportFacadesGate::class,
        'Hash' => IlluminateSupportFacadesHash::class,
        'Lang' => IlluminateSupportFacadesLang::class,
        'Log' => IlluminateSupportFacadesLog::class,
        'Mail' => IlluminateSupportFacadesMail::class,
        'Notification' => IlluminateSupportFacadesNotification::class,
        'Password' => IlluminateSupportFacadesPassword::class,
        'Queue' => IlluminateSupportFacadesQueue::class,
        'Redirect' => IlluminateSupportFacadesRedirect::class,
        'Redis' => IlluminateSupportFacadesRedis::class,
        'Request' => IlluminateSupportFacadesRequest::class,
        'Response' => IlluminateSupportFacadesResponse::class,
        'Route' => IlluminateSupportFacadesRoute::class,
        'Schema' => IlluminateSupportFacadesSchema::class,
        'Session' => IlluminateSupportFacadesSession::class,
        'Storage' => IlluminateSupportFacadesStorage::class,
        'URL' => IlluminateSupportFacadesURL::class,
        'Validator' => IlluminateSupportFacadesValidator::class,
        'View' => IlluminateSupportFacadesView::class,

    ],

Tại đây, rất nhiều cái tên quen thuộc như App, DB, Auth,… Laravel đã khai báo sẵn một loạt các class alias. Mục đích của việc này để chúng ta có thể sử dụng khi code với cái tên ngắn gọn thay vì phải viết đầy đủ cả namespace. Ví dụ khai báo ‘Auth’ => IlluminateSupportFacadesAuth::class, khi chúng ta sử dụng class Auth,  thực tế ta đã gọi đến class IlluminateSupportFacadesAuth. Để ý chút ta sẽ thấy tên các class được đăng ký alias đều có namespace chung là IlluminateSupportFacades.Điều này có nghĩa là những class được đăng ký ở đây đều là Facades, và tất cả những class này đều extends một class có tên là Facade. Từ ví dụ các facades Auth::id(), Auth::user(), Auth::logout(),… Các gọi này chính là gọi các static method, hãy xem trong class Auth ta có những method nào.

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

    /**
     * Register the typical authentication routes for an application.
     *
     * @return void
     */
    public static function routes()
    {
        static::$app->make('router')->auth();
    }
}

Có thể thấy trong class Auth không có static method nào là id(), user(),… cả, nhưng ta thấy class này overrides lại một hàm là getFacadeAccessor(), hãy vào thử abstact class Facade xem nó có gì bên trong.

    protected static function getFacadeAccessor()
    {
        return 'auth';
    }

Việc định nghĩa hàm getFacadeAccessor() sẽ bắt buộc các class extends từ class Facade sẽ phải overrides lại hàm này, nếu không sẽ throw ra Exception.

    public static function __callStatic($method, $args)
    {
        $instance = static::getFacadeRoot();

        if (! $instance) {
            throw new RuntimeException('A facade root has not been set.');
        }

        return $instance->$method(...$args);
    }

Kéo xuống phần dưới cùng của class, ta thấy có magic method là __callStatic(). Như đã trình bày ở trên, khi gọi các hàm static của Auth thực tế sẽ được xử lý trong magic method __callStatic, ở đây sẽ tạo ra một Facade instance, instance này được resolve ra từ Application Instance $$pp với hàm getFacadeRoot(); (Chính là Service Container). Như vậy việc sử dụng facade Auth chính là sử dụng service auth của Service Container Ví dụ:

Auth::user();
// Tương đương với 
$auth = app(‘auth’);
$auth->user();

Bài viết này hy vọng sẽ giúp bạn hiểu rõ hơn về Facades, cũng như sự ứng dụng của Service Container trong Laravel. Dưới đây là tên các Facade với Class và Service Container tương ứng.

Facade Class Service Container Binding
App IlluminateFoundationApplication app
Artisan IlluminateContractsConsoleKernel artisan
Auth IlluminateAuthAuthManager auth
Auth (Instance) IlluminateContractsAuthGuard auth.driver
Blade IlluminateViewCompilersBladeCompiler blade.compiler
Broadcast IlluminateContractsBroadcastingFactory
Broadcast (Instance) IlluminateContractsBroadcastingBroadcaster
Bus IlluminateContractsBusDispatcher
Cache IlluminateCacheCacheManager cache
Cache (Instance) IlluminateCacheRepository cache.store
Config IlluminateConfigRepository config
Cookie IlluminateCookieCookieJar cookie
Crypt IlluminateEncryptionEncrypter encrypter
DB IlluminateDatabaseDatabaseManager db
DB (Instance) IlluminateDatabaseConnection
Event IlluminateEventsDispatcher events
File IlluminateFilesystemFilesystem files
Gate IlluminateContractsAuthAccessGate
Hash IlluminateContractsHashingHasher hash
Lang IlluminateTranslationTranslator translator
Log IlluminateLogLogger log
Mail IlluminateMailMailer mailer
Notification IlluminateNotificationsChannelManager
Password IlluminateAuthPasswordsPasswordBrokerManager auth.password
Password (Instance) IlluminateAuthPasswordsPasswordBroker auth.password.broker
Queue IlluminateQueueQueueManager queue
Queue (Instance)IlluminateContractsQueueQueue queue.connection
Queue (Base Class) IlluminateQueueQueue
Redirect IlluminateRoutingRedirector redirect
Redis IlluminateRedisRedisManager redis
Redis (Instance) IlluminateRedisConnectionsConnection redis.connection
Request IlluminateHttpRequest request
Response IlluminateContractsRoutingResponseFactory
Response (Instance) IlluminateHttpResponse
Route IlluminateRoutingRouter router
Schema IlluminateDatabaseSchemaBuilder
Session IlluminateSessionSessionManager session
Session (Instance) IlluminateSessionStore session.store
Storage IlluminateFilesystemFilesystemManager filesystem
Storage (Instance) IlluminateContractsFilesystemFilesystem filesystem.disk
URL IlluminateRoutingUrlGenerator url
Validator IlluminateValidationFactory validator
Validator (Instance) IlluminateValidationValidator
View IlluminateViewFactory view
View (Instance) IlluminateViewView

Bài viết tham khảo từ nhiều nguồn

0