ตรวจสอบความถูกต้องของค่าฟิลด์ฟอร์มและ flatten พร้อมรักษาสถานะเชิงโต้ตอบ
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”ไปป์ไลน์ฟอร์มระดับโปรดักชันแทบไม่ควร flatten อินพุตดิบโดยตรง ขั้นแรกให้ตรวจสอบความถูกต้องของค่าแต่ละค่า จากนั้นจึงตัดสินใจว่าฟิลด์ใดควรกลายเป็นเนื้อหาถาวร และฟิลด์ใดยังคงแก้ไขได้ NextPDF core มีองค์ประกอบพื้นฐานสองอย่างสำหรับงานนี้ ได้แก่ trait สำหรับสร้างฟอร์ม HasFormFields ซึ่งเขียนค่าฟิลด์ลงในเอกสารขณะสร้างฟิลด์ และ flattenForms() ซึ่งฝังฟิลด์ทั้งหมดลงในกราฟิกหน้าแบบคงที่และนำฟอร์มเชิงโต้ตอบออก
สูตรนี้เชื่อมองค์ประกอบทั้งสองเข้าด้วยกันด้วยขั้นตอนการตรวจสอบความถูกต้องในชั้นแอปพลิเคชันที่ core จงใจปล่อยให้เป็นหน้าที่ของคุณ คุณจะ:
- ตรวจสอบความถูกต้องของแมปค่ากับกฎเฉพาะของแต่ละฟิลด์ก่อนสร้างฟิลด์ใดๆ เพื่อไม่ให้ค่าที่ไม่ถูกต้องไปถึงเอกสารได้
- สร้างชุดข้อมูลที่ผ่านการตรวจสอบหนึ่งชุด แล้วส่งออกสองครั้ง — ครั้งหนึ่งเป็นแบบ flatten (สำเนาที่ล็อกและอ่านอย่างเดียว) และอีกครั้งเป็นแบบเชิงโต้ตอบ (สำเนาที่แก้ไขได้) — เพื่อให้สถานะฟิลด์เดียวกันคงอยู่ในเอาต์พุตทั้งสอง
ข้อกำหนดเบื้องต้น: ต้องมีการติดตั้ง NextPDF core ที่ใช้งานได้ (composer require nextpdf/core) และอ่าน Build and pre-fill a PDF form กับ Flatten form fields ครบถ้วนแล้ว สูตรนี้นำกลไกการสร้างฟิลด์และการ flatten มารวมกัน
ขอบเขตของเรื่อง
flattenForms()ของ core ทำงานกับทั้งเอกสาร: คือจะ flatten ทุกฟิลด์หรือไม่ flatten เลย core form API ไม่มีสวิตช์สาธารณะสำหรับ flatten เฉพาะฟิลด์ และไม่มีตัวตรวจสอบความถูกต้องของค่าในตัว ดังนั้น “flatten บางฟิลด์ คงเหลือฟิลด์อื่นไว้ให้ แก้ไขได้” จึงเกิดขึ้นที่ชั้นแอปพลิเคชัน: ตรวจสอบความถูกต้องครั้งเดียว จากนั้นเรนเดอร์ ชุดข้อมูลที่ผ่านการตรวจสอบชุดเดียวกันเป็นเอกสารสองฉบับ สูตรนี้บันทึกรูปแบบดังกล่าวไว้ โดย ไม่ได้สร้างเมธอด core แบบเฉพาะฟิลด์ขึ้นมาใหม่
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”composer require nextpdf/coreไม่จำเป็นต้องใช้ extension เพิ่มเติม ทั้ง trait สำหรับสร้างฟอร์มและตัว flattener รวมอยู่ใน core แล้ว
ภาพรวมเชิงแนวคิด
หัวข้อที่มีชื่อว่า “ภาพรวมเชิงแนวคิด”ฟิลด์ฟอร์ม Acrobat (AcroForm) เก็บค่าปัจจุบันไว้ในรายการ V ของพจนานุกรมฟิลด์ flattenForms() อ่านค่า V ของแต่ละฟิลด์และเรนเดอร์ลงในสตรีมเนื้อหาของหน้าที่ฟิลด์นั้นสังกัดอยู่ — ฟิลด์ข้อความกลายเป็นข้อความ BT ... Tj ... ET ช่องทำเครื่องหมายและปุ่มตัวเลือกกลายเป็นเส้นที่วาดขึ้น และฟิลด์ตัวเลือกจะเรนเดอร์รายการที่ถูกเลือก จากนั้นจะลบรายการ /AcroForm ในแคตาล็อกออก ผลลัพธ์คือฟอร์มแบบไม่เชิงโต้ตอบ: การแสดงแทนฟิลด์แบบคงที่ที่แสดงผลเหมือนกันในโปรแกรมอ่านทุกตัว โดยไม่ต้องใช้ความสามารถในการกรอกฟอร์ม (ISO 32000-2 12.7)
ข้อเท็จจริงสองประการกำหนดรูปแบบระดับโปรดักชัน:
-
core ไม่ตรวจสอบความถูกต้องของค่าฟิลด์ เมธอดการสร้างแต่ละตัว (
textField(),comboBox(),checkBox()และอื่นๆ) เขียนค่าใดๆที่ส่งเข้าไปลงในVโดยตรง รูปแบบอีเมล การเป็นสมาชิกของตัวเลือกที่อนุญาต และการมีอยู่ของฟิลด์ที่จำเป็นเป็นเรื่องของแอปพลิเคชัน ตรวจสอบความถูกต้องก่อนสร้าง และหยุดทันทีเมื่อมีการละเมิด แทนที่จะส่งออกเอกสารที่ฝังค่าไม่ถูกต้องไว้ -
การ flatten ย้อนกลับไม่ได้และทำกับทั้งเอกสาร หลังจากเรียก
flattenForms()และsave()แล้ว ฟิลด์จะกลายเป็นกราฟิกแบบคงที่ หากต้องการเก็บสำเนาที่แก้ไขได้ไว้ด้วย ไม่ต้องพยายามย้อนการ flatten — ให้เรนเดอร์ชุดข้อมูลที่ผ่านการตรวจสอบเป็นครั้งที่สองโดยไม่เรียกflattenForms()สำเนาทั้งสองเริ่มจากค่าที่ผ่านการตรวจสอบชุดเดียวกัน ดังนั้นสำเนาที่ล็อกและสำเนาที่แก้ไขได้จึงมีสถานะฟิลด์เหมือนกัน
โปรไฟล์การทำซ้ำได้คือ structural: เอกสารแต่ละฉบับมีอาร์เรย์ /ID ใน trailer ซึ่งการประมวลผลภายหลังจะปรับให้เป็นมาตรฐานก่อนเปรียบเทียบการรันสองครั้ง
ขอบเขต API
หัวข้อที่มีชื่อว่า “ขอบเขต API”NextPDF\Core\Document (ผ่าน NextPDF\Core\Concerns\HasFormFields):
textField(string $name, float $x, float $y, float $w, float $h, string $default = '', array $options = []): static— สร้างฟิลด์ข้อความโดยกำหนดค่าไว้ในdefaultcomboBox(string $name, float $x, float $y, float $w, float $h, array $items, string $selected = ''): static— สร้างดรอปดาวน์โดยกำหนดรายการที่ถูกเลือกไว้ในselectedcheckBox(string $name, float $x, float $y, float $size, bool $checked = false): static— สร้างช่องทำเครื่องหมายโดยกำหนดสถานะไว้ในcheckedflattenForms(): static— ฝังค่าของทุกฟิลด์ลงในเนื้อหาหน้าแบบคงที่และตัด AcroForm ออก เป็น no-op เมื่อไม่มีฟิลด์ ภายในมอบหมายงานไปยังNextPDF\Form\FormFlattener
NextPDF\Core\Concerns\HasOutput:
save(string $path): void— สร้างและเขียน PDF โยนNextPDF\Exception\InvalidConfigExceptionเมื่อพาธเอาต์พุตเป็น stream wrapper มี null byte หรือระบุไดเรกทอรีหลักที่ไม่มีอยู่
ตัวตรวจสอบความถูกต้องในตัวอย่างด้านล่างเป็นโค้ดของแอปพลิเคชันที่ต้องดูแลเอง ไม่ใช่สัญลักษณ์จาก core และ core ไม่มี API สำหรับตรวจสอบความถูกต้องของค่า จึงต้องระบุขั้นตอนการตรวจสอบไว้อย่างชัดเจนในที่นี้
ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว”โฟลว์ขั้นต่ำนี้ตรวจสอบความถูกต้องของแมปค่า สร้างสามฟิลด์จากแมปนั้น จากนั้น flatten และบันทึกสำเนาที่ล็อกหนึ่งชุด
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
/** @var array<string, string> $input Untrusted value map (e.g. from a request). */$input = [ 'full_name' => 'Ada Lovelace', 'country' => 'Taiwan',];
$allowedCountries = ['United Kingdom', 'Taiwan', 'Japan'];
// Validate before authoring: core writes whatever you pass, so reject early.if (trim($input['full_name']) === '') { throw new InvalidArgumentException('full_name must not be empty.');}if (filter_var($input['email'], FILTER_VALIDATE_EMAIL) === false) { throw new InvalidArgumentException('email is not a valid address.');}if (!in_array($input['country'], $allowedCountries, true)) { throw new InvalidArgumentException('country is not an allowed option.');}
$doc = Document::createStandalone();$doc->setTitle('Validated Form (locked copy)');$doc->addPage();
$doc->textField(name: 'full_name', x: 20, y: 30, w: 90, h: 8, default: $input['full_name']);$doc->textField(name: 'email', x: 20, y: 45, w: 90, h: 8, default: $input['email']);$doc->comboBox( name: 'country', x: 20, y: 60, w: 90, h: 8, items: $allowedCountries, selected: $input['country'],);
// Whole-document flatten: every field becomes static graphics.$doc->flattenForms();
$doc->save(__DIR__ . '/registration-locked.pdf');echo "Wrote registration-locked.pdf\n";ตัวอย่างโค้ด — โปรดักชัน
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — โปรดักชัน”โฟลว์ระดับโปรดักชันแยกการตรวจสอบความถูกต้องออกจากการเรนเดอร์ FieldRuleSet แบบระบุชนิดข้อมูลจะตรวจสอบความถูกต้องของแมปค่าหนึ่งครั้งและคืนชุดข้อมูลที่ผ่านการตรวจสอบ ฟังก์ชันตัวช่วย renderForm() เพียงตัวเดียวสร้างฟิลด์และรันสองครั้ง — แบบ flatten สำหรับสำเนาที่ล็อก และแบบไม่ flatten สำหรับสำเนาที่แก้ไขได้ สำเนาทั้งสองมาจากค่าที่ผ่านการตรวจสอบชุดเดียวกัน ดังนั้นสถานะเชิงโต้ตอบจึงคงอยู่ในทั้งสองสำเนา ฮาร์เนสอ่านพาธเอาต์พุตจาก NEXTPDF_COOKBOOK_LOCKED_OUTPUT และ NEXTPDF_COOKBOOK_EDITABLE_OUTPUT
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;use NextPDF\Exception\InvalidConfigException;
/** * A single validated form record. Immutable: once constructed, every value has * already passed the rule set, so the rendering step cannot re-introduce a bad * value. This is the "validate once, render many" boundary. */final readonly class ValidatedRegistration{ /** * @param non-empty-string $fullName * @param non-empty-string $email * @param non-empty-string $country */ public function __construct( public string $fullName, public string $email, public string $country, public bool $newsletter, ) {}}
/** * Application-layer field validation. Core performs no value validation, so the * rules live here. Each method throws on the first violation; the caller maps * the exception to an HTTP 422 or a user-facing message. */final class FieldRuleSet{ /** @var list<non-empty-string> */ private const array ALLOWED_COUNTRIES = ['United Kingdom', 'Taiwan', 'Japan', 'Germany'];
/** * @param array<string, string|bool> $input Untrusted value map. * * @throws InvalidArgumentException When any field fails its rule. */ public function validate(array $input): ValidatedRegistration { $fullName = $this->requireNonEmpty($input, 'full_name'); $email = $this->requireEmail($input, 'email'); $country = $this->requireAllowed($input, 'country', self::ALLOWED_COUNTRIES);
$newsletter = $input['newsletter'] ?? false; if (!is_bool($newsletter)) { throw new InvalidArgumentException('newsletter must be a boolean.'); }
return new ValidatedRegistration( fullName: $fullName, email: $email, country: $country, newsletter: $newsletter, ); }
/** * @param array<string, string|bool> $input * * @return non-empty-string * * @throws InvalidArgumentException */ private function requireNonEmpty(array $input, string $key): string { $value = $input[$key] ?? ''; if (!is_string($value) || trim($value) === '') { throw new InvalidArgumentException(sprintf('%s must not be empty.', $key)); }
return $value; }
/** * @param array<string, string|bool> $input * * @return non-empty-string * * @throws InvalidArgumentException */ private function requireEmail(array $input, string $key): string { $value = $input[$key] ?? ''; if (!is_string($value) || $value === '' || filter_var($value, FILTER_VALIDATE_EMAIL) === false) { throw new InvalidArgumentException(sprintf('%s is not a valid email address.', $key)); }
return $value; }
/** * @param array<string, string|bool> $input * @param list<non-empty-string> $allowed * * @return non-empty-string * * @throws InvalidArgumentException */ private function requireAllowed(array $input, string $key, array $allowed): string { $value = $input[$key] ?? ''; if (!is_string($value) || !in_array($value, $allowed, true)) { throw new InvalidArgumentException(sprintf('%s is not an allowed option.', $key)); }
return $value; }
/** @return list<non-empty-string> */ public function allowedCountries(): array { return self::ALLOWED_COUNTRIES; }}
/** * Author the same field layout from one validated record. When $flatten is * true, every field is baked into static page content and the AcroForm is * dropped; when false, the fields stay interactive and editable. Both paths * start from identical values, preserving the form's state across copies. */function renderForm(ValidatedRegistration $record, FieldRuleSet $rules, bool $flatten): Document{ $doc = Document::createStandalone(); $doc->setTitle($flatten ? 'Customer Registration (locked)' : 'Customer Registration (editable)'); $doc->addPage();
$doc->setFont('helvetica', 'B', 18); $doc->cell(0, 12, 'Customer Registration', newLine: true); $doc->ln(4);
$leftMargin = 15.0; $fieldX = 70.0; $fieldW = 120.0; $fieldH = 8.0; $rowSpacing = 12.0; $y = 40.0;
$doc->setFont('helvetica', '', 10);
$doc->setXY($leftMargin, $y); $doc->cell(50, $fieldH, 'Full Name:'); $doc->textField(name: 'full_name', x: $fieldX, y: $y, w: $fieldW, h: $fieldH, default: $record->fullName); $y += $rowSpacing;
$doc->setXY($leftMargin, $y); $doc->cell(50, $fieldH, 'Email:'); $doc->textField(name: 'email', x: $fieldX, y: $y, w: $fieldW, h: $fieldH, default: $record->email); $y += $rowSpacing;
$doc->setXY($leftMargin, $y); $doc->cell(50, $fieldH, 'Country:'); $doc->comboBox( name: 'country', x: $fieldX, y: $y, w: $fieldW, h: $fieldH, items: $rules->allowedCountries(), selected: $record->country, ); $y += $rowSpacing;
$doc->setXY($leftMargin, $y); $doc->cell(50, $fieldH, 'Newsletter:'); $doc->checkBox(name: 'newsletter', x: $fieldX, y: $y, size: 5, checked: $record->newsletter);
if ($flatten) { // Whole-document flatten: locked, read-only copy. $doc->flattenForms(); }
return $doc;}
/** @var array<string, string|bool> $input Untrusted value map (request payload). */$input = [ 'full_name' => 'Ada Lovelace', 'country' => 'Taiwan', 'newsletter' => true,];
$rules = new FieldRuleSet();
try { // Validate once. A violation aborts before any document is built. $record = $rules->validate($input);
// Render the validated dataset twice: locked, then editable. $locked = renderForm($record, $rules, flatten: true); $editable = renderForm($record, $rules, flatten: false);
$lockedPath = getenv('NEXTPDF_COOKBOOK_LOCKED_OUTPUT') ?: __DIR__ . '/registration-locked.pdf'; $editablePath = getenv('NEXTPDF_COOKBOOK_EDITABLE_OUTPUT') ?: __DIR__ . '/registration-editable.pdf';
$locked->save($lockedPath); $editable->save($editablePath);
echo "Wrote locked and editable registration copies\n";} catch (InvalidArgumentException $e) { // Validation failure: a bad value never reached the document. fwrite(STDERR, 'Form validation failed: ' . $e->getMessage() . "\n"); exit(1);} catch (InvalidConfigException $e) { // Output failure: bad path, missing directory, or stream wrapper. fwrite(STDERR, sprintf( 'PDF save failed for key "%s": %s' . "\n", $e->getConfigKey(), $e->getMessage(), )); exit(1);}เอาต์พุตที่คาดหวัง:
Wrote locked and editable registration copiesสำเนาที่ล็อกจะเปิดขึ้นโดยไม่มีฟิลด์เชิงโต้ตอบ — ค่าต่างๆเป็นกราฟิกแบบคงที่ สำเนาที่แก้ไขได้จะเปิดขึ้นโดยมีค่าเดียวกันกรอกไว้ล่วงหน้า และทุกฟิลด์ยังคงแก้ไขได้ ทั้งสองสำเนาสะท้อนชุดข้อมูลที่ผ่านการตรวจสอบชุดเดียว
กรณีขอบและข้อควรระวัง
หัวข้อที่มีชื่อว่า “กรณีขอบและข้อควรระวัง”- ตรวจสอบความถูกต้องก่อนสร้าง ไม่ใช่หลังจากนั้น เมธอดการสร้างเขียนค่าของคุณลงใน
Vแบบตรงตามตัวอักษร ไม่มี hook ของ core ที่ปฏิเสธค่ารูปแบบผิดในเวลาsave()ดังนั้นค่าที่ข้ามการตรวจสอบความถูกต้องจะถูกฝังลงในสำเนาที่ flatten แล้วโดยไม่มีทางกู้คืน flattenForms()ทำทั้งหมดหรือไม่ทำเลย โดยจะ flatten ทุกฟิลด์ในเอกสาร หากต้องการให้บางฟิลด์ยังแก้ไขได้ ให้เรนเดอร์เอกสารฉบับที่สองโดยไม่เรียกการ flatten ตามที่ตัวอย่างระดับโปรดักชันทำ — ไม่ควรคาดหวังว่าจะมีสวิตช์แบบเฉพาะฟิลด์ใน core API- ลำดับการเรียก สร้างทุกฟิลด์ก่อน จากนั้นเรียก
flattenForms()แล้วจึงsave()การเรียกflattenForms()เมื่อไม่มีฟิลด์เป็น no-op ที่ปลอดภัย ส่วนการเรียกหลังsave()ไม่มีผลต่อไบต์ที่เขียนไปแล้ว - ชื่อฟิลด์ต้องไม่ซ้ำกัน ฟิลด์สองตัวที่ใช้ชื่อเดียวกันจะกลายเป็นฟิลด์เชิงตรรกะหนึ่งตัวที่มีค่าร่วมกันในโปรแกรมอ่านที่ทำตามมาตรฐาน ตรวจสอบความไม่ซ้ำกันของชื่อเมื่อชื่อถูกกำหนดจากข้อมูล
- ค่าความจริงของช่องทำเครื่องหมายขณะ flatten ช่องทำเครื่องหมายที่ flatten แล้วจะวาดเครื่องหมายถูกเมื่อค่าเป็น
Yes,On,1หรือtrueส่วนค่าว่างหรือOffจะวาดเฉพาะกล่อง ส่งค่า boolean จริงไปยังcheckBox()เพื่อให้สถานะที่เรนเดอร์ตรงกับค่าที่ผ่านการตรวจสอบ - ฟิลด์ลายเซ็นจะไม่ถูก flatten ลักษณะที่ปรากฏของฟิลด์
/Sigสร้างจากเพย์โหลดลายเซ็น ไม่ใช่ค่าที่เรนเดอร์ใหม่ได้ ตัว flattener จึงข้ามฟิลด์นี้ ให้ flatten ก่อนลงนาม และห้าม flatten หลังลงนามเด็ดขาด - สำเนาที่แก้ไขได้ยังคงแก้ไขได้ การรักษาสถานะไว้ในสำเนาที่แก้ไขได้หมายความว่าผู้รับสามารถเปลี่ยนแปลงได้ ให้ถือว่าสำเนาที่ล็อกเป็นบันทึกอย่างเป็นทางการ และสำเนาที่แก้ไขได้เป็นฉบับร่างสำหรับใช้งาน
ประสิทธิภาพ
หัวข้อที่มีชื่อว่า “ประสิทธิภาพ”การตรวจสอบความถูกต้องมีความซับซ้อนเชิงเส้นตามจำนวนฟิลด์และรันหนึ่งครั้งต่อชุดข้อมูล การเรนเดอร์แต่ละครั้งสร้างคำอธิบายประกอบ widget หนึ่งรายการพร้อมลักษณะที่ปรากฏต่อหนึ่งฟิลด์ ขั้นตอน flatten เพิ่มบล็อกเนื้อหาที่มีขอบเขตจำกัดต่อหนึ่งฟิลด์ การเรนเดอร์ชุดข้อมูลสองครั้งทำให้ต้นทุนต่อเอกสารเพิ่มขึ้นราวสองเท่า ซึ่งยังคงอยู่ภายในงบประมาณ 1500 ms / 64 MB ได้อย่างเหลือเฟือสำหรับฟอร์มที่มีฟิลด์ไม่กี่ร้อยฟิลด์ หากต้องการเอาต์พุตเพียงชุดเดียว ให้เรนเดอร์ครั้งเดียวและข้ามรอบที่สองไป
หมายเหตุด้านความปลอดภัย
หัวข้อที่มีชื่อว่า “หมายเหตุด้านความปลอดภัย”- ตรวจสอบความถูกต้องของอินพุตที่ไม่น่าเชื่อถือที่ขอบเขต รูปแบบอีเมล การเป็นสมาชิกของตัวเลือกที่อนุญาต และการมีอยู่ของฟิลด์ที่จำเป็นถูกบังคับใช้ในโค้ดแอปพลิเคชัน เพราะ core ไม่ได้บังคับใช้สิ่งเหล่านี้ ให้ escape หรือปรับค่าใดๆที่มาจากอินพุตที่ไม่น่าเชื่อถือให้เป็นมาตรฐานก่อนที่ค่านั้นจะไปถึงฟิลด์ เพราะ core เขียนค่านั้นลงในเอกสารแบบตรงตามตัวอักษร
- การ flatten ไม่ใช่การควบคุมการเข้าถึง ค่าที่ flatten แล้วไม่สามารถแก้ไขได้ในโปรแกรมอ่านทั่วไป แต่ยังคงมองเห็นได้ในเนื้อหาของหน้าและสามารถดึงออกมาได้ด้วยเครื่องมือข้อความใดๆ อย่าถือว่าการ flatten เป็น redaction หรือเป็นการปกป้องค่าที่ละเอียดอ่อน
- สำเนาที่แก้ไขได้มีข้อมูลเดียวกัน แจกจ่ายให้เฉพาะฝ่ายที่ได้รับอนุญาตให้เห็นและเปลี่ยนแปลงค่าเหล่านั้นเท่านั้น เมื่อเนื้อหามีความละเอียดอ่อน ให้ผนวกสำเนาฉบับใดก็ได้เข้ากับ Encrypt with permissions และสังเกตข้อควรระวังที่อาศัยความร่วมมือของโปรแกรมอ่านตามที่อธิบายไว้ในนั้น: บิตสิทธิ์ไม่ได้บังคับใช้ข้อจำกัดในการอ่าน
- ล้มเหลวแบบปิด ตัวอย่างระดับโปรดักชันออกด้วยค่าที่ไม่ใช่ศูนย์เมื่อการตรวจสอบความถูกต้องหรือเอาต์พุตล้มเหลว แทนที่จะเขียนเอกสารที่ไม่สมบูรณ์หรือไม่ถูกต้อง ห้ามกลืน exception เหล่านี้เด็ดขาด
ความสอดคล้องตามมาตรฐาน
หัวข้อที่มีชื่อว่า “ความสอดคล้องตามมาตรฐาน”| ข้อความระบุ | ข้อกำหนด | ข้อ | รหัสอ้างอิง (reference_id) |
|---|---|---|---|
| ฟอร์มที่ flatten แล้วคือการแสดงแทนฟิลด์แบบไม่เชิงโต้ตอบ (คงที่) | ISO 32000-2 | 12.7 |
NextPDF สร้างโครงสร้างแบบคงที่ตามที่อธิบายไว้ในข้อที่อ้างถึง แต่ไม่ได้ยืนยันความสอดคล้องตาม ISO 32000-2 แบบครอบคลุมทั้งหมด กฎการตรวจสอบความถูกต้องในสูตรนี้เป็นนโยบายของแอปพลิเคชัน ไม่ใช่ข้อกำหนดด้านความสอดคล้องของมาตรฐาน
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”- Build and pre-fill a PDF form — สร้างฟิลด์และกำหนดค่าเริ่มต้นให้ฟิลด์
- Flatten form fields — การ flatten ทั้งเอกสารที่สูตรนี้ต่อยอดมา
- Handle errors with the NextPDF exception hierarchy — ดักจับความล้มเหลวในระดับความละเอียดที่เหมาะสม
- Encrypt with permissions — เพิ่มการรักษาความลับเมื่อข้อมูลฟอร์มมีความละเอียดอ่อน
- Form module — เอกสารอ้างอิงของฟิลด์ฟอร์ม