PSR-4: A new specs for autoloader

Sep 20, 2020

I. Giới thiệu

Như giới thiệu trong post trước PSR-0 đã bị không còn được khuyến nghị sử dụng mà thay vào đó là chuẩn mới với tên PSR-4 cho autoloader. Trên thực tế PSR-4 là một chuẩn hoàn toàn có khả năng tương tác và làm việc cùng các chuẩn autoloader khác kể cả PSR-0. PSR-4 môt tả một đặc tả cho việc tự động load các lớp từ đường dẫn và nó cũng mô tả nơi đặt file để lớp có thể được tự động load.

II. Specifications

  • Cụm từ "class"  trong đặc tả được hiểu với ý nghĩa tham chiếu tới các lớp, interface, traits và các cấu trúc tương tự
  • Một tên lớp đầy đủ sẽ có hình thức như sau :
 \<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
  • Tên lớp đầy đủ PHẢI có một top-level name space được gọi là "vendor namespace"
  • Một tên lớp đầy đủ có thể có một hoặc nhiều tên sub-namespace
  • Một tên lớp đầy đủ phải kết thúc bởi một class
  • Dấu gạch dưới _ không có ý nghĩa đặc biệt trong tên lớp đầy đủ
  • Các ký tự alphabet trong tên lớp đầy đủ có thể là bất cứ sự kết hợp nào của ký tự hoa và thường
  • Tất cá các tên lớp PHẢI được tham chiếu theo cách phân biệt chữ hoa chữ thường.
  • Khi load một file tương ứng với một tên lớp đầy đủ :

   – Một chuỗi liên tục của một hoặc nhiều namespace và sub namespace không bao gồm ký tự phân cách trong phần đầu một tên lớp đầy đủ (prefix namespace) sẽ tương ứng với một đường dẫn cơ sở (base directory)

App\Repositories\UserRepository  sẽ có phần đầu "App\" tương ứng đường dẫn cơ sở /app

Quan sát trong file composer có thể thấy base directory được định nghĩa như sau. Bạn có thể hoàn toàn định nghĩa thêm nếu cần.

"autoload": {
    "psr-4": {
        "App\\": "app/"
    },
 }

   – Chuỗi liên tục các sub-namespace sau prefix namespace sẽ tương ứng với cấu trúc thư mục con bên trong đường dẫn cơ bản với dấu phân cách namespace được dịch sang tương ứng dấu phân cách đường dẫn thư mục. Tên thư mục PHẢI trung với tên của sub-namespace tương ứng.

Ví dụ : Như ví dụ trên phần sau namespace prefix "App" là Repositories sẽ tương ứng với thư mục con Repositories trong thư mục "app/"

  – Tên class kết thúc sẽ tương ứng với tên file kết thúc bởi .php. Tên file PHẢI trùng với tên lớp kết thúc phân biệt chữ hoa-thường

Ví dụ: trong ví dụ trên UserRepository là tên lớp kết thúc và thực tế tương ứng với file UserRepository.php trong thư mục Repositories là thư mục con của thư mục app (base directory)

 – Autoloader phải không được ném ra ngoại lệ, không được raise error ở bất cứ level nào và không nên trả về giá trị.

Q : Tại sao ?
A: Vì như trong PSR-0 đã nói, autoloader không còn là 1 hàm mà là 1 chuỗi hàm và nếu một autoloader lỗi thì các autoloader khác vẫn nên được có cơ hội hoạt động tiếp, trong khi đó việc ném ra ngoại hoặc raise exceptions sẽ tước đi cơ hội này của các autoloader phía sau.

III. So sánh với PSR-0

  • PSR-0 không có khái niệm prefix namespace nên cấu trúc đường dẫn sẽ tương ứng với cấu trúc namespace (kiểu đường dẫn tuyệt đối ) . Trong khi đó PSR-4 cho phép định nghĩa prefix namespace và từ đó cho phép tên namespace sẽ tương ứng với "đường dẫn tương đối" bên trong dường dẫn được tham chiếu tới bởi prefix namespace.
  • Dấu _ trong PSR-0 có ý nghĩa đặc biệt còn trong PSR-4 thì không.
  • PSR-4 cũng quy ước thêm các autoloader không throw exception hay lỗi cũng như không nên trả về value.

VI. Autoloading trong Laravel

Xem file composer.json trong laravel ta sẽ thấy Laravel đang implement PSR-4

"autoload": {
    "psr-4": {
        "App\\": "app/"
    },
 }

Khi thêm các lớp mới trong classmap chạy composer dump-autoload thì composer sẽ duyệt composer.json để update list các class cần được autoload. Bạn có thể xem các list rule autoload trong thư composer theo pattern sau  vendor/composer/autoload_*.php

Như bạn có thể nhận thấy do các autoloader không trả về value hay throw exception trong khi để load được class thì file tương ứng trong đường dẫn phải tồn tại nên thông thường các autoloader phải check sự tồn tại của các file này trước khi tiến hành load. Việc check này khá tốn thời gian và làm chậm hiệu năng ứng dụng trên production. Chính vì vậy bạn có thể optimize công việc này thông qua lệnh `composer dump-autoload --optimize` để tạo ra autoload_classmap với sự tồn tại của file đã được composer check trước nên ứng dụng chỉ cần load mà không cần phải check lại.

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.