Pro 版本
Interop — 深入參考
本頁是 NextPDF\Pro\Interop\V1 的合約層參考。此模組包含十四個公開符號:一個序列化合約(InteropResultInterface)、一個 CI 完整性守衛(SchemaLock)、三個頂層結果 DTO(ExtractedText、DocumentSegmentation、FormData),以及九個支援用的值物件與列舉。每個 DTO 都是某一項分析結果的不可變、可 JSON 序列化的視圖。線路格式帶有版本且經過鎖定;此介面上沒有任何東西會重新執行分析。任務導向的視圖請見能力頁面。
供應與授權
標題為「供應與授權」的區段此能力隨 NextPDF Pro(nextpdf/pro)出貨,並以 Pro 層級的授權封套啟用。缺少該權利的部署不會載入此能力的類別。比較版本並取得授權。
沒有任何執行期能力旗標閘控此模組。只要安裝並授權 nextpdf/pro,這些類別即可使用。
公開 API 介面
標題為「公開 API 介面」的區段| 符號 | 參數 | 預設行為 | 回傳 | 拋出或失敗於 | 備註 |
|---|---|---|---|---|---|
InteropResultInterface | — | 頂層結果 DTO 的合約;擴充 JsonSerializable | — | 不會拋出 | SCHEMA_VERSION 是字串 '1.0'。 |
InteropResultInterface::toArray() | 無 | 序列化為一律帶有 schema_version 的 JSON 安全陣列 | array<string, mixed> | 不會拋出 | 實作亦會發出 type 判別欄。 |
InteropResultInterface::toJson() | int $flags = 0 | 編碼 toArray() 的輸出;一律 OR 進 JSON_THROW_ON_ERROR | string | 對無法編碼的資料拋出 JsonException | 可傳入如 JSON_PRETTY_PRINT 等旗標。 |
SchemaLock::verify() | 無 | 對磁碟上的 V1 schema.json 雜湊,並與鎖定的 SHA-256 比對 | bool | 不會拋出 | 當 schema 檔案缺少、無法讀取或遭修改時為 false。 |
SchemaLock::expectedHash() | 無 | 回傳鎖定的雜湊 | string | 不會拋出 | 供 CI 失敗分診用的診斷輸出。 |
SchemaLock::actualHash() | 無 | 回傳目前 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 | 字串支撐的列舉 | 十二個案例,heading 到 unknown | — | 不會拋出 | isContent() 與 isStructural() 將各案例分割。 |
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 | 字串支撐的列舉 | 八個案例,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 物件。欄位在此跨行程邊界上會被型別守衛:缺少或型別錯誤的值會退回已載明的預設值,而非拋出。 - 列舉退回。 在
Segment::fromArray()中,無法識別的type字串對應到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()會在該鍵缺少或型別錯誤時,代入一個 595 × 842 點、第 1 頁的退回page_info。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 檔名與工單前綴皆不在範圍內。