__call và __callStatic
Thuộc phần Lập trình hướng đối tượng trong hành trình PHP của Coddy. Bài học 47 trên 91.
Tương tự như __get() và __set() chặn thao tác truy cập thuộc tính, các phương thức __call() và __callStatic() chặn lời gọi phương thức. Chúng được kích hoạt khi bạn gọi một phương thức không tồn tại hoặc không thể truy cập trên một đối tượng hoặc lớp.
Phương thức __call() xử lý các lệnh gọi phương thức của đối tượng. Phương thức này nhận tên phương thức và một mảng đối số:
<?php
class Messenger {
public function __call(string $name, array $arguments): string {
return "Called '$name' with: " . implode(", ", $arguments);
}
}
$msg = new Messenger();
echo $msg->sendEmail("Hello", "World");
Đầu ra:
Called 'sendEmail' with: Hello, WorldĐể gọi phương thức tĩnh, hãy dùng __callStatic(). Lưu ý, bạn phải khai báo phương thức này là static:
<?php
class QueryBuilder {
public static function __callStatic(string $name, array $arguments): string {
if (str_starts_with($name, "findBy")) {
$field = substr($name, 6);
return "Finding by $field: " . $arguments[0];
}
return "Unknown method: $name";
}
}
echo QueryBuilder::findByEmail("test@example.com");
Đầu ra:
Finding by Email: test@example.comCác phương thức ma thuật rất hữu ích khi tạo API linh hoạt, triển khai tính năng chuyển tiếp phương thức hoặc xây dựng trình tạo truy vấn động, trong đó tên phương thức được chuyển thành các thao tác cơ sở dữ liệu. Chúng cho phép đối tượng phản hồi thông minh với mọi lời gọi phương thức, kể cả những phương thức bạn chưa định nghĩa rõ ràng.
Thử thách
DễHãy cùng xây dựng một API client linh hoạt, sử dụng các phương thức ma thuật để xử lý lời gọi phương thức. Bạn sẽ tạo một lớp chặn cả lời gọi phương thức của đối tượng lẫn lời gọi phương thức tĩnh, rồi chuyển chúng thành các phản hồi giống API có ý nghĩa mà không cần định nghĩa từng phương thức riêng.
Bạn sẽ sắp xếp code trong hai tệp:
ApiClient.php: Tạo lớpApiClientmô phỏng các tương tác API bằng phương thức ma thuật. Lớp của bạn cần có thuộc tính$baseUrlriêng, được thiết lập thông qua hàm khởi tạo. Hãy triển khai hai phương thức ma thuật:__call(): Xử lý lời gọi phương thức của đối tượng. Khi có lời gọi phương thức bắt đầu bằngget(chẳng hạngetUsershoặcgetPosts), hãy trích xuất tên tài nguyên (phần sau "get") và trả về"GET [baseUrl]/[resource]: [arguments joined by comma]". Tên tài nguyên cần được chuyển thành chữ thường. Nếu phương thức không bắt đầu bằng "get", hãy trả về"Unknown action: [methodName]".__callStatic(): Xử lý lời gọi phương thức tĩnh. Khi có lời gọi phương thức bắt đầu bằngcreate(chẳng hạncreateUser), hãy trích xuất tên tài nguyên và trả về"POST /[resource]: [arguments joined by comma]". Tên tài nguyên cần viết bằng chữ thường. Với các phương thức bắt đầu bằngdelete, hãy trả về"DELETE /[resource]: [first argument]". Với mọi phương thức khác, hãy trả về"Static action not supported: [methodName]".
main.php: Nạp tệp ApiClient. Bạn sẽ nhận ba đầu vào: URL cơ sở, mã định danh tài nguyên và một giá trị. Tạo một đối tượngApiClientbằng URL cơ sở. Sau đó, in ra bốn dòng:- Gọi một phương thức
getđộng, dùng mã định danh tài nguyên làm hậu tố tên phương thức (ví dụ: nếu tài nguyên là "Users", hãy gọigetUsers) và dùng giá trị làm đối số - Gọi
getProductsvới hai đối số:"electronics"và"active" - Gọi phương thức tĩnh
createOrdervới giá trị làm đối số - Gọi phương thức tĩnh
deleteItemvới mã định danh tài nguyên làm đối số
- Gọi một phương thức
Phương thức ma thuật cho phép API client phản hồi linh hoạt với mọi lời gọi phương thức. Thay vì định nghĩa getUsers(), getPosts(), getProducts() và hàng chục phương thức khác, chỉ một phương thức __call() có thể xử lý tất cả bằng cách kiểm tra tên phương thức và trích xuất thông tin liên quan.
Tự làm thử
<?php
require_once 'ApiClient.php';
// Đọc dữ liệu đầu vào
$baseUrl = trim(fgets(STDIN));
$resource = trim(fgets(STDIN));
$value = trim(fgets(STDIN));
// TODO: Tạo một instance ApiClient với URL cơ sở
// TODO: Gọi phương thức get động, dùng resource làm hậu tố tên phương thức
// Gợi ý: Dùng cách gọi phương thức qua biến như $api->{"get" . $resource}($value)
// TODO: Gọi getProducts với hai đối số: "electronics" và "active"
// TODO: Gọi phương thức tĩnh createOrder với value làm đối số
// Gợi ý: Dùng ApiClient::createOrder($value)
// TODO: Gọi phương thức tĩnh deleteItem với resource làm đối số
?>Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng về OOP
Tệp bên ngoàiGiới thiệu về OOPLớp và đối tượngTừ khóa $thisPhương thứcThuộc tínhHàm khởi tạo (__construct)Hàm hủy (__destruct)Ôn tập: máy tính đơn giản4Kế thừa
Kế thừa cơ bảnTừ khóa parent::Ghi đè phương thứcTừ khóa finalLớp trừu tượngÔn tập: hệ thống phân cấp nhân viên7Đóng gói
Công khai, được bảo vệ, riêng tưTìm hiểu sâu về bộ điều chỉnh quyền truy cậpGetter và setterẨn thông tinRút gọn hàm khởi tạo (8.0)Ôn tập: hệ thống hồ sơ học sinh2Không gian tên và tự động nạp
Giới thiệu về không gian tênTừ khóa useChuẩn tự động nạp PSR-4Trình tự động nạp của ComposerÔn tập: dự án có tổ chức5Giao diện và hợp đồng
Giới thiệu về giao diệnTriển khai giao diệnTriển khai nhiều giao diệnGiao diện và lớp trừu tượngGợi ý kiểu với giao diệnÔn tập: Máy tính hình học8Phương thức ma thuật
Giới thiệu về phương thức ma thuật__toString và __debugInfo__get, __set, __isset, __unset__call và __callStatic__clone và sao chép đối tượng__serialize và __unserializeÔn tập: Bộ sưu tập tùy chỉnh3Thuộc tính của lớp
Thuộc tính instance và staticHằng số trong lớpPhương thức và thuộc tính staticThuộc tính private và protectedThuộc tính chỉ đọc (PHP 8.1)Ôn tập: Trình quản lý tài khoản ngân hàng6Đa hình
Xem lại việc ghi đè phương thứcĐa hình qua giao diệnGợi ý kiểu và kiểu hợpLiên kết tĩnh muộnÔn tập: bộ xử lý thanh toánTự luyện tập: Trình biên dịch PHP online