Chuẩn tự động nạp PSR-4
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 12 trên 91.
PSR-4 là một tiêu chuẩn quy định cách tự động tải các lớp PHP dựa trên không gian tên và vị trí tệp của chúng. Thay vì tự đưa từng tệp lớp vào, PSR-4 giúp PHP tự tìm và tải các lớp khi bạn sử dụng chúng.
Quy tắc cốt lõi rất đơn giản: namespace phải khớp với cấu trúc thư mục. Nếu bạn có lớp App\Models\User, tệp phải nằm ở App/Models/User.php.
<?php
// Tệp: src/Models/User.php
namespace App\Models;
class User {
public $name;
public function __construct($name) {
$this->name = $name;
}
}
Bạn có thể viết một hàm tự động nạp đơn giản tuân theo các quy tắc PSR-4:
<?php
// Tệp: autoload.php
spl_autoload_register(function ($class) {
$prefix = 'App\\';
$baseDir = __DIR__ . '/src/';
// Kiểm tra xem lớp có dùng tiền tố không gian tên của chúng ta không
if (strpos($class, $prefix) === 0) {
$relativeClass = substr($class, strlen($prefix));
$file = $baseDir . str_replace('\\', '/', $relativeClass) . '.php';
if (file_exists($file)) {
require $file;
}
}
});
Hàm (function) spl_autoload_register yêu cầu PHP gọi hàm của bạn mỗi khi gặp một lớp không xác định. Hàm này chuyển không gian tên thành đường dẫn tệp rồi tải tệp đó.
Điểm chính: PSR-4 tạo ra quy tắc ánh xạ dễ dự đoán giữa namespace và đường dẫn tệp. Khi thấy App\Models\User, bạn biết ngay tệp nằm ở src/Models/User.php. Quy ước này giúp bạn dễ dàng tìm hiểu cấu trúc và bảo trì dự án.
Thử thách
DễHãy xây dựng một hệ thống nạp tự động PSR-4 đơn giản, tự động tải các lớp dựa trên không gian tên và vị trí tệp.
Bạn sẽ tạo một dự án gồm ba tệp để minh họa cách PSR-4 ánh xạ không gian tên thành đường dẫn thư mục:
src/Services/Logger.php: Định nghĩa lớp (class)Loggertrong không gian tênApp\Services. Lớp này cần có thuộc tính (property)public $name, một hàm khởi tạo (constructor) nhận và thiết lập tên, cùng phương thức (method)log($message)trả về"[name] logged: [message]".src/Services/Mailer.php: Định nghĩa lớpMailertrong không gian tênApp\Services. Lớp này cần có thuộc tínhpublic $sender, một hàm khởi tạo nhận và thiết lập người gửi, cùng phương thứcsend($to)trả về"Mail from [sender] to [to]".main.php: Tạo trình nạp tự động PSR-4 bằngspl_autoload_register, ánh xạ tiền tố không gian tênApp\tới thư mụcsrc/. Trình nạp tự động cần chuyển dấu phân cách không gian tên thành dấu phân cách thư mục và thêm.phpđể tìm đúng tệp. Sau khi đăng ký trình nạp tự động, dùng từ khóauseđể nhập cả hai lớp, sau đó tạo mộtLoggercó tên"FileLogger"và mộtMailercó người gửi"admin@site.com". In kết quả gọilog("System started")trên logger vàsend("user@example.com")trên mailer, mỗi kết quả trên một dòng riêng.
Điểm mấu chốt là hàm (function) nạp tự động nhận tên lớp đầy đủ (chẳng hạn App\Services\Logger) và phải chuyển tên đó thành đường dẫn tệp (src/Services/Logger.php). Dùng strpos để kiểm tra xem tên lớp có bắt đầu bằng tiền tố không gian tên của bạn không, dùng substr để lấy tên lớp tương đối và dùng str_replace để chuyển dấu gạch chéo ngược thành dấu gạch chéo xuôi.
Tự làm thử
<?php
// Triển khai trình tự động tải PSR-4
// TODO: Đăng ký trình tự động tải bằng spl_autoload_register
// Trình tự động tải cần:
// 1. Kiểm tra xem tên lớp có bắt đầu bằng tiền tố không gian tên 'App\' không
// 2. Bỏ tiền tố 'App\' để lấy tên lớp tương đối
// 3. Chuyển dấu phân cách không gian tên (\) thành dấu phân cách thư mục (/)
// 4. Thêm 'src/' vào đầu và '.php' vào cuối để tạo đường dẫn tệp
// 5. Nạp tệp nếu tệp tồn tại
spl_autoload_register(function ($class) {
// TODO: Xác định tiền tố không gian tên và thư mục gốc
// TODO: Kiểm tra xem lớp có dùng tiền tố không gian tên không (dùng strpos)
// TODO: Lấy tên lớp tương đối (dùng substr)
// TODO: Tạo đường dẫn tệp bằng cách thay \ bằng / (dùng str_replace)
// TODO: Nạp tệp nếu tệp tồn tại
});
// TODO: Dùng từ khóa 'use' để nhập các lớp (class) Logger và Mailer
// TODO: Tạo một instance Logger có tên "FileLogger"
// TODO: Tạo một instance Mailer với người gửi là "admin@site.com"
// TODO: In ra kết quả của log("System started")
// TODO: In ra kết quả của send("user@example.com")
?>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