PSR-0 vs PSR-4: Các chuẩn Autoload file
This post hasn't been updated for 6 years
Nếu như các bạn quá quen thuộc với các chuẩn PSR-1, PSR-2 là các chuẩn code convention thì dường như lại không ai để ý mấy đến chuẩn autoload file PSR-0 và PSR-4. Hai chuẩn này là chuẩn load file được sử dụng trong composer
, trong bài viết mình sẽ lấy ví dụ để so sánh 2 chuẩn này.
Note:
- Bài viết mang tính chất bổ sung ví dụ về PSR-0 và PSR-4 cho bài viết chi tiết này
- Bài viết chỉ là các ví dụ để "chứng minh": "Sự khác biệt chủ yếu của PSR-0 so với PSR-4 đó là, PSR-0 không có khái niệm namespace prefix nên cấu trúc namespace sẽ tương ứng với cấu trúc thư mục chứa class"
1. Giới thiệu
-
Các chuẩn PSR-1 và PSR-2 các bạn có thể tham khảo tại đây đây
-
Autoaloading là gì?: Bạn có để ý là khi đọc về PHP thuần, muốn sử dụng source code từ file khác, người ta cần
include
orrequire
, làm một cách thủ công. Đó là vì bạn chưa biết autoload @@. Autoload sẽ thực hiện một cách tự độngrequire
,include
cho bạn thông qua cácmagic method
, cácfunction
. Chi tiết bạn có thể xem các magic method nào và hàm nào có thể đọc tại đây - quá chi tiết (len) -
Nếu bạn đọc ở đâu đó, người ta khuyên bạn sử dụng
composer
thì nên sử dụng PSR-4 và quên đi PSR-0 đi, vì sao lại vậy, ta thử xem xét ví dụ sau nhé -
Đường dẫn các thư mục (mình giữ nguyên thư mục của bài Viblo mình thao khảo). Ta sẽ xem xét việc
require
các file trong các đường dẫn Controllers, Models, Views vàoindex.php
như thế nào với 2 chuẩn kia nhé
.
├── composer.json
├── index.php
└── src
├── Controllers
│ └── HomeController.php
├── Models
│ └── User.php
└── Views
└── home.php
2. PSR-0
Nếu sử dụng PSR-0, không cho phép sử dụng namespace prefix, vì vậy bạn phải tạo đường dẫn đúng cho thư mục của bạn.
File HomeController.php
:
<?php
namespace Controllers;
use Models\User;
class HomeController
{
public function actionIndex()
{
return (new User)->list();
}
}
File User.php
<?php
namespace Models;
class User
{
public function list()
{
// TODO: get actual data
return [1, 2, 3];
}
}
File composer.json
{
"autoload": {
"psr-0": {
"Controllers\\HomeController": "src/",
"Models\\User" : "src/"
}
}
}
File index.php
<?php
require __DIR__ . '/vendor/autoload.php';
use Controllers\HomeController;
$homeCtrl = new HomeController;
print_r($homeCtrl->actionIndex());
Tiến hành chạy autoload:
$ composer dump-autoload
Chạy file index.php để test
$ php index.php
Và tất nhiên kết quả là OK. Tuy nhiên bạn để ý thấy file composer.json khá phức tạp.
Bây giờ bài toán đặt ra là giả sử giờ bạn muốn thêm 1 lớp có đường dẫn khác các đường dẫn sẵn có, chẳng hạn Repositories như sau:
.
├── composer.json
├── index.php
└── src
├── Controllers
│ └── HomeRepository.php
├── Repositories
│ └── HomeController.php
├── Models
│ └── User.php
└── Views
└── home.php
File HomeRepository.php
<?php
namespace Repositories;
class HomeRepository
{
public function hello()
{
echo "Hello, I am Minh";
}
}
Lúc đó, bạn cần cập nhật composer.json
lại như sau đê file index.php có thể sử dụng được:
{
"autoload": {
"psr-0": {
"Controllers\\HomeController": "src/",
"Models\\User" : "src/",
"Repositorirs\\Repository": "src/", }
}
}
Thêm 10 lớp hay 100 lớp, cập nhật composer.json
mệt phết nhể :3.
3. PSR-4
Để khắc phục nhược điểm phải cập nhật composer.json
như trên, giờ ta sẽ chuyển sang dùng chuẩn PSR-4 với namespace prefix để giải quyết vấn đề.
File composer.json sử dụng PSR-4 sẽ như sau:
{
"autoload": {
"psr-4": {
"Viblo\\": "src/"
}
}
}
Với các lớp được viết lại (sử dụng namespace prefix: Viblo)
File HomeController.php
:
<?php
namespace Viblo\Controllers;
use Viblo\Models\User;
class HomeController
{
public function actionIndex()
{
return (new User)->list();
}
}
File User.php
<?php
namespace Viblo\Models;
class User
{
public function list()
{
// TODO: get actual data
return [1, 2, 3];
}
}
Khi đó thêm với HomeRepository, chỉ cần đặt namespace prefix
Viblo cho lớp này là được mà không cần cập nhật composer.json
=> đơn giản và thuận tiện hơn khá nhiều.
File HomeRepository.php
sẽ như sau:
<?php
namespace Viblo\Repositories;
class HomeRepository
{
public function hello()
{
echo "Hello, I am Minh";
}
}
File index.php
để test sẽ như sau:
<?php
require __DIR__ . '/vendor/autoload.php';
use Viblo\Controllers\HomeController;
use Viblo\Repositories\HomeRepository;
$homeCtrl = new HomeController;
$homeRps = new HomeRepository;
print_r($homeCtrl->actionIndex());
$homeRps->hello(); // Hello, I am Minh - vì đã được load thành công
?>
Tổng kết
Qua ví dụ trên hi vọng các bạn có thể thấy được sự khác biệt khá rõ rệt của PSR-0 và PSR-4 và hãy quên PSR-0 đi :3
Tài liệu tham khảo
All Rights Reserved