post-image

Khái niệm Lambda và Closure trong PHP

Tổng quan

NỘI DUNG BÀI VIẾT

Trong quá trình làm quen với các framework PHP như Laravel, Symfony… chúng ta rất hay gặp các khái niệm Lambda, Closure, chúng đều là những tính năng mới cho phép tái cấu trúc mã nguồn trở lên trực quan và dễ đọc hơn. Các khái niệm này đều rất căn bản tuy nhiên không phải ai cũng để ý và sử dụng chúng thành thạo. Bài viết này sẽ giới thiệu với các bạn Lambda là gì?, Closure là gì? và chúng được sử dụng trong lập trình PHP như thế nào?

Lambda là gì?

Nếu bạn đã từng làm việc nhiều với các ngôn ngữ như Javascript hay Ruby thì không còn xa lạ gì với hàm “nặc danh” (anonymous function), khái niệm này cũng tương tự trong PHP. Hàm nặc danh là một hàm không có tên và Lambda là một hàm nặc danh có thể được gán vào một biến hoặc truyền vào một hàm khác như một tham số. Chúng ta đã quá quen thuộc với các hàm thông thường trong PHP:

function sayHello() { return "Xin chào!"; } echo sayHello();
Code language: PHP (php)

Hàm nặc danh chỉ đơn giản là một hàm không có tên và nó có thể được định nghĩa như sau:

function () { return "Xin chào!"; }
Code language: JavaScript (javascript)

Các hàm thông thường muốn thực hiện được chúng ta cần gọi đến tên của nó, vậy hàm nặc danh thì thế nào? Do hàm nặc danh không có tên nên bạn cần gán nó với một biến hoặc truyền nó vào như một tham số:

$hello = function () { return "Xin chào!"; } // Gọi hàm này echo $hello(); // Xin chào!
Code language: PHP (php)

Ví dụ trên đây chúng ta đã gắn hàm nặc danh với một biến, tiếp theo cùng tìm hiểu cách truyền hàm nặc danh vào như tham số.

// Truyền anonymous function vào tham số function speak($message){ echo $message(); } // Gọi hàm speak(function(){ return "Xin chào"; });
Code language: PHP (php)

Sử dụng hàm nặc danh hay Lambda là rất hữu ích khi các chức năng chúng ta chỉ cần sử dụng một lần duy nhất, bản chất sâu xa của vấn đề là nó sử dụng một phương thức được xây dựng sẵn trong PHP là create_function(). Ví dụ ở trên có thể viết lại như sau:

$hello = create_function('', 'echo "Xin chào";'); // Gọi hàm $hello();
Code language: PHP (php)

Closure là gì?

Closure là một class sử dụng anonymous function, nói cách khác Closure về cơ bản giống hàm nặc danh, ngoài ra nó có thể truy cập các biến bên ngoài phạm vi mà nó tạo ra. Closure đóng gói phạm vi của nó, nó không có quyền truy nhập vạo phạm vi mà nó được định nghĩa hoặc thực hiện. Nó có thể kế thừa các biến từ phạm vi cha (nơi closure được định nghĩa) vào closure với từ khóa use.

// Tạo một người dùng $user = "Nguyễn Văn A"; // Tạo một Closure $hello = function() use ($user) { echo "Xin chào $user"; }; // Hiển thị lời chào $hello(); // "Xin chào Nguyễn Văn A"
Code language: PHP (php)

Trong ví dụ trên bạn có thể thấy Closure có thể truy xuất biến user vì nó khai báo trong từ khoá usertrong phần định nghĩa Closure. Nếu bạn thay đổi giá trị của user vì nó được khai báo trong từ khoá use trong phần định nghĩa Closure. Nếu bạn thay đổi giá trị của user trong Closure, nó không ảnh hưởng gì đến giá trị gốc. Để cập nhật được giá trị gốc chúng ta sử dụng con trỏ tham chiếu & trong PHP. Ví dụ:

$i = 0; // Tăng biến $i trong phạm vi Closure $closure = function () use ($i){ $i++; }; // Gọi hàm $closure(); // Kết quả $i ở ngoài không thay đổi echo $i; // 0 $i = 0; // Tăng biến $i trong phạm vi Closure nhưng sử dụng con trỏ tham chiếu & $closure = function () use (&$i){ $i++; }; // Gọi hàm $closure(); // Biến $i ở ngoài đã thay đổi echo $i; // 1
Code language: PHP (php)

Closure là rất hữu dụng khi sử dụng các hàm PHP mà chấp nhận một hàm callback kiểu như array_map, array_filter… Ví dụ tiếp theo chúng ta sử dụng hàm array_walk, nó nhận một mảng và chạy qua từng phần tử và cho phép gọi các hàm callback:

// Mảng tên người dùng $users = array("Trần Thu Hà", "Nguyễn Mỹ Linh", "Hồ Quỳnh Hương", "Thu Minh"); // Truyền mảng này vào array_walk array_walk($users, function ($name) { echo "Xin chào $name<br>"; }); // Xin chào Trần Thu Hà // Xin chào Nguyễn Mỹ Linh // ...
Code language: PHP (php)

Closure có thể sử dụng các biến ngoài phạm vi của nó bằng cách sử dụng từ khóa use, ví dụ tiếp theo chúng ta

$multiplier = 7; // Mảng các số $numbers = array(1,2,3,4,5); // Sử dụng array_walk để đi qua toàn bộ các phần tử và nhân chúng với $multiplier array_walk($numbers, function($number) use($multiplier){ echo $number * $multiplier; });
Code language: PHP (php)

Trong ví dụ trên, chúng ta thấy rằng không cần thiết phải tạo ra một hàm chỉ để nhân hai số với nhau, do đó chúng ta sử dụng Closure để thực hiện công việc như thế này và sau đó không bao giờ dùng đến nó. Bằng cách sử dụng Closure như một hàm callback, chúng ta có thể sử dụng chức năng này một lần và sau đó quên đi nó.

Như ở đầu bài đã nói, Closure là một khái niệm rất hay dùng trong các framework PHP hiện nay, việc sử dụng Lambda và Closure để thực hiện các công việc nhỏ mà không làm ảnh hưởng đến namespace của dự án và đặc biệt sử dụng nó rất tốt trong callback. Ví dụ tiếp theo chúng ta sẽ thực hiện một route trong routes/web.php của Laravel nhằm in ra lời chào với định dạng đường dẫn kiểu user/tên_người_dùng.

Route::get('user/(:any)', function($name){ return "Xin chào " . $name; });
Code language: PHP (php)

Cảm ơn các bạn đã đọc.

Các bạn có thể tham khảo các bài viết hay về Laravel tại đây.


Hãy tham gia nhóm Học lập trình để thảo luận thêm về các vấn đề cùng quan tâm.

Nguồn tham khảo: allaravel

Leave a Reply

Your email address will not be published.