Laravel Deep Dive

Lời Nói Đầu.

Laravel là một trong những framework php nổi tiếng nhất hiện nay. Nó hỗ trợ cho lập trình viên rất nhiều trong việc tổ chức cấu trúc cho project, xử lý truy vấn dữ liệu, xử lý các tác vụ liên quan đến queue, job,, load các package cần thiết cho project... Tuy nhiên nó cũng làm cho lập trình viên không thể hiểu sâu được cách thức hoạt động của Laravel. Bài viết sẽ mở đầu seri tìm hiểu về Laravel core của mình để hiểu rõ hơn cách làm việc của Laravel. Ở bài viết này mình muốn giới thiệu về cách mà Laravel tự động phát hiện các package trong project (Package auto discovery) - một trong những tính năng mới sẽ được ra mắt trong bản Laravel 5.5 sắp tới đây.

Laravel package auto discovery.

Package trong PHP.

Như ta đã biết các ngôn ngữ lập trình khác nhau rất thường đóng gói các phần code xử lý về một tác vụ lại, sau đó có thể sử dụng được ở các phần khác trong project hoặc trong các project khác. Php cũng không ngoại lệ, như hiện nay các package của PHP thường được đẩy lên GitHub để phân phối đến các lập trình viên khác cũng nhận được sự đóng góp, phát triển thêm từ cộng đồng. Các lập trình viên có thể kéo code các package về thông qua tải mã nguồn trên GitHub hoặc một cách thông dụng hơn là qua Composer.

Composer là một tool giúp quản lý các package trong PHP. Nó cho phép lập trình viên khai báo các thư viện cần thiết cho project cũng như quản lý việc cài đặt và update các thư viện này.

Trong laravel khi cài đặt project đã có sẵn file Composer.json, là file chúng ta sẽ khai báo các package cần dùng cho project thông qua cú pháp:

{
    "require": {
        "spatie/laravel-analytics": "3.*",
    },
}

Sau đó chạy lệnh composer install để cài đặt các package đó cho project. Ngoài ra nếu cài đặt các package một cách riêng rẽ ta có thể sử dụng câu lệnh

composer require <tên package>

Các package khi được cài đặt thông qua Composer sẽ được tải về và đặt vào thư mục vendor của project. Như vậy các package đã được tải về project và có thể sử dụng được ngay. Tuy nhiên đa phần các Package đòi hỏi thêm một vài bước:

  • Đăng ký service provider.
  • Đăng ký Facade
  • Publish assets

Các bước trên nhiều khi gây khó khăn cho các lập trình viên sử dụng các package cũng như các lập trình viên phát triển các package trong quá trình cài đặt cũng như gỡ bỏ các package không cần thiết. Do đó trong bản Laravel 5.5 sắp tới package auto discovery được đưa vào giúp việc quản lý các package cho project một cách dễ dàng hơn.

Package Auto Discovery

Tính năng này được Mohamed Said - một trong những developer làm việc với laravel core team trình bày như sau: Khi lập trình viên cài đặt thông qua Composer thì có rất nhiều event được bắn ra một trong những event được sử dụng đó là post-autoload-dump. Event này được bắn ra sau khi composer sinh ra danh sách các class sẽ được load trong project. Ở event này Laravel sẽ đăng ký 2 action:

"post-autoload-dump": [
        "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
        "@php artisan package:discover"
    ]

Trước hết gọi phương thức postAutoloadDump nhằm xóa các package hoặc các service đã được cached. Sau đó chạy lệnh package:discovery. Câu lênh trên sẽ thực thi việc class Illuminate\Foundation\Console\PackageDiscoverCommand sẽ gọi phương thức build() lên class Illuminate\Foundation\PackageManifest, tại class này Laravel sẽ tiến hành phát hiện các package đã được cài đặt. Bên trong phương thức build() Laravel tìm tới file vendor/composer/installed.json được sinh ra bởi Composer giữ việc mapping với các package đã vài đặt. Laravel sẽ map nội dung của file này và tìm kiếm các trong phần extra.laravel.

"extra": {
    "laravel": {
        "providers": [
            "Barryvdh\\Debugbar\\ServiceProvider"
        ],
        "aliases": {
            "Debugbar": "Barryvdh\\Debugbar\\Facade"
        }
    }
}

Sau đó các thông tin sẽ được ghi vào một file php bootstrap/cache/packages.php có dạng:

<?php return array (
  'barryvdh/laravel-debugbar' =>
  array (
    'providers' =>
    array (
      0 => 'Barryvdh\\Debugbar\\ServiceProvider',
    ),
    'aliases' =>
    array (
      'Debugbar' => 'Barryvdh\\Debugbar\\Facade',
    ),
  ),
);

Sau khi phát hiện tất cả các package được cài đặt trong project và lưu chúng vào bootstrap/cache/packages.php , Laravel sẽ tiến hành tự động đăng ký các package này để lập trình viên có thể sử dung. Hai boostrapper được sử dụng để đăng ký Facade cũng như Service provider của các package được cài đặt bởi Composer và phát hiện bởi Laravel cho Laravel để có thể sử dụng là:

  • \Illuminate\Foundation\Bootstrap\RegisterFacades
  • \Illuminate\Foundation\Bootstrap\RegisterProviders

Đầu tiên boopstraper \Illuminate\Foundation\Bootstrap\RegisterFacades sử dụng class Illuminate\Foundation\AliasLoader để load tất cả các facades trong project, ngoài ra Laravel còn tìm trong tệp packages.php và lấy ra các alias của các package muốn Laravel đăng ký tự động và đăng ký cho project. Tất cả các alias được load từ tệp config/app.php sẽ được gộp lại với các alias được đăng ký tự động ở trên. Quá trình trên được mô tả ở dưới:

// in RegisterFacades::bootstrap()

AliasLoader::getInstance(array_merge(
    $app->make('config')->get('app.aliases', []),
    $app->make(PackageManifest::class)->aliases()
))->register();

Tương tự quá trình đăng ký service provider cũng diễn ra gần như vậy. Boostraper \Illuminate\Foundation\Bootstrap\RegisterProviders gọi đến phương thức registerConfiguredProviders() của class Foundation\Application để lấy toàn bộ các service provider cần tự động đăng ký và đăng ký chúng. Quá trình này tương được với trước đây ta khai báo service provider và allias của package trong file config/app.php, tuy nhiên chúng sẽ được diễn ra tự động bởi Laravel. Đây là tính năng rất hữu ích sẽ xuất hiện trong Laravel 5.5.

Tài liệu tham khảo.

  1. https://divinglaravel.com/package-auto-discovery
  2. https://medium.com/@taylorotwell/package-auto-discovery-in-laravel-5-5-ea9e3ab20518

All Rights Reserved