NextPDF Laravel 启动与自动探索
Laravel 会根据包自身的 composer.json 自动探索 NextPdfServiceProvider。这个 provider 会注册延迟(deferred)的容器绑定,并在 console(控制台)上下文中发布配置文件。本页逐一说明自动探索机制与每个绑定的生命周期。
composer require nextpdf/laravelphp artisan vendor:publish --tag=nextpdf-configLaravel 自动探索的工作方式
标题为“Laravel 自动探索的工作方式”的章节包会在自身 composer.json 的 extra.laravel 块中声明 provider 与 facade 别名:
{ "extra": { "laravel": { "providers": [ "NextPDF\\Laravel\\NextPdfServiceProvider" ], "aliases": { "Pdf": "NextPDF\\Laravel\\Facades\\Pdf" } } }}当你运行 composer require 时,Laravel 会读取这个块并注册 provider 与别名。你不需要手动编辑 config/app.php 或 bootstrap/providers.php。extra.laravel.providers 数组会自动注册 provider,而 extra.laravel.aliases 会自动注册 facade 别名(Laravel 12 包开发指南,
https://laravel.com/docs/12.x/packages,访问日期 2026-05-18)。
启动顺序
标题为“启动顺序”的章节NextPdfServiceProvider 同时实现 DeferrableProvider 和标准的 register() / boot() 生命周期。
register()会把包配置合并到nextpdf键之下。接着它会绑定容器条目:字体注册表、图像注册表、文档工厂、PSR-18 HTTP 客户端、timestamp 客户端、签章器、文档,以及 e-invoice 合约。每个绑定都是闭包,因此这里不会构造任何重量级对象。boot()会检查mbstring与zlib这两个 PHP 扩展是否已加载。它只会在nextpdf-config标签下注册可发布的配置,且仅当runningInConsole()为 true 时。
这个 provider 是延迟加载的,因此只有当你 resolve(解析)provides() 返回的某个条目时,register() 才会运行。解析其他无关的容器键不会启动 NextPDF。
容器绑定与生命周期
标题为“容器绑定与生命周期”的章节PSR-11 允许用相同标识符连续调用两次 get(),并按绑定策略返回不同的值(PSR-11 §1.1.2)。这个 provider 有意依赖这一特性:
| 绑定键 | 生命周期 | 备注 |
|---|---|---|
FontRegistryInterface(含 FontRegistry 别名) | 单例(singleton),预热后锁定 | 由 preload_fonts 预热;锁定后任何请求都无法更改它 |
ImageRegistry | 单例(singleton) | 由 image_cache_mb 决定容量的有界 LRU 缓存;不锁定 |
DocumentFactoryInterface(含 DocumentFactory 别名) | 单例(singleton) | 无状态;共享前述两个注册表 |
Psr\Http\Client\ClientInterface | 单例(singleton) | 带请求伪造防护的客户端,封装一个 curl 客户端;由 tsa.* 构造 |
TsaClient | 作用域(scoped) | null(当 tsa.url 为空时) |
SignerInterface | 工厂(factory) | null(当签章停用或凭证为空时) |
PdfDocumentInterface(含 nextpdf 别名) | 工厂(factory) | 每次解析都会生成全新的 NextPDF\Core\Document,并应用默认元数据 |
EmbedderInterface、ValidatorInterface、ProfileInterface、SchematronRunnerInterface | 工厂(factory) | 解析为 Premium 具体实现;首次解析时,如果缺少该包就会报错:nextpdf/premium |
文档绑定会把 defaults.creator、defaults.language,以及(非空时)defaults.author 应用到每份新建文档。当 pdfa 不为 null 时,它会启用 PDF/A(Premium)。当存在 artisan 区段且有 Chrome 浏览器工厂类时,它会应用 Chrome renderer(渲染器)配置。
has() 在容器中接受单一字符串标识符(PSR-11 §1.1.2)。e-invoice 合约已被绑定,因此即使缺少 Premium,has() 对它们仍返回 true。缺少的具体实现只会在构造时出错。
停用自动探索
标题为“停用自动探索”的章节把包加入应用的 dont-discover 数组,然后手动注册 provider:
{ "extra": { "laravel": { "dont-discover": ["nextpdf/laravel"] } }}<?php
declare(strict_types=1);
return [ App\Providers\AppServiceProvider::class, NextPDF\Laravel\NextPdfServiceProvider::class,];配置解析顺序
标题为“配置解析顺序”的章节每个键按以下顺序解析:环境变量 → 已发布的 config/nextpdf.php 值 → 在 register() 中合并的包默认值。大多数键可接受 NEXTPDF_* 名称或旧版 TCPDF_* 环境变量名称。建议优先使用 NEXTPDF_*。
php artisan package:discover --ansi输出中出现列出 nextpdf/laravel 的一行,即可确认自动探索成功。由于 provider 是延迟加载的,绑定本身要等到第一次解析后才会出现。这行探索消息才是正确的成功信号。
边界情况与陷阱
标题为“边界情况与陷阱”的章节- 配置发布只会在 console 上下文中注册,因此纯 Web 请求永远不会触发它。请从 CLI 运行
vendor:publish。 - 除了注册表、工厂、HTTP 客户端、签章器、timestamp 与文档等键之外,
provides()还包含四个 e-invoice 合约键。 - 全新安装在第一次相关解析之前,看起来可能像是没有生效。这是延迟 provider 的设计,并不是错误。
register() 是 O(1),只包含闭包。字体注册表预热的复杂度是预载字体数的 O(f),且每个 worker 进程只运行一次。延迟加载 provider 可以避免 NextPDF 的构造成本进入框架启动路径,直到实际用到某个绑定为止。
安全性备注
标题为“安全性备注”的章节延迟设计缩小了启动时的攻击面。锁定的字体注册表可以防止长生命周期 worker 中出现跨请求的字体状态变更。如需完整的威胁覆盖说明,请见 /integrations/laravel/security-and-operations/。
符合性
标题为“符合性”的章节| 主张 | 来源 | 条款 | 参考 ID(reference_id) |
|---|---|---|---|
| 连续解析可能会因绑定策略而不同 | PSR-11 容器(Container) | §1.1.2 | |
has() 接受单一字符串标识符 | PSR-11 容器(Container) | §1.1.2 |
Laravel 探索键名已对照官方 Laravel 12 包文档查证(https://laravel.com/docs/12.x/packages,访问日期 2026-05-18)。
商业场景
标题为“商业场景”的章节Premium 具体实现会通过相同的延迟绑定键来解析。这是可选的 Enterprise 能力;本页所述的 Core 包无需修改任何代码即可采用它。请见 https://nextpdf.dev/get-license/?intent=laravel-signing。
另请参阅
标题为“另请参阅”的章节- /integrations/laravel/install/ — 安装与发布
- /integrations/laravel/overview/ — 包架构
- /integrations/laravel/integration/ — 端到端接入教程
- /integrations/laravel/configuration/ — 所有配置键