Một ngày đẹp trời bạn đang viết những dòng code xịn xò, ngon nghẻ trên chiếc PC cấu hình khủng với con chip Intel thế hệ mới nhất cùng với 256GB ram thì bỗng nhiên bạn nhận ra.
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\View\View;
...Model User thì mình định nghĩa rõ ràng ở thư mục App\Models rồi, vậy còn cái View kia ở đâu ra nhỉ, mình đâu có định nghĩa đâu.
- Click vào phát xem vào
- Ồ thì ra nó nằm trong thư mục vendor, sao các file trong này có thể dùng bên ngoài với namespace ngắn thế nhỉ ?
- Bạn đọc được bài viết này.
AUTOLOADER
Ngày xưa khi bạn mới bắt đầu với PHP thì muốn chèn một file khác vào file hiện tại bạn phải sử dụng các method như include, include_once, require, require_once phải không ?
Rồi sau đó bạn chuyển sang một framework PHP như Larvavel, Symfony ... thì không còn thấy sử dụng nhiều nữa mà cứ thế use trực tiếp các class từ các namespace về sử dụng như bình thường.
Vì sao thế nhỉ ?
=> PHP AUTOLOAD
Từ phiên bản PHP5 đã có các hàm trợ giúp tự động hóa việc gọi như là spl_autoload_register, spl_autoload_functions, spl_autoload_extensions ...
Thực chất các hàm tự động nạp sẽ được gọi như sau:
<?php
spl_autoload_register(function ($class) {
include 'classes/' . $class . '.php';
});
?>Giờ thì sao ?
Khi chúng ta khai báo class mang tên là User đi chẳng hạn, trong thư mục classes.
// classes/User.php
<?php
class User
{
public function __construct()
{
echo 'User';
}
}
?>Và khi chúng ta muốn sử dụng thì thật đơn giản như là:
// index.php
<?php
spl_autoload_register(function ($class) {
include 'classes/' . $class . '.php';
});
vardump(new User());
// user
?>Đại khái là vậy, các bạn có thể tìm hiểu thêm.
Cùng với đó là khái niệm namespace trong PHP, các lập trình viên xây dựng cho mình một bộ code tự động nạp. Tuy nhiên để dễ dàng chia sẻ dùng lại code giữa các framework, giữa các dự án ..., cộng đồng PHP thống nhất một cách thức tự động nạp thư viện theo một chuẩn bố trí thư viện. Việc thống nhất đó hình thành một tiêu chuẩn nên tuân theo đó là PSR - 4 Autoload. Ngoài tiêu chuẩn tự động load PSR-4 còn có tiêu chuẩn tự động load theo PSR-0 (tuy nhiên đã lỗi thời, các dự án mới không nên theo PSR -0 nữa).
PSR-4 AUTOLOADED
Ứng dụng của tiêu chuẩn này như sau: Phải có một có chế và cách bố trí code trong các thư mục sao cho mọi lớp (class) đều có thể được tham chiếu đến bằng cách viết mã như sau:
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>Có nghĩa là mỗi lớp bạn phải xây dựng sao cho có thể được tham chiếu đến bởi dòng code ba thành phần: Namespace, Các SubNamespaceNames con, và tên lớp ClassName.
- NameSpace : Tiền đố đầu tiên bắt buộc phải có - được hiểu là tên
vendor. Tên này do bạn tự đặt, sao cho không xung đột tên các thư viện khác. - SubNameSpaces: Các namespace con (theo sau NameSpace đầu tiên - vendor). Có một hoặc nhiều tùy bạn. Nhưng bắt đầu từ SubNameSpace thì nó tương ứng với cấu trúc thư mục lưu trữ code. Ví dụ bạn lưu trữ code thư viện tại thư mục gốc là
src, và gọi đến một lớp của bạn tên là cls1 với cú pháp như sau\myvendor\namespace1\namespace2\cls1điều này có nghĩa là trong thư mụcsrccó thư mục tên lànamespace1, trong namespace1 có thư mụcnamespace2. - ClassName: Bắt buộc phải có và phải có tên file PHP trùng tên ClassName ở thư mục tương ứng với namespace cuối cùng (ClassName.php), trong file đó sẽ định nghĩa nội dung của code của lớp.
Đó là cách thống nhất viết bố trí code PHP trên các thư mục và theo các namespace. Khi đã viết code tuân thủ theo hướng dẫn này thì các famework khác nhau đều sử dụng một cơ chế tự động nạp tương tự nhau nên có thể dùng lại thư viện.
Đến đây trong dự án của bạn cần sử dụng một thư viện Autoload để tự động nạp cấu trúc trên khi cần dùng đến. Các Framework PHP hầu hết có sử dụng bộ tự động nạp theo PSR-4. Tham khảo mẫu Autoloader tự động đăng ký các lớp tự động tải vào khi dùng đến, với điều kiện các lớp viết theo PSR-4. Dùng Composer nó sẽ phát sinh mã tự động nạp thư viện theo PSR-4 cho bạn.
Giờ tôi viết thư mục như nào để chạy đây ?
Dùng composer bạn nhé, đôi khi bạn tham gia các dự án Laravel theo hướng Packages, Module... hoặc thì bạn sẽ băn khoăn làm thế nào để sử dụng và chạy được với cấu trúc như này, câu trả lời chính là composer và file compose.json.
Tôi muốn tạo một module chuyên hiển thị ra màn hình tôi đẹp trai.
Tôi tạo một thư mục modules/desod/handsome/notify.php
<?php
namespace Modules\Desod\Handsome;
class Notify
{
public function __construct()
{
echo 'Tôi đẹp trai';
}
}Trong đó modules là thư mục chứa các module, desod là NameSpace, handsome là SubNameSpace, notify là ClassName.
Tôi sửa file composer.json như sau:
{
"autoload":
{
"psr-4": { "modules\\": "modules/" }
}
}Sau đó tôi chạy lệnh:
composer dump-autoloadĐể nó sẽ tạo ra file autoload.php trong thư mục vendor.
File này sẽ include cả các class, namespace trong thư mục modules vào autoload của hệ thống.
Giờ đây bạn có thể sử dụng class này như sau:
<?php
//
include '/vendor/autoload.php';
new modules\desod\handsome\Notify();
hoặc
use Modules\Desod\Handsome\Notify;
Notify();Trong các framework thì phần include '/vendor/autoload.php' đã có trong code như trong Laravel là trong public/index.php
Và đó bạn có thể hiểu và tự viết lại theo cấu trúc bất kỳ nào mà bạn muốn trong dự án.