將表單欄位扁平化為靜態頁面內容
重點摘要
標題為「重點摘要」的區段這則範例會將一份互動式 AcroForm 扁平化。它會把每個欄位目前的值,以一般圖形繪入頁面的內容串流,然後移除 AcroForm 字典。結果是一份非互動式表單:欄位的靜態呈現,在任何地方看起來都一致,即使閱讀器不支援表單也一樣(ISO 32000-2 §12.7)。這則範例會先從 examples/30-form-fields.php 建立表單,再呼叫 flattenForms()。
composer require nextpdf/core:^3概念總覽
標題為「概念總覽」的區段扁平化會把每個欄位元件「印」到它所在的頁面上。文字欄位會變成 BT … Tj … ET 文字;核取方塊與選項按鈕會變成繪製出來的路徑;選擇欄位會繪製出被選取的項目;命令按鈕則會繪製成靜態、類似按鈕的方框。這符合規範中靜態定義外觀的模型,也就是在欄位內容事先已知時所採用的做法(ISO 32000-2 §12.7)。由於這些值已被寫入內容中,因此不需要已棄用的 NeedAppearances 機制。
此設定檔為 structural。文件帶有一個結尾的 /ID,後處理流程會在比較兩次執行結果之前先將它正規化。
API 介面
標題為「API 介面」的區段NextPDF\Core\Concerns\HasFormFields::flattenForms(): static 會將文件上建立的每個欄位扁平化為靜態頁面內容,並移除 AcroForm。若沒有任何欄位,它不會做任何事。在內部,它會將這項工作委派給 NextPDF\Form\FormFlattener。
請使用欄位建構式建立表單。相關步驟請參閱 建立並預先填寫 PDF 表單一節。接著呼叫 flattenForms(),並在 save() 之前完成。
程式碼範例 — 快速上手
標題為「程式碼範例 — 快速上手」的區段<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Flattened Form');$doc->addPage();
$doc->textField(name: 'full_name', x: 20, y: 30, w: 90, h: 8, default: 'Ada Lovelace');$doc->checkBox(name: 'agree', x: 20, y: 45, size: 5, checked: true);
// Bake the field values into the page; the AcroForm is removed.$doc->flattenForms();
$doc->save(__DIR__ . '/flattened.pdf');echo "Wrote flattened.pdf (no interactive fields)\n";程式碼範例 — 正式環境
標題為「程式碼範例 — 正式環境」的區段下方完整範例會從 examples/30-form-fields.php 建立這份多區段表單。它會先預先填寫表單,再將表單扁平化,並寫入 NEXTPDF_COOKBOOK_OUTPUT 供測試載具使用。
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Customer Registration — Flattened');$doc->addPage();
$doc->setFont('helvetica', 'B', 20);$doc->cell(0, 14, 'Customer Registration (read-only copy)', newLine: true);$doc->ln(4);
$leftMargin = 15.0;$fieldX = 70.0;$fieldW = 120.0;$fieldH = 8.0;$rowSpacing = 12.0;
$prefill = [ 'full_name' => 'Ada Lovelace', 'phone' => '+44 20 7946 0000', 'company' => 'Analytical Engines Ltd',];
$y = 40.0;$doc->setFont('helvetica', '', 10);foreach ($prefill as $name => $value) { $doc->setXY($leftMargin, $y); $doc->cell(50, $fieldH, ucwords(str_replace('_', ' ', $name)) . ':'); $doc->textField(name: $name, x: $fieldX, y: $y, w: $fieldW, h: $fieldH, default: $value); $y += $rowSpacing;}
$y += 6;$doc->setXY($leftMargin, $y);$doc->cell(0, 7, 'Newsletter');$doc->checkBox(name: 'newsletter', x: $leftMargin + 70, y: $y, size: 5, checked: true);
// Flatten: widgets become static page content; the AcroForm is dropped.$doc->flattenForms();
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');$doc->save($out !== false ? $out : __DIR__ . '/registration-flattened.pdf');
echo "Wrote flattened registration form\n";預期輸出:
Wrote flattened registration form輸出會顯示相同的值,但不再包含互動式欄位。不支援表單的閱讀器也會以相同方式繪製。
邊緣案例與陷阱
標題為「邊緣案例與陷阱」的區段- 扁平化不可逆。 一旦你呼叫
save(),互動式欄位就會消失。如果之後可能還需要編輯這些值,請保留尚未扁平化的原始檔。 - 呼叫順序。 請在建立欄位之後執行
flattenForms(),也就是在save()之前。沒有欄位時呼叫它不會做任何事,因此是安全的。 - 簽章欄位不會被扁平化。
/Sig欄位的視覺呈現,是由它的 CMS SignedData 所產生的外觀,而非可重新繪製的值。重新點陣化它只會產生一個靜態的「殘影」圖形,不再對應任何可驗證的簽章。基於這個原因,扁平化流程會刻意略過簽章欄位。請務必在簽署之前扁平化表單,絕不要在簽署之後。 - 核取方塊的真值判斷。 當核取方塊的值為
Yes/On/1/true時,它會繪製勾選標記;空值或Off值則只會繪製方框。 - 扁平化文字所用的字型。 扁平化後的文字會使用目前的字型。若未設定字型,它會退回使用 Helvetica。若欄位值是 CJK 或使用自訂字型,請在
flattenForms()之前設定你想要的字型。
扁平化耗用的資源會隨欄位數量呈線性成長。對每個欄位,它會附加一個有界的內容區塊,接著移除 AcroForm 物件。對一般表單而言,它會穩定落在 1500 ms/64 MB 的預算之內。
安全性注意事項
標題為「安全性注意事項」的區段扁平化會讓欄位值在一般閱讀器中無法編輯。這只是呈現方式的改變,並不是存取控制。這些值仍會顯示在頁面內容中,任何文字工具都能擷取。請勿把扁平化當成遮蔽(redaction),也不要視為保護敏感值的手段。若需要機密性,請使用 以權限加密一節。也請一併閱讀該節關於閱讀器須配合(reader-cooperative)的提醒,因為權限位元同樣無法強制執行讀取限制。絕不要扁平化一份已簽署的文件。請先扁平化,再簽署。
符合性
標題為「符合性」的區段| 陳述 | 規範 | 條款 | 參考 ID |
|---|---|---|---|
| 扁平化表單是欄位的非互動式(靜態)呈現。 | ISO 32000-2 | §12.7 | |
| 當欄位內容事先已知時,其外觀會以靜態方式定義。 | ISO 32000-2 | §12.7 | |
由於外觀已被寫入內容中,已棄用的 NeedAppearances 旗標就變得不必要。 | ISO 32000-2 | §12.7 |
NextPDF 會產生所引條款所描述的靜態結構。它並未主張全面符合 ISO 32000-2。