ข้ามไปยังเนื้อหา

การบูตและการค้นพบอัตโนมัติของ NextPDF บน Laravel

Laravel ค้นพบ NextPdfServiceProvider โดยอัตโนมัติจาก composer.json ของแพ็กเกจ จากนั้น provider จะลงทะเบียน container binding แบบเลื่อนการสร้าง (deferred) และเผยแพร่ไฟล์การกำหนดค่าเมื่ออยู่ในบริบทคอนโซล หน้านี้อธิบายวิธีการทำงานของการค้นพบและอายุการใช้งานของ binding แต่ละรายการ

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

แพ็กเกจประกาศ provider และ facade alias ของแพ็กเกจไว้ในบล็อก extra.laravel ภายใน composer.json ของตัวเอง:

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

เมื่อรัน composer require Laravel จะอ่านบล็อกนี้แล้วลงทะเบียน provider และ alias จึงไม่ต้องแก้ไข config/app.php หรือ bootstrap/providers.php ด้วยตนเอง อาร์เรย์ extra.laravel.providers จะลงทะเบียน service provider โดยอัตโนมัติ และ extra.laravel.aliases จะลงทะเบียน facade alias โดยอัตโนมัติ (คู่มือการพัฒนาแพ็กเกจของ Laravel 12, https://laravel.com/docs/12.x/packages สืบค้นเมื่อ 2026-05-18)

NextPdfServiceProvider ใช้งาน DeferrableProvider พร้อม register() / boot() ซึ่งเป็นวงจรชีวิตมาตรฐาน

  1. register() ผสานการกำหนดค่าของแพ็กเกจไว้ภายใต้คีย์ nextpdf จากนั้น bind รายการใน container ได้แก่ font registry, image registry, document factory, ไคลเอนต์ Hypertext Transfer Protocol (HTTP) ตาม PHP Standards Recommendation 18 (PSR-18), ไคลเอนต์ timestamp, signer, document และสัญญา e-invoice ทุก binding เป็น closure จึงยังไม่สร้างองค์ประกอบที่ใช้ทรัพยากรมากในจุดนี้
  2. boot() ตรวจสอบว่าโหลดส่วนขยาย PHP mbstring และ zlib แล้วหรือไม่ และลงทะเบียนการกำหนดค่าที่เผยแพร่ได้ภายใต้แท็ก nextpdf-config เฉพาะเมื่อ runningInConsole() เป็น true เท่านั้น

เนื่องจาก provider เป็นแบบเลื่อนการสร้าง register() จะทำงานเฉพาะเมื่อมีการ resolve รายการใดรายการหนึ่งที่ provides() ส่งคืน การ resolve คีย์ของ container ที่ไม่เกี่ยวข้องจะไม่ทำให้ NextPDF บูต

PHP Standards Recommendation 11 (PSR-11) อนุญาตให้การเรียก get() สองครั้งติดกันด้วยตัวระบุเดียวกันส่งคืนค่าที่ต่างกันได้ ขึ้นอยู่กับกลยุทธ์การ bind (PSR-11 §1.1.2) provider จงใจอาศัยพฤติกรรมนี้ในการออกแบบ:

คีย์ของ bindingอายุการใช้งานหมายเหตุ
FontRegistryInterface (+ alias FontRegistry)singleton ล็อกหลังจาก warmupwarmup จาก preload_fonts แล้วล็อกไว้เพื่อไม่ให้คำขอใดเปลี่ยนแปลงได้
ImageRegistrysingletonแคชแบบ least recently used (LRU) ที่จำกัดขนาด โดยกำหนดจาก image_cache_mb และไม่ได้ล็อก
DocumentFactoryInterface (+ alias DocumentFactory)singletonไม่มีสถานะ ใช้ registry ทั้งสองตัวร่วมกัน
Psr\Http\Client\ClientInterfacesingletonไคลเอนต์ที่คำนึงถึงการปลอมแปลงคำขอ (request forgery) ซึ่งห่อหุ้มไคลเอนต์ curl และสร้างจาก tsa.*
TsaClientscopednull เมื่อ tsa.url ว่างเปล่า
SignerInterfacefactorynull เมื่อปิดใช้งานการลงนามหรือใบรับรองว่างเปล่า
PdfDocumentInterface (+ alias nextpdf)factoryอินสแตนซ์ NextPDF\Core\Document ใหม่ทุกครั้งที่ resolve พร้อมใช้ค่าเมทาดาทาเริ่มต้น
EmbedderInterface, ValidatorInterface, ProfileInterface, SchematronRunnerInterfacefactoryจะ resolve ไปยังคอนกรีตของ Premium และจะเกิดข้อผิดพลาดในการ resolve ครั้งแรกหากไม่มี nextpdf/premium

binding ของ document จะใช้ defaults.creator, defaults.language และใช้ defaults.author กับเอกสารใหม่แต่ละฉบับเมื่อค่านั้นไม่ว่างเปล่า เมื่อ pdfa ไม่เป็น null จะเปิดใช้งาน PDF/A (Premium) หากมีส่วน artisan และมีคลาส browser-factory ของ Chrome อยู่ ระบบจะใช้การกำหนดค่าตัวเรนเดอร์ Chrome

has() บน container รับตัวระบุที่เป็นสตริงเดียว (PSR-11 §1.1.2) สัญญา e-invoice ถูก bind ไว้แล้ว ดังนั้น has() จะส่งคืน true สำหรับสัญญาเหล่านั้นแม้ไม่มี Premium ส่วนคอนกรีตที่ขาดหายไปจะเกิดข้อผิดพลาดเมื่อสร้างเท่านั้น

เพิ่มแพ็กเกจลงในอาร์เรย์ dont-discover ของแอปพลิเคชัน จากนั้นลงทะเบียน provider ด้วยตนเอง:

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,
];

คีย์แต่ละรายการจะ resolve ตามลำดับนี้: ตัวแปรสภาพแวดล้อม → ค่าจาก config/nextpdf.php ที่เผยแพร่แล้ว → ค่าเริ่มต้นของแพ็กเกจที่ผสานใน register() คีย์ส่วนใหญ่รองรับได้ทั้งชื่อ NEXTPDF_* หรือชื่อตัวแปรสภาพแวดล้อมแบบเดิม TCPDF_* แนะนำให้ใช้ NEXTPDF_* แทน

Terminal window
php artisan package:discover --ansi

บรรทัดที่แสดงรายการ nextpdf/laravel เป็นการยืนยันว่าการค้นพบทำงาน เนื่องจาก provider เป็นแบบเลื่อนการสร้าง binding เองจะยังไม่ปรากฏจนกว่าจะ resolve ครั้งแรก บรรทัดการค้นพบจึงเป็นสัญญาณความสำเร็จที่ถูกต้อง

  • การเผยแพร่การกำหนดค่าจะลงทะเบียนเฉพาะในบริบทคอนโซล ดังนั้นคำขอที่เป็นเว็บเท่านั้นจะไม่ทริกเกอร์ ให้รัน vendor:publish จาก command-line interface (CLI)
  • นอกเหนือจากคีย์ registry, factory, ไคลเอนต์ HTTP, signer, timestamp และ document แล้ว provides() ยังรวมคีย์สัญญา e-invoice ทั้งสี่คีย์ด้วย
  • การติดตั้งใหม่อาจดูเหมือนยังไม่ทำงานจนกว่าจะมีการ resolve ที่เกี่ยวข้องครั้งแรก นี่คือการออกแบบ provider แบบเลื่อนการสร้าง ไม่ใช่ข้อผิดพลาด

register() เป็น O(1) เนื่องจากสร้างเฉพาะ closure เท่านั้น การ warmup ของ font registry เป็น O(f) ตามจำนวนฟอนต์ที่โหลดล่วงหน้า และทำงานครั้งเดียวต่อกระบวนการ worker การเลื่อนการสร้าง provider ช่วยให้ต้นทุนการสร้าง NextPDF ไม่อยู่ในเส้นทางการบูตของเฟรมเวิร์กจนกว่าจะมีการใช้ binding จริง

การออกแบบแบบเลื่อนการสร้างช่วยลดพื้นผิวการโจมตีในช่วงบูต font registry ที่ล็อกไว้จะป้องกันไม่ให้คำขอหนึ่งเปลี่ยนสถานะฟอนต์ของอีกคำขอหนึ่งใน worker ที่มีอายุยาวนาน สำหรับความครอบคลุมของภัยคุกคามทั้งหมด ดู /integrations/laravel/security-and-operations/

ข้อยืนยันแหล่งที่มาข้อกำหนดรหัสอ้างอิง (reference_id)
ผลการ resolve ติดต่อกันอาจต่างกันได้ตามกลยุทธ์การ bindPSR-11 Container§1.1.2
has() รับตัวระบุที่เป็นสตริงเดียวPSR-11 Container§1.1.2

เอกสารแพ็กเกจอย่างเป็นทางการของ Laravel 12 ยืนยันชื่อคีย์สำหรับการค้นพบของ Laravel (https://laravel.com/docs/12.x/packages สืบค้นเมื่อ 2026-05-18)

คอนกรีตของ Premium จะ resolve ผ่านคีย์ binding แบบเลื่อนการสร้างชุดเดียวกัน ความสามารถ Enterprise เพิ่มเติมนี้ไม่ต้องเปลี่ยนแปลงโค้ดในแพ็กเกจ Core ที่ระบุไว้ในเอกสารนี้ ดู https://nextpdf.dev/get-license/?intent=laravel-signing เพื่อรับใบอนุญาต

  • /integrations/laravel/install/ — ติดตั้งและเผยแพร่
  • /integrations/laravel/overview/ — สถาปัตยกรรมของแพ็กเกจ
  • /integrations/laravel/integration/ — คู่มือการเชื่อมต่อแบบครบวงจร
  • /integrations/laravel/configuration/ — ทุกคีย์การกำหนดค่า