Pro 版本
Interop — 深度参考
本页是 NextPDF\Pro\Interop\V1 的契约级参考。该模块包含十四个公共符号:一个序列化契约(InteropResultInterface)、一个 CI 完整性守卫(SchemaLock)、三个顶层结果 DTO(ExtractedText、DocumentSegmentation、FormData),以及九个支撑用的值对象与枚举。每个 DTO 都是某个分析结果的不可变、可 JSON 序列化的视图。其线格式(wire shape)带有版本并被锁定;此接口面上的任何内容都不会重新运行分析。面向任务的视角见能力页。
可用性与授权
标题为“可用性与授权”的章节此能力随 NextPDF Pro(nextpdf/pro)发布,并在 Pro 层级的授权信封(license envelope)下激活。没有该权益的部署不会加载此能力的类。对比版本并获取授权。
没有任何运行时能力标记对此模块进行门控。只要安装并授权了 nextpdf/pro,这些类即可使用。
公共 API 接口面
标题为“公共 API 接口面”的章节| Symbol | Parameters | Default behavior | Returns | Throws or fails with | Notes |
|---|---|---|---|---|---|
InteropResultInterface | — | 顶层结果 DTO 的契约;扩展 JsonSerializable | — | 不抛出 | SCHEMA_VERSION 是字符串 '1.0'。 |
InteropResultInterface::toArray() | none | 序列化为始终携带 schema_version 的 JSON 安全数组 | array<string, mixed> | 不抛出 | 实现类还会输出一个 type 判别字段。 |
InteropResultInterface::toJson() | int $flags = 0 | 对 toArray() 的输出进行编码;JSON_THROW_ON_ERROR 始终被 OR 进标志位 | string | 数据不可编码时抛出 JsonException | 可传入 JSON_PRETTY_PRINT 等标志。 |
SchemaLock::verify() | none | 对磁盘上的 V1 schema.json 求哈希,并与锁定的 SHA-256 比较 | bool | 不抛出 | 当 schema 文件缺失、不可读或被修改时返回 false。 |
SchemaLock::expectedHash() | none | 返回锁定的哈希 | string | 不抛出 | 用于 CI 失败排查的诊断输出。 |
SchemaLock::actualHash() | none | 返回当前 schema 文件的哈希 | string | 不抛出 | I/O 失败时,哨兵字符串 FILE_NOT_FOUND / READ_FAILED 会取代哈希。 |
BoundingBox | float $x、float $y、float $width、float $height | PDF 用户空间点为单位的不可变盒,原点在左下角 | — | 不抛出 | area()、overlaps()、toArray()、fromArray()。 |
DocumentInfo | int $pageCount 外加六个可选元数据字段 | 不可变的文档元数据 | — | 不抛出 | fromArray() 对每个字段做类型守卫;缺失字段回退为默认值。 |
PageInfo | int $pageNumber、float $width、float $height、int $rotation = 0 | 不可变的页面元数据 | — | 不抛出 | isLandscape();fromArray() 会强制转换数字字符串与浮点数。 |
ExtractedText | list<ExtractedPage> $pages、DocumentInfo $documentInfo、float $processingTimeMs = 0.0 | 整篇文档的文本提取结果 | — | 仅 toJson() 抛出 JsonException | page()、totalBlockCount()、plainText()、fromArray()。 |
ExtractedPage | PageInfo $pageInfo、list<TextBlock> $textBlocks | 按阅读顺序排列的每页文本块容器 | — | 不抛出 | plainText() 以单个空格连接块内容。 |
TextBlock | string $content、BoundingBox $boundingBox、int $pageNumber、string $fontName = ''、float $fontSize = 0.0 | 已定位的连续文本段 | — | 不抛出 | 字体名与字号为尽力而为(块内主导字体)。 |
DocumentSegmentation | list<Segment> $segments、DocumentInfo $documentInfo、float $processingTimeMs = 0.0 | 版面感知的分段结果 | — | 仅 toJson() 抛出 JsonException | segmentCount()、ofType()、onPage()、contentSegments()、fromArray()。 |
Segment | SegmentType $type、string $content、BoundingBox $boundingBox、int $pageNumber、float $confidence = 1.0、list<Segment> $children = [] | 已分类的页面区域;子项递归嵌套 | — | 不抛出 | isHighConfidence() 阈值为 0.8;descendantCount() 为递归计数。 |
SegmentType | 字符串背衬的枚举 | 十二个 case,从 heading 到 unknown | — | 不抛出 | isContent() 与 isStructural() 对这些 case 进行划分。 |
FormData | list<FormField> $fields、DocumentInfo $documentInfo、float $processingTimeMs = 0.0 | 整篇文档的表单提取结果 | — | 仅 toJson() 抛出 JsonException | field()、dataFields()、filledCount()、toKeyValueMap()、fromArray()。 |
FormField | string $name、FormFieldType $type,外加六个可选字段 | 单个已提取的表单字段 | — | 不抛出 | isFilled() 即 value !== ''。 |
FormFieldType | 字符串背衬的枚举 | 八个 case,从 text 到 button | — | 不抛出 | 对 button 与 signature 而言 isDataField() 为 false。 |
interface InteropResultInterface extends JsonSerializable
public const SCHEMA_VERSION = '1.0';
public function toArray(): array;
public function toJson(int $flags = 0): string;final class SchemaLock
public static function verify(): bool
public static function expectedHash(): string
public static function actualHash(): stringfinal readonly class ExtractedText implements InteropResultInterface
public function __construct( public array $pages, public DocumentInfo $documentInfo, public float $processingTimeMs = 0.0,)
public function page(int $pageNumber): ?ExtractedPage
public function totalBlockCount(): int
public function plainText(): string
public static function fromArray(array $data): selffinal readonly class DocumentSegmentation implements InteropResultInterface
public function __construct( public array $segments, public DocumentInfo $documentInfo, public float $processingTimeMs = 0.0,)
public function ofType(SegmentType $type): array
public function onPage(int $pageNumber): array
public function contentSegments(): array
public static function fromArray(array $data): selffinal readonly class FormData implements InteropResultInterface
public function __construct( public array $fields, public DocumentInfo $documentInfo, public float $processingTimeMs = 0.0,)
public function field(string $name): ?FormField
public function dataFields(): array
public function toKeyValueMap(): array
public static function fromArray(array $data): self行为契约
标题为“行为契约”的章节- 带版本的信封。 每个顶层 DTO(
ExtractedText、DocumentSegmentation、FormData)都实现InteropResultInterface。其toArray()输出始终携带schema_version('1.0')与一个type判别字段:extracted_text、document_segmentation或form_data。 - JSON 编码。
toJson()委托给json_encode,并将JSON_THROW_ON_ERROROR 进调用方的标志位。jsonSerialize()委托给toArray(),因此json_encode($dto)产出相同的格式。 - 确定性序列化。 键顺序与格式由 DTO 固定。
Segment::toArray()在children为空时省略该键;FormField::toArray()在bounding_box为null时省略它。消费方必须将这两个键都视为可选。 - 往返。 每个 DTO 都暴露一个静态
fromArray(),接受一个已解码的 JSON 对象。字段在此跨进程边界上做类型守卫:缺失或类型错误的值会回退为文档所述的默认值,而不是抛出异常。 - 枚举回退。 无法识别的
type字符串在Segment::fromArray()中映射为SegmentType::Unknown,在FormField::fromArray()中映射为FormFieldType::Text。 - 坐标。
BoundingBox坐标为 PDF 用户空间单位(点,1/72 英寸),原点在页面左下角。页码在全篇均为从 1 开始。 - 纯文本连接。
ExtractedPage::plainText()以单个空格连接块内容。ExtractedText::plainText()以空行("\n\n")连接各页。 - 分段查询。
ofType()、onPage()与contentSegments()仅过滤顶层分段,并返回重新索引的列表。contentSegments()选取SegmentType::isContent()为true的类型:heading、sub_heading、paragraph、table、list、code。 - 表单查询。
FormData::dataFields()与toKeyValueMap()排除非数据型字段类型(button、signature)。filledCount()统计值为非空字符串的字段。 - Schema 锁。
SchemaLock::verify()读取随包发布的 V1schema.json,将 CRLF 规范化为 LF,以 SHA-256 求哈希,并以常量时间与锁定常量比较。CI 用它来阻止静默的 schema 漂移;锁值仅在一次刻意的、带版本的 schema 变更时才会改变。 - 版本策略。 V1 接口面是一份显式的公共契约。增量式变更会提升 schema 版本;破坏性变更需要一个新的主版本。
边界情形与失败模式
标题为“边界情形与失败模式”的章节- 此接口面上唯一会抛出异常的成员是
toJson():当数组不可编码时(例如提取内容中出现无效 UTF-8)抛出JsonException。 - 当 schema 文件缺失、不可读或被修改时,
SchemaLock::verify()返回false——从不抛出。比较expectedHash()与actualHash()可区分漂移与 I/O 失败。 fromArray()的回退在设计上是静默的。类型错误的page_number会变为1;类型错误的confidence会变为默认值。当无法接受伪造的默认值时,请在上游做校验。- 数字字符串强制转换是不对称的。
PageInfo::fromArray()对其 int 与 float 字段接受数字字符串;Segment与TextBlock对confidence与font_size仅接受 int 或 float。 BoundingBox::fromArray()按其文档所述的数组格式要求全部四个键。嵌入它的 DTO 在包裹键缺失时会替换为零盒(对FormField则为null)。- 当键缺失或类型错误时,
ExtractedPage::fromArray()会替换为一个回退的page_info:第 1 页、595 × 842 点。 FormField::fromArray()对required与read_only仅接受严格的布尔值;真值字符串与整数均映射为false。Segment的子项递归没有深度上限。极深的嵌套仅受 PHP 的内存与栈限制约束。- 此模块中不发生任何密码学密钥或签名操作。
SchemaLock仅将 SHA-256 用作文件完整性校验和,因此没有任何 FIPS 模式特有的行为。
一致性
标题为“一致性”的章节Interop V1 是一份 NextPDF 自有的、带版本的线契约。它不实现任何外部标准,因此没有规范性引用表。BoundingBox 语义与产出方 Core 子系统所用的 PDF 用户空间坐标模型对齐;这是一条结构对齐陈述,而非一致性测试结果。NextPDF 不持有任何认证,也不授予任何认证。
开发说明
标题为“开发说明”的章节- 在消费方基于
schema_version进行分支。将增量键视为兼容;对未知的主版本显式拒绝。 - 在 CI 中运行
SchemaLock::verify()。失败时记录expectedHash()与actualHash(),并要求一次刻意的、带版本的 schema 变更,绝不做就地编辑。 - 对于跨进程往返,使用关联数组解码(
json_decode($json, true)),并将结果喂给匹配的fromArray()。 - 所有 DTO 均为
final且readonly。通过组合来扩展;从公共字段派生出新视图。 toKeyValueMap()仅摊平承载数据的字段。当signature字段的存在与否很重要时,直接从FormData::$fields读取它们。- 复用是安全的:这些 DTO 不持有可变状态、也不持有资源,因此可被缓存、跨请求共享并反复序列化。
发布边界
标题为“发布边界”的章节本页仅记录外部可观察的行为与受支持的公共 API 接口面。内部命名空间路径、辅助类、机制表、runbook 文件名以及工单前缀均不在范围内。