Bí mật lớn nhất Laravel được tiết lộ – Magic Methods

Tram Ho

Xin chào các bạn! Như các bạn biết thì Laravel là 1 framework mới nhưng đã vượt trội hoàn toàn so với các Framework đàn anh đàn chị khác của PHP về sự phổ biến. Vậy bạn có bao giờ bạn đặt câu hỏi WHAT, điều gì làm cho Laravel trở nên nổi bật như vậy không?
Trong bài này, mình muốn giới thiệu cho các bạn đặc trưng của PHP đóng góp vai trò quan trọng trong việc xây dựng framework Laravel tuyệt vời như vậy, không thể không nhắc đến Magic Methods của PHP.

Vậy nó có điều gì ‘ma thuật’ như vậy, hãy cùng mình tìm hiểu trong bài viết này nhé!

Magic Methods là gì?

Điều đầu tiên, các bạn phải hiểu rằng các magic methods không chỉ dành riêng cho Laravel, mà nó có sẵn trong bất kỳ ứng dụng PHP nào. Vì mình đang làm việc với Framework Laravel nên mình xin phép bài viết này lấy ví dụ liên quan đến framework này ạ.

Magic methods là các phương thức đặc biệt để tùy biến các sự kiện trong PHP. Hiểu đơn giản là nó cung cấp thêm cách giải quyết 1 vấn đề. Magic methods được dùng để xử lý các đối tượng trong OOPS.

Các magic methods sẽ không bao giờ được gọi trực tiếp, có thể gọi magic methods là behind the scenes.

Hiện tại có tổng 15 hàm magic methods:

Nếu bạn, đã từng làm việc với OOPs PHP nói chung, Laravel nói riêng thì bạn đã bắt gặp ở đâu đó phương thức __construct(). Hàm __contruct sẽ tự động được gọi khi ta khởi tạo 1 đối tượng (còn được gọi là hàm khởi tạo). Vậy là bạn đã từng sử dụng method magics rồi phải không?

Bạn cũng sẽ nhận thấy rằng tất cả các magic methods đều có tiền tố prefix __.

Bài viết này, mình không thể giới thiệu hết các magic method, mình chỉ nêu ra 4 hàm: __get(), __set(), __call(), __callStatic() được sử dụng trong codebase của Laravel. Nếu bạn quan tâm đến các hàm khác, có thể tìm hiểu thêm tại đây.

Laravel đã sử dụng ‘ma thuật’ như nào?

__get()

Trong Model của Laravel thực sự đặc biệt. Chúng không lưu trữ dữ liệu thuộc tính dưới dạng thuộc tính trực tiếp của Class nhưng trong đó có 1 thuộc tính protected $attributes, là mảng lưu các thuộc tính attribute của Model.

Sự khác biệt giữa cách sử dụng giữa lớp trong PHP thuần và lớp Model trong Laravel

Chúng ta có thể thấy 2 ví dụ hoạt động cho ra kết quả giống hệt nhau. Tuy nhiên, trong Laravel các thuộc tính attribute không được lưu như trong PHP, thay vào đó, tất cả thuộc tính attribute được định nghĩa trong 1 thuộc tính có tên $attributes. Vậy tại sao khi truy cập vào thuộc tính cần, chúng lại có thể trả về đúng dữ liệu được nhỉ 😕 😕 😕

Đơn giản vì phía sau con đường luôn có magic method __get

Mọi thứ có vẻ ổn!

Chúng ta cần lưu ý rằng magic method __get() chỉ được gọi khi ta truy cập vào thuộc tính không tồn tại hoặc thuộc tính không thể truy cập (protected hoặc private) trong Class. Để làm rõ điều này, hãy cùng xem ví dụ dưới đây:

Còn nhiều thứ được Laravel thực hiện khi hàm __get() magic methods được gọi, chi tiết các bạn có thể xem tại đây.

__set()

Magic method __set() được gọi khi ta truyền dữ liệu vào thuộc tính không tồn tại hoặc thuộc tính (protected hoặc private) trong Class.

Cùng mình xem tiếp ví dụ để xem sự khác biệt giữa cách sử dụng giữa lớp trong PHP thuần và lớp Model trong Laravel nhé!

Trong ví dụ, ta đang cố gắng gán value ‘Quan’ vào thuộc tính attribute firstName không tồn tại trong Class mà nó được định nghĩa trong thuộc tính $attributes.

Các bạn nhìn title là __set(), chắc nhiều bạn cũng đoán được là dùng ma thuật của hàm __set() để xử lí chứ gì hãy cùng thử thực hiện xem sao 😕 😕 😕

Vậy là xong, chúng ta đã thực hiện thành công việc sử dụng cơ bản magic method __get()__set() trong Laravel. Mình đang cố gắng lấy ví dụ đơn giản để bạn có thể hiểu đơn giản về các mà Laravel làm việc, chi tiết về __set() các bạn có thể xem thêm tại đây.

__call() & __callStatic()

Magic method __call() được gọi khi ta gọi phương thức không được phép truy cập trong phạm vi của một đối tượng. Trong Laravel, magic method này được sử dụng để tạo ra các macro có trong PHP.

Nhiệm vụ của macro là gì? Thì nhiệm của macro khác nhau ở các ngôn ngữ khác nhau, tuy nhiên nó đều mang một sứ mệnh chung là thực hiện một nhiệm vụ mầ chúng ta định sẵn.

Bây giờ, thử xem làm thế nào chúng ta có thể tạo macro trong PHP thuần nhé…

Đoạn chương trình này khi chạy chắc chắn sẽ gặp lỗi vì phương thức fullName chưa được khai báo trong class User. Chúng ta nhận được thông báo Call to undefined method User::fullName()

Bây giờ với magic method __call, ta có thể định nghĩa 1 mảng sẽ chứa hàm Closure.

Vậy là chúng ta đã biết tạo macro bằng việc sử dụng magic method __call.

Với magic method __callStatic hoạt động tương tự như magic method _call nhưng đối với các phương thức tĩnh static.

Bạn có thể tham khảo Macroable trong Laravel [tại đây].(https://github.com/laravel/framework/blob/7.x/src/Illuminate/Support/Traits/Macroable.php)

Kết luận

Trên đây mình đã giới thiệu cho các bạn cách Laravel sử dụng magic methods trong basecode của họ. Bài viết này có vẻ hơi sâu về framework với những bạn mới tìm hiểu về Laravel nhưng chung quy lại thì nếu bạn chắc về kiến thức PHP thì cũng không gặp khó khăn gì cả. Mong qua bài viết này, các bạn có hiểu được thêm dòng code mình viết ra nó được xử lí như nào.

Cảm ơn bạn đã đọc bài viết của mình!!!

Tài liệu tham khảo

https://www.php.net/manual/en/language.oop5.magic.php

https://github.com/laravel/framework/blob/7.x/src/Illuminate/Database/Eloquent/Model.php

https://github.com/laravel/framework/blob/7.x/src/Illuminate/Support/Traits/Macroable.php

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo