Facade Laravel là gì
Laravel đơn giản, đẹp và hiệu quả hơn với Laravel Facade63,006 lượt xem - Viết bởi FirebirD- 11 bình luận Share Facebook Twitter Google+ Pinterest WhatsApp 1. Giới thiệuCó thể nói Laravel là framework PHP số 1 hiện nay vì mấy lý do sau: Show
2. Laravel Facade là gì?Quay trở lại bài viết, sở dĩ chúng ta có tiêu đề bài viết "Laravel đơn giản, đẹp và hiệu quả hơn với Laravel Facade", đúng vậy trong các phần khóa học Laravel 5 miễn phí, bạn đã bắt đầu ngay với các khái niệm ở thượng tầng hệ thống một cách rất dễ hiểu, nhưng bạn không ngờ tới rằng mình sử dụng Laravel Facade rất nhiều. Ví dụ, khái niệm đầu tiên khi làm quen với Laravel là Laravel Route, bạn sẽ thấy ngay một route được định nghĩa sẵn trong routes\web.php: Route::get('/', function () { return view('welcome'); });Route ở đây chính là một Laravel Facade và get() là một phương thức của Facade Route. Facade là một đề tài nóng trong cộng đồng Laravel, một số người thích nó, một số người khác thì không. Cá nhân tôi, Facade là một phần không thể thiếu của Laravel, không có nó Laravel không thể trở thành một framework PHP phổ biến như hôm nay. Laravel Facade có mấy điểm mà rất nhiều người thắc mắc:
3. Laravel Facade hoạt động như thế nào?3.1 __callStatic là mấu chốt của Laravel FacadeCác thành phần trong Laravel được lưu giữ trong một container, bạn có thể tưởng tượng nó là một cái hộp lớn lưu trữ toàn bộ các service. Các service này chỉ được tạo ra instance một lần và chỉ tạo ra khi cần dùng đến, tức là bạn không cần khởi tạo các dịch vụ này, nó tự động hoàn toàn. Chúng ta cùng tìm hiểu xem cách Laravel Facade sử dụng container như thế nào? Trở lại với ví dụ Route đầu tiên ở trên, nó gọi đến phương thức get() theo cách gọi một phương thức static, nhưng không phải vậy Laravel Facade tương đồng với Proxy Pattern, nó sử dụng magic method __callStatic() để làm một bức tường chắn phía trước (proxy) để thực hiện các phương thức của lớp. Khi chúng ta gọi phương thức get(), Facade sẽ lấy các service liên quan trong container và trả về một instance, do vậy nó có thể thực thi được phương thức của class tương ứng. Chính vì thế cách viết code sau là cùng kết quả với ví dụ đầu. $app->router->get('/', function () { return view('welcome'); });Đến đây, bạn thấy rõ cú pháp của Laravel đã đơn giản, dễ đọc hơn khi áp dụng Laravel Facade. Tuy nhiên, một câu hỏi chưa được trả lời "Laravel Facade hoạt động như thế nào?". Chúng ta cùng tiếp tục tìm hiểu nhé. Khi bạn gọi Route::get() thì Route là một cái tên ngắn (alias) cho tên lớp đầy đủ Illuminate\Support\Facades\Route. Thiết lập này được thực hiện trong file cấu hình config\app.php trong mảng aliases: 'aliases' => [ ... 'Route' => Illuminate\Support\Facades\Route::class, ... ],Như vậy, khi bạn thực hiện Route::get() thì thực ra là bạn gọi đếnIlluminate\Support\Facades\Route::get(). Chúng ta sẽ đi sâu hơn vào framework để hiểu cách hoạt động của Laravel Facade, classIlluminate\Support\Facades\Route được lưu trữ trong file vendor\laravel\framework\src\Illuminate\Support\Facades\Route.php, mở file này chúng ta thấy các Facade có chung một phương thức getFacadeAccessor: namespace Illuminate\Support\Facades; class Route extends Facade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'router'; } }Các class này đều được mở rộng từ class cơ bản Facade, như ở trên đã nói thì các phương thức của Facade được gọi theo kiểu phương thức static do đó khi gọi nó sẽ thực hiện magic method callStatic() của class. Như vậy, phương thức callStatic của class Facade chính là nơi xử lý các lời gọi phương thức kiểu như Route::get(). namespace Illuminate\Support\Facades; abstract class Facade { ... 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); } ... }Laravel sử dụng spread operator (toán tử ...) từ phiên bản Laravel 5.0 trở đi, với các phiên bản cũ hơn, phương thức __callStatic() được thực hiện như sau: Chúng ta thấy dù là theo cách nào, tại đây Facade sẽ lấy một instance tương ứng với class và thực hiện gọi đến phương thức với việc truyền vào cả các tham số. 3.2 Sử dụng IoC ContainerIoC viết tắt của Inversion of Control, để hiểu được Inversion of Control là gì chúng ta đến với vấn đề sau trong lập trình. Một class A phụ thuộc vào một service hoặc một component là những lớp cụ thể (concrete class) trong lúc chạy ứng dụng. Chúng ta có một số vấn đề sau:
Nguyên lý Inversion of Control để giải quyết vấn đề trên, nó ủy quyền thực hiện việc lựa chọn các class cụ thể cho một component ở ngoài. Thực hiện nguyên lý này có hai pattern hay được sử dụng là Service Locator và Dependency Injection. Dưới đây là hai cách thực hiện nguyên lý trên. Service Locator: Dependency Injection: Các khái niệm này chúng ta sẽ cùng nhau bàn cụ thể hơn trong các bài viết khác, quay trở lại với Laravel Facade, nó sử dụng một Inversion of Control Container hay chính là một trong hai pattern trên, ở đây Laravel sử dụng IoC Container là Service Locator. Container này đơn giản là một lưu trữ kiểu key-value để tìm ra thực thể của class cần sử dụng. Trong luồng hướng đối tượng, việc gán tĩnh các object được thay thế bởi builder object, nó sẽ đưa ra các object ở runtime (thông thường là tạo đối tượng ngay, nhưng ở đây sẽ tạo đối tượng trong một lúc nào đó không xác định khi ứng dụng chạy). Với kỹ thuật này, dễ dàng thay thế các đối tượng với các thực thể khác phù hợp. Chúng ta cùng xem một ví dụ về container: class App { private static $instances = []; public static function set($name, $instance) { if (is_string($instance)) { $instance = new $instance(); } static::$instances[$name] = $instance; } public static function get($name) { $instance = static::$instances[$name]; if ($instance instanceof Closure) { $instance = $instance(); } return $instance; } }Hai phương thức set và get trong class trên cho phép tương tác với mảng các instance, người dùng có thể thêm hoặc lấy ra các thực thể thông qua tên class. Ví dụ chúng ta có một class sau: interface MessageInterface { public function greeting(); } class EnglishMessage implements MessageInterface { public function greeting() { return 'Hello!'; } } class VietnameseMessage implements MessageInterface { public function greeting() { return 'Xin chào!'; } }Khi đó chúng ta có thể sử dụng Service Locator như sau: App::set('message', 'EnglishMessage'); echo App::get('message')->greeting(); // Hello!Khi bạn muốn thay thế thực thể của EnglishMessage bởi một thực thể của class khác phù hợp, ví dụ như VietnameseMessage, chúng ta chỉ cần thiết lập lại và vẫn thực hiện các phương thức get như bình thường. App::set('message', 'VietnameseMessage'); echo App::get('message')->greeting(); // Xin chào!Bạn thấy đấy, phần code thực hiện không bị thay đổi gì, và nó giải quyết vấn đề về phụ thuộc trong lập trình. Trong Laravel Facade, nó cũng thực hiện tương tự thông qua thuộc tính$resolvedInstance và phương thứcresolveFacadeInstance() trong class Facade: protected static function resolveFacadeInstance($name) { if (is_object($name)) { return $name; } if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } return static::$resolvedInstance[$name] = static::$app[$name]; }4. Tạo Laravel Facade riêng trong Laravel 5.4Đôi khi bạn cần sử dụng lại các đoạn code, các chức năng, bạn hoàn toàn có thể tạo ra một Laravel Facade riêng để sử dụng. Cách tạo một Facade cũng khá đơn giản, chúng ta cùng thực hiện các bước sau: Bước 1: Tạo class Trước hết bạn cần có một môi trường đã cài đặt sẵn Laravel, tạo một thư mục Allaravel trong thư mục app của project để lưu trữ các class tạo ra. Tiếp đó tạo một file DemoClass.php trong app\Allaravel với nội dung bạn muốn thực hiện: namespace App\Allaravel; class DemoClass { public function demoMethod() { return 'This is custome Facade demo'; } }Class này rất đơn giản với phương thức demoMethod() trả về dòng chữ 'This is custome Facade demo'. Bước 2: Tạo Service Provider Service Provider dùng để đăng ký class với framework, sử dụng câu lệnh Laravel Artisan để thực hiện: câu lệnh này sẽ tạo ra file DemoClassServiceProvider.php trong thư mục app\Providers, mở file ra và thêm code gắn class. namespace App\Providers; use Illuminate\Support\ServiceProvider; use App; class DemoClassServiceProvider extends ServiceProvider { /** * Bootstrap the application services. * * @return void */ public function boot() { // } /** * Register the application services. * * @return void */ public function register() { App::bind('democlass', function() { return new \App\Allaravel\DemoClass; }); } }Bước 3: Tạo Facade class Trong bước này chúng ta tạo ra một class DemoClassFacade.php nằm trong thư mục app\Allaravel, class này phải kế thừa từ class Facade. namespace App\Allaravel; use Illuminate\Support\Facades\Facade; class DemoClassFacade extends Facade{ protected static function getFacadeAccessor() { return 'democlass'; } }Bước 4: Thiết lập cấu hình ứng dụng Service Provider ở bước 2 và lớp DemoClassFacade cần được thiết lập trong file cấu hình của ứng dụng Laravel, các thiết lập này trong file config\app.php: 'providers' => [ ... App\Providers\DemoClassServiceProvider::class, ... ], 'aliases' => [ ... 'DemoClass'=> App\Allaravel\DemoClassFacade::class, ... ],Thiết lập thứ nhất cho Service Provider, thiết lập thứ hai để alias cho Facade. Bước 5: Sử dụng DemoClassFacade Mở file routes\web.php và thử sử dụng DemoClassFacade: Route::get('/', function () { $message = DemoClass::demoMethod(); echo $message;\\ This is custome Facade demo });5. Lời kếtLaravel Facade là một nội dung nâng cao trong framework Laravel do nó ăn sâu vào trong hệ thống, cái hay của Laravel là cho người dùng mới sử dụng ngay Facade nhưng người dùng không biết gì về khái niệm phức tạp này. Qua bài viết, các bạn chỉ cần nhớ một số điều sau về Laravel Facade:
Trong bài viết này chúng ta cũng nhắc đến Dependency Injection, đây cũng là một mảng kiến thức rất hay mà có dịp chúng ta sẽ bàn luận chi tiết về nó. Bài viết trên là những hiểu biết cá nhân, có thể có những khái niệm chưa rõ ràng do hạn chế về hiểu biết, rất mong các bạn có ý kiến cùng trao đổi cùng nhau nâng cao kiến thức.
Share Facebook Twitter Google+ Pinterest WhatsApp Bài viết trước Inversion of Control nguyên lý của các nguyên lý Bài tiếp theo Adapter Pattern cắm là chơi FirebirD Đam mê Toán học, Lập trình. Sở thích chia sẻ kiến thức, Phim hài, Bóng đá, Cà phê sáng với bạn bè. |