Bỏ qua để đến nội dung

Khởi động và tự động phát hiện NextPDF trong Laravel

Laravel tự động phát hiện NextPdfServiceProvider từ tệp composer.json của gói. Provider đăng ký các container binding dạng hoãn lại và xuất bản tệp cấu hình trong ngữ cảnh console. Trang này giải thích cơ chế phát hiện đó hoạt động ra sao và vòng đời của từng binding.

Terminal window
composer require nextpdf/laravel
php artisan vendor:publish --tag=nextpdf-config

Cách hoạt động của tính năng tự động phát hiện của Laravel

Phần tiêu đề “Cách hoạt động của tính năng tự động phát hiện của Laravel”

Gói khai báo provider và facade alias trong khối extra.laravel của chính tệp composer.json:

resource: composer.json (extra.laravel)
{
"extra": {
"laravel": {
"providers": [
"NextPDF\\Laravel\\NextPdfServiceProvider"
],
"aliases": {
"Pdf": "NextPDF\\Laravel\\Facades\\Pdf"
}
}
}
}

Khi bạn chạy composer require, Laravel đọc khối này rồi đăng ký provider và alias. Bạn không cần chỉnh sửa thủ công config/app.php hoặc bootstrap/providers.php. Mảng extra.laravel.providers tự động đăng ký các service provider, còn extra.laravel.aliases tự động đăng ký các facade alias (hướng dẫn phát triển gói Laravel 12, https://laravel.com/docs/12.x/packages, truy cập ngày 2026-05-18).

NextPdfServiceProvider triển khai DeferrableProvider và vòng đời tiêu chuẩn register() / boot().

  1. register() gộp cấu hình của gói vào khóa nextpdf. Sau đó, phương thức này đăng ký binding cho các mục container: font registry, image registry, document factory, PHP Standards Recommendation 18 (PSR-18) Hypertext Transfer Protocol (HTTP) client, timestamp client, signer, document, và các e-invoice contract. Mỗi binding là một closure, nên không có thành phần nặng nào được khởi tạo tại đây.
  2. boot() kiểm tra xem các PHP extension mbstringzlib đã được nạp hay chưa. Phương thức này chỉ đăng ký cấu hình có thể xuất bản dưới thẻ nextpdf-config khi runningInConsole() là true.

Vì provider được hoãn lại, register() chỉ chạy khi bạn resolve một trong các mục mà provides() trả về. Việc resolve một khóa container không liên quan sẽ không khởi động NextPDF.

PHP Standards Recommendation 11 (PSR-11) cho phép hai lệnh gọi get() liên tiếp với cùng một định danh trả về các giá trị khác nhau tùy theo chiến lược binding (PSR-11 §1.1.2). Provider chủ động dựa trên hành vi này:

Khóa bindingVòng đờiGhi chú
FontRegistryInterface (+ alias FontRegistry)singleton, khóa sau khi khởi động nóngĐược khởi động nóng từ preload_fonts; đã khóa nên không request nào có thể thay đổi nó
ImageRegistrysingletonBộ nhớ đệm least recently used (LRU) có giới hạn, kích thước theo image_cache_mb; không bị khóa
DocumentFactoryInterface (+ alias DocumentFactory)singletonKhông trạng thái; dùng chung hai registry
Psr\Http\Client\ClientInterfacesingletonClient có cơ chế nhận biết tấn công giả mạo request, bao bọc một curl client; được tạo từ tsa.*
TsaClientscopednull khi tsa.url rỗng
SignerInterfacefactorynull khi tắt ký hoặc chứng chỉ rỗng
PdfDocumentInterface (+ alias nextpdf)factoryTạo mới NextPDF\Core\Document cho mỗi lần resolve, đã áp dụng metadata mặc định
EmbedderInterface, ValidatorInterface, ProfileInterface, SchematronRunnerInterfacefactoryResolve thành các lớp cụ thể của Premium; báo lỗi ở lần resolve đầu tiên nếu thiếu nextpdf/premium

Binding của document áp dụng defaults.creator, defaults.language, và, khi không rỗng, defaults.author cho mỗi tài liệu mới. Khi pdfa khác null, binding này bật PDF/A (Premium). Khi có phần artisan và lớp browser-factory của Chrome tồn tại, nó áp dụng cấu hình bộ kết xuất Chrome.

has() trên container nhận một định danh chuỗi duy nhất (PSR-11 §1.1.2). Các e-invoice contract đã có binding, nên has() trả về true cho chúng ngay cả khi không có Premium. Lớp cụ thể bị thiếu chỉ gây lỗi tại thời điểm khởi tạo.

Thêm gói vào mảng dont-discover của ứng dụng, rồi đăng ký provider theo cách thủ công:

resource: application composer.json
{
"extra": {
"laravel": {
"dont-discover": ["nextpdf/laravel"]
}
}
}
resource: bootstrap/providers.php
<?php
declare(strict_types=1);
return [
App\Providers\AppServiceProvider::class,
NextPDF\Laravel\NextPdfServiceProvider::class,
];

Mỗi khóa được phân giải theo thứ tự này: biến môi trường → giá trị config/nextpdf.php đã xuất bản → giá trị mặc định của gói đã được gộp tại register(). Hầu hết các khóa chấp nhận một tên NEXTPDF_* hoặc tên biến môi trường cũ TCPDF_*. Nên ưu tiên NEXTPDF_*.

Terminal window
php artisan package:discover --ansi

Một dòng liệt kê nextpdf/laravel xác nhận việc phát hiện. Vì provider được hoãn lại, các binding chỉ xuất hiện sau lần resolve đầu tiên. Dòng phát hiện đó là tín hiệu thành công phù hợp.

Trường hợp đặc biệt và điểm cần lưu ý

Phần tiêu đề “Trường hợp đặc biệt và điểm cần lưu ý”
  • Việc xuất bản cấu hình chỉ được đăng ký trong ngữ cảnh console, nên một request web đơn thuần sẽ không bao giờ kích hoạt nó. Chạy vendor:publish từ giao diện dòng lệnh (CLI).
  • Bên cạnh các khóa registry, factory, HTTP client, signer, timestamp, và document, provides() còn bao gồm bốn khóa e-invoice contract.
  • Một bản cài mới có thể trông như chưa hoạt động cho đến lần resolve liên quan đầu tiên. Đây là thiết kế provider hoãn lại, không phải lỗi.

register() là O(1) vì nó chỉ tạo các closure. Quá trình khởi động nóng font registry là O(f) theo số phông chữ được nạp trước và chạy một lần cho mỗi worker process. Việc hoãn lại provider giữ chi phí khởi tạo NextPDF nằm ngoài đường khởi động của framework cho đến khi một binding thực sự được dùng.

Thiết kế hoãn lại thu hẹp bề mặt tấn công tại thời điểm khởi động. Font registry bị khóa để ngăn một request thay đổi trạng thái phông chữ của request khác trong các worker tồn tại lâu dài. Để bao quát đầy đủ các mối đe dọa, xem /integrations/laravel/security-and-operations/.

Tuyên bốNguồnĐiều khoảnreference_id
Các lần phân giải liên tiếp có thể khác nhau tùy theo chiến lược bindingPSR-11 Container§1.1.2
has() nhận một định danh chuỗiPSR-11 Container§1.1.2

Tài liệu chính thức về gói của Laravel 12 xác nhận tên các khóa phát hiện của Laravel (https://laravel.com/docs/12.x/packages, truy cập ngày 2026-05-18).

Các lớp cụ thể của Premium được phân giải qua cùng các khóa binding hoãn lại đó. Tính năng Enterprise tùy chọn này không cần thay đổi mã trong gói Core được mô tả ở đây. Xem https://nextpdf.dev/get-license/?intent=laravel-signing.

  • /integrations/laravel/install/ — cài đặt và xuất bản
  • /integrations/laravel/overview/ — kiến trúc gói
  • /integrations/laravel/integration/ — hướng dẫn tích hợp từ đầu đến cuối
  • /integrations/laravel/configuration/ — mọi khóa cấu hình