扩展开发:公开 SPI 概览
NextPDF 对外开放一组精简且经过刻意设计的公开契约,全部位于 NextPDF\Contracts 与 NextPDF\Event 这两个命名空间(namespace)中。实现这些契约后,你就能添加字体、拦截文本、观察文档生命周期,或提供自己的签名后端(backend),而无需 fork 整个引擎。
composer require nextpdf/core:^3概念总览
标题为“概念总览”的章节NextPDF 将其**公开服务提供方接口(SPI)**与内部代码分离。SPI 由一组类型构成,供你实现或观察。其余内容均为私有,可能在不另行通知的情况下变动。
公开 SPI 有三种形态:
- **注册表契约。**这是进程生命周期级别的服务,你需要在创建文档之前完成配置;
FontRegistryInterface与ImageRegistryInterface是主要例子。你负责注册这些资源,引擎随后读取它们。 - **策略契约。**这是引擎在渲染过程中调用的一次性任务钩子。
TextPreprocessorInterface负责布局阶段的文本拦截,而HtmlSecurityPolicyInterface用于管控 HTML 功能。你提供行为,引擎负责驱动它。 - **签名契约。**这是密码学后端(backend)。
SignerInterface、HsmSignerInterface与DeferredSignerInterface让你自行提供密钥托管与签名生成能力。引擎负责构建 CMS 结构,而你的代码持有密钥。
观察能力则由 NextPDF\Event 中一套独立、兼容于 PSR-14 的事件系统负责。生命周期事件让你能对文档创建、新页面、字体加载、签名与写出做出响应。它们不会改变引擎的行为。
每个契约在其源代码的 PHPDoc 中都带有一个 @stability 标签:stable(稳定)、experimental(实验性)或 deprecated(已弃用)。这个标签会结合每个契约各自的向后兼容承诺,说明你应预期多大程度的变动。完整策略请见 SPI 稳定性规则一节。
哪些部分可扩展
标题为“哪些部分可扩展”的章节| 功能 | 公开契约 | 稳定性 |
|---|---|---|
| 字体注册与查找 | NextPDF\Contracts\FontRegistryInterface | 稳定(自 1.7.0 起) |
| 图像缓存与解码 | NextPDF\Contracts\ImageRegistryInterface | 稳定(自 2.0.0 起) |
| 布局阶段的文本拦截 | NextPDF\Contracts\TextPreprocessorInterface | 稳定(自 1.9.0 起) |
| HTML 功能管控 | NextPDF\Contracts\HtmlSecurityPolicyInterface | 稳定(自 3.1.0 起) |
| 文档工厂装配 | NextPDF\Contracts\DocumentFactoryInterface | 稳定(自 1.7.0 起) |
| 同步签名 | NextPDF\Contracts\SignerInterface | 稳定(自 1.0.0 起) |
| 硬件后端签名 | NextPDF\Contracts\HsmSignerInterface | 稳定(自 1.0.0 起) |
| 延后签名与批量签名 | NextPDF\Contracts\DeferredSignerInterface | 实验性(自 3.0.0 起) |
| RFC 3161 时间戳 | NextPDF\Contracts\TimestampProviderInterface | 实验性(自 3.0.0 起) |
| 生命周期观察 | NextPDF\Event\*(兼容于 PSR-14) | 调度器稳定;载荷为实验性 |
哪些部分不属于公开
标题为“哪些部分不属于公开”的章节以下内容均属于内部。请勿导入、继承或依赖它们:
- 任何位于
NextPDF\Contracts与NextPDF\Event命名空间以外的类,除非其 PHPDoc 带有@stability标签。 - 具体的引擎代码,例如 HTML 解析器、写出器、布局流水线与字体子集化器。
- NextPDF Pro 与 NextPDF Enterprise 包。它们的内部类并不属于开源的对外范围。当付费版本随附一份 SPI 实现时,你使用的是公开契约,而不是它的内部类型。
API 接口范围
标题为“API 接口范围”的章节最具权威性的清单是自动生成的契约对照表。它会在每次发布时从源代码重新生成。请把每个接口文件中的 @stability PHPDoc 标签当作唯一可信来源。上表仅用于辅助阅读。
代码示例 —— 快速上手
标题为“代码示例 —— 快速上手”的章节先注册字体,再观察它何时加载。这两个步骤都只使用公开类型。
<?php
declare(strict_types=1);
use NextPDF\Contracts\FontRegistryInterface;use NextPDF\Event\Content\FontLoadedEvent;use NextPDF\Event\EventDispatcher;use NextPDF\Event\ListenerProvider;
/** @var FontRegistryInterface $fonts */$fonts->register('/srv/fonts/Inter-Regular.ttf', 'Inter');
$listeners = new ListenerProvider();$listeners->addListener( FontLoadedEvent::class, static function (FontLoadedEvent $event): void { \error_log("Font loaded: {$event->family} {$event->style}"); },);
$dispatcher = new EventDispatcher($listeners);代码示例 —— 生产环境
标题为“代码示例 —— 生产环境”的章节对于长时间运行的 worker(工作进程),请在启动时一次性创建并锁定这些注册表,再通过文档工厂注入共享的调度器。
<?php
declare(strict_types=1);
use NextPDF\Contracts\DocumentFactoryInterface;use NextPDF\Contracts\FontRegistryInterface;use NextPDF\Event\EventDispatcher;use NextPDF\Event\ListenerProvider;use Psr\Log\LoggerInterface;
final class DocumentBootstrap{ public function __construct( private readonly FontRegistryInterface $fonts, private readonly DocumentFactoryInterface $factory, private readonly LoggerInterface $logger, ) {}
public function warmup(): EventDispatcher { $this->fonts->warmup([ '/srv/fonts/Inter-Regular.ttf', '/srv/fonts/Inter-Bold.ttf', ]); $this->fonts->lock();
$listeners = new ListenerProvider(); $listeners->addListener( \NextPDF\Event\Security\SignatureAppliedEvent::class, fn (object $event): mixed => $this->logger->info('Signature applied'), );
return new EventDispatcher($listeners); }}边界情况与陷阱
标题为“边界情况与陷阱”的章节- **注册表锁定。**在调用
FontRegistryInterface::lock()之后,会变更状态的方法会抛出LogicException。请仅在预热完成后锁定。 - **稳定性不一致。**标注为
experimental的契约可能在次要版本中变动。在生产环境依赖某个契约之前,请先确认它声明的稳定性。 - **命名空间纪律。**位于
NextPDF\Contracts或NextPDF\Event以外、且没有@stability标签的类型,都属于内部。即使它在技术上是public,这一点仍然成立。
SPI 未使用时不会产生额外成本。当某个事件类没有绑定任何监听器时,事件调度器会在单次 hasListeners() 检查后立即返回。注册表只保存纯 PHP 数据,而且支持启动时预热,以分摊首次请求的延迟。
安全注意事项
标题为“安全注意事项”的章节签名契约属于安全敏感的接口范围。HsmSignerInterface 要求私钥绝不离开硬件边界。你的实现必须满足这一要求。关于第三方签名后端契约及其威胁模型,请见 KMS 提供方契约一节。
符合性
标题为“符合性”的章节本总览页面不作任何规范性主张。各契约的符合性(PAdES、密钥管理)记录在相关的 SPI 页面中。
商业情境
标题为“商业情境”的章节NextPDF Pro 与 NextPDF Enterprise 为数项签名与验证契约提供生产环境级别的实现,包括以密钥管理系统为后端的签名。你依赖的是公开契约,具体实现由这些版本提供,因此你的代码能在各版本之间保持可移植。
另请参阅
标题为“另请参阅”的章节相关契约与模块
标题为“相关契约与模块”的章节- 契约模块参考 —— 完整的自动生成契约对照表。
- 签名契约参考 ——
SignerInterface、HsmSignerInterface与DeferredSignerInterface。 - 安全策略契约参考 ——
HtmlSecurityPolicyInterface的细节。 - 事件模块参考 —— 生命周期观察的接口范围。
- SPI 稳定性规则 —— 每个
@stability标签背后的变更策略。 - KMS 提供方契约 —— 签名后端契约与威胁模型。
词汇表定义了 SPI、扩展点、稳定性标签 与 向后兼容承诺;正式定义请见已发布的词汇表。