Tìm hiểu về Facade trong Laravel

Khái niệm Facade?

Trong ngôn ngữ

Mình thấy nhiều người (thật ra có cả mình) hay đọc là phờ cát hay phờ kết đờ Facade (fəˈsäd) – đọc là phơ-sát-đờ (đờ là ending sound nên đọc nhẹ nha)

Trong design pattern

Nếu như trước đây bạn hay tìm hiểu về Design Pattern thì có lẽ bạn cũng sẽ biết hoặc đâu đó nghe qua về Facade Pattern. Vì bài viết này không phải về Facade Pattern nên mình sẽ ko đi sâu vào nó. Đây là ví dụ nho nhỏ mang tính thực tế để giúp các bạn hình dung một cách cơ bản nhất về Facade Pattern:

Công ty bạn muốn đi picnic và bạn được giao nhiệm vụ chuẩn bị đồ ăn. Bạn sẽ phải mua nào là thịt, rau, nước uống,…

Thông thường thì bạn sẽ phải đi đến cửa hàng cá để mua cá, cửa hàng rau để mua rau và cửa hàng tạp hóa để mua nước uống.

Như vậy tức là bạn (client) sẽ phải giao tiếp với nhiều cửa hàng (service). Và rồi dịch vụ mua đồ hộ xuất hiện. Bạn chỉ cần tạo order:

– Bạn: Anh ơi cho em mua thịt, rau với nước uống

– Dịch vụ: ô kê anh ei. Giờ em sẽ đi ra 3 cửa hàng và mua cho anh. Đợi em 5 phút.

Trong trường hợp này dịch vụ mua đồ đóng vai trò là Facade.

Như vậy ta có thể rút ra:

  • Facade Pattern – đúng như cái tên của nó – mặt tiền – giúp cung cấp 1 lớp bề mặt để thống nhất các service con trong hệ thống.
  • Việc thống nhất sẽ giúp cho client tương tác với các service một cách nhanh gọn, dễ dàng hơn. Tại sao vậy? Vì làm việc với 1 lớp chung sẽ nhanh gọn hơn là làm việc với N service con.

Trong Laravel

Nhìn thì có vẻ cùng là Facade đấy, nhưng các bạn ạ, Facade cũng có Facade this và Facade that. Và Facade trong Laravel hoàn toàn…không phải là Facade Pattern mà mình đã nêu ở trên. Tuy nhiên nếu so về tư tưởng thì đâu đó mình thấy nó khá là tương đồng với nhau. Còn về việc nó tương đồng ở đâu, tương đồng như thế nào thì hãy xem hết bài viết này nhé.

Theo Laravel Documentaion thì:

Facades provide a “static” interface to classes that are available in the application’s service container. Laravel ships with many facades which provide access to almost all of Laravel’s features. Laravel facades serve as “static proxies” to underlying classes in the service container, providing the benefit of a terse, expressive syntax while maintaining more testability and flexibility than traditional static methods.

https://laravel.com/docs/7.x/facades

Tạm dịch là:

Facade cung cấp một “static” interface (tạm dịch là giao diện tĩnh) cho các lớp có sẵn trong service container của application. Các facade trong Laravel cung cấp quyền truy cập tới hầu hết các tính năng của Laravel. Facade trong Laravel phục vụ giống như là “static proxies” tới các lớp bên dưới trong service container. Nó khiến cho syntax code của chúng ta trở lên ngắn gọn hơn trong khi vẫn có khả năng test và mở rộng cao hơn so với các static methods truyền thống.

– Mình không dịch word-by-word như doc nhưng vẫn đủ ý nhé. ^^

Facade trong Laravel?

Khái niệm bên trên có vẻ hơi mang tính lý thuyết nhỉ. Mình nghĩ là nếu chỉ đọc khái niệm thì có thể bạn sẽ không biết Facade trong Laravel mặt mũi ra sao.

Thật ra thì…mình tin rằng bất cứ ai dùng qua Laravel cũng đề đã dùng qua Facade rồi. Nếu không biết thì chỉ là do các bạn không để ý đấy thôi.

Ví dụ nếu bạn nào đã dùng Query Builder thì chắc các bạn cũng đã từng sử dụng cú pháp ngắn gọn như sau:

use DB;

$users = DB::table('users')->get();

Hoặc là Auth chẳng hạn:

use Auth;

$user = Auth::user();

Ngoài ra còn có Cache, Config, Cookie, File, Hash,… nữa nhỉ. Thật ra thì đây cũng chưa hẳn phải là Facade, đây là các alias để giúp các bạn có thể import (đúng hơn là use) các Facade một cách ngắn gọn. Các bạn có thể xem chi tiết định nghĩa các alias ở trong file config/app.php nhé.

Như vậy lợi ích đầu tiên của Facade là giúp cho việc sử dụng các tính năng của Laravel một cách dễ dàng hơn mà không cần phải ghi nhớ toàn bộ namespace của nó.

Tiếp theo, nếu các bạn để ý thì khi dùng Facade hầu hết các bạn đều dùng các static function đúng không. Vẫn là 2 ví dụ ở trên:

DB::table('users')->get();
Auth::user();

Như vậy các bạn hoàn toàn không phải khởi tạo instance (bằng từ khóa new hoặc bằng Dependency Injection) từ class để có thể sử dụng được các tính năng của Laravel mà chỉ cần dùng các static function. Và đây cũng là lợi ích thứ 2 của nó.

Cách tạo Facade trong Laravel?

Mình xin tóm gọn lại thành 5 bước như sau:

  1. Tạo một service (như là Helper chẳng hạn)
  2. Đăng ký Helper với Service Provider
  3. Tạo ra một Facade Class
  4. Đăng ký Alias cho Facade vừa tạo
  5. Sử dụng

1. Tạo service (helper)

Mình sẽ tạo ra 1 file helper là Common.php trong thư mục app/Helpers như sau:

<?php

namespace App\Helpers;

class Common
{
    public function getBlogUrl()
    {
        return 'https://vantien.net';
    }
}

2. Đăng ký với Service Provider

Bạn có tự tạo 1 Service Provider để bind helper bên trên với từ khóa common_helper. Trong đây thì mình thì mình sẽ dùng luôn AppServiceProvider cho nhanh nhé. Đoạn code dưới đây mình sẽ cho vào hàm register() của AppServiceProvider.

App::bind('common_helper',function() {
    return new \App\Helpers\Common;
});

3. Tạo Facade class

Mình sẽ tạo ra 1 folder là Facades trong folder app cho facade của chúng ta vào đó. Sau đó mình tạo 1 file là CommonHelper.php trong đó và tạo 1 hàm tên là getFacadeAccessor(). Hàm này sẽ return về từ khóa mà chúng ta đã đăng ký ở trên:

<?php

namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class CommonHelper extends Facade
{
    public static function getFacadeAccessor()
    {
        return 'common_helper';
    }
}

4. Đăng ký alias cho Facade vừa tạo

Bạn còn nhớ file config/app.php lúc đầu chứ. Hãy vào đó và đăng ký nhé, nhìn list alias chắc mình cũng ko cần phải hướng dẫn cách thức đâu nhỉ.

5. Sử dụng

Xong hết tất cả các bước cần thiết rồi các bạn ạ. Bước cuối cùng là sử dụng thôi. Bây giờ bạn thử sử dụng như sau nhé:

use CommonHelper;
CommonHelper::getBlogUrl();

Quẩy lên nàoooooooo.

Tổng kết

Trên đây là nội dung bài viết về Facade trong Laravel. Thực ra là bài viết chỉ dừng lại ở phần cơ bản là cách dùng thôi. Còn việc nó hoạt động thế nào thì chưa có. Vì vậy mình xin phép được bổ sung sau nhé.

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *