Chúng ta sẽ thảo luận riêng về chủ đề Autoload optimizing PHP Autoloading, PSR4 and Composer (ok)

https://viblo.asia/p/php-autoloading-psr4-and-composer-V3m5Wy0QZO7

C:\xampp\htdocs\test\composer.json

{
  "autoload": {
    "psr-4": {
      "Viblo\\": "src/"
    }
  }
}

C:\xampp\htdocs\test\src\Controllers\HomeController.php

<?php
namespace Viblo\Controllers;

use Viblo\Models\User;

class HomeController
{
  public function actionIndex()
  {
    return (new User)->list();
  }
}

C:\xampp\htdocs\test\src\Models\User.php

<?php
namespace Viblo\Models;

class User
{
    public function list()
    {
        // TODO: get actual data
        return [1, 2, 3];
    }
}

C:\xampp8\htdocs\testauth\index.php

<?php
require __DIR__ . '/vendor/autoload.php';
use Viblo\Controllers\HomeController;
$homeCtrl = new HomeController;
print_r($homeCtrl->actionIndex());

Autoload optimizing

Với các quy tắc PSR-0, PSR-4, autoloader cần phải check sự tồn tại của class file trong filesystem trước khi load class. Việc này có thể làm chậm tốc độc của application một chút, nhưng bù lại nó làm cho việc develop dễ dàng hơn khi bạn thêm một class và có thể sử dụng nó ngay lập tức mà không phải rebuild autoloader.

Vấn đề ở đây là, trong môi trường production, bạn thường muốn app của mình chạy nhanh nhất có thể, vì môi trường này ít khi thay đổi và bạn có thể dễ dàng rebuild lại autoloader khi deploy.

Vì lý do này, Composer cung cấp vài phương pháp để optimize autoloader. Mình sẽ giới thiệu 1 phương pháp thường được sử dụng nhất.

Trước

Thiết lập trong file composer.json

{
  "autoload": {
    "psr-4": {
      "Viblo\\": "src/"
    }
  },
  "config": {
    "optimize-autoloader": true
  }
}

Sau chạy lệnh

composer update -o 

Nó hoạt động như thế nào?

Composer sẽ convert các rule PSR-4/PSR-0 sang classmap rule. Các bạn có thể xem file vendor/composer/autoload_classmap.php để kiểm tra. File này sẽ return một array, có key là tên class đầy đủ và value là đường dẫn đến class. Composer đã check sự tồn tại của các class này trước và generate ra classmap, do đó, khi tham chiếu đến class thì autoloader chỉ việc require file vào không cần phải check filesystem nữa.

Với PHP 5.6+, Composer còn thực hiện cache classmap trong opcache, làm cho việc load class có thể chạy nhanh nhất có thể.

Nhược điểm

Không có nhược điểm thực sự với phương pháp này, và bạn nên luôn luôn dùng nó trong môi trường production.

Một vấn đề nhỏ với ở đây là, nếu class không tồn tại trong classmap, nó sẽ có fallback về PSR-4 rule, tức là tiếp tục follow theo PSR-4 rule và có thể phát sinh filesystem check.

Để giải quyết vấn đề này Composer cung cấp thêm 2 phương pháp optimize level 2 đó là Level 2/A: Authoritative class maps (loại bỏ fallback về PSR-4 rule) và Level 2/B: APCu cache (sử dụng apcu cache). Hai option level 2 này không thể được sử dụng cùng 1 lúc và cũng ít được sử dụng.

Ngoài ra còn 1 vấn đề nữa mình phát hiện trong quá trình tham gia một project, đó là khi sử dụng optimize thì rule PSR-4 sẽ không được đảm bảo về ràng buộc giữa class namespaces và thư mục chứa class. Tức là, vd 1 class là App\User nhưng lại được đặt trong thư mục khác, chẳng hạn app/Http/Models/User.php thay vì app/User.php.

Đây cũng không phải là vấn đề lớn và vẫn đang được thảo luận, các bạn có thể theo dõi tại issue này.

Last updated