Перейти к содержимому

Form: интерактивные поля AcroForm и сведение формы

Модуль Form создаёт интерактивные формы в документах Portable Document Format (PDF). Он создаёт текстовые поля, флажки, переключатели, поля выбора (список или раскрывающийся список), кнопки и поля подписи; организует их в иерархию parent/child; записывает их как объекты PDF с потоками внешнего вида; может сводить форму в статическое содержимое страницы.

Окно терминала
composer require nextpdf/core:^3

Интерактивная форма PDF — это AcroForm: иерархия полей на уровне документа, конечные поля которой сопоставлены с аннотациями виджетов на страницах. ISO 32000-2 §12.7 определяет эту форму, словари её полей, корень AcroForm и иерархию полей. Этот модуль кодирует эти структуры данных для движка.

FormFieldManager — основной интерфейс. Он предоставляет построители textField(), checkBox(), radioButton(), button() и signatureField(), отслеживает поля и сериализует их с помощью writeFields(). Для каждого виджета он формирует один поток внешнего вида Form XObject (/Subtype /Form, /BBox), как требует §8.10. FormField — объект значения поля. FormFieldDictionaryBuilder преобразует поле в его словарь PDF и применяет записи и флаговые биты, зависящие от типа, к текстовым полям, флажкам, полям выбора и кнопкам. Менеджер и FormField доступны @since 1.0.0. Построитель словаря доступен @since 1.1.0.

FormFieldHierarchy моделирует дерево полей parent/child с помощью addChild(), getRootFieldNames(), getChildren(), getParent() и посетителя walkDepthFirst(). Полное имя поля — это путь через эту иерархию, разделённый точками и соответствующий модели вложенных полей в §12.7.

FormFlattener отрисовывает форму как статическое содержимое страницы. flatten() возвращает FlattenResult, поэтому вы можете зафиксировать заполненную форму для архивирования. FieldMDP и FieldMdpAction моделируют преобразование блокировки полей. Подписанный документ может блокировать именованный набор полей от дальнейших изменений. FieldMdpAction перечисляет варианты области блокировки, а requiresFieldList() указывает, когда явный список полей обязателен. FieldMDP доступен @since 2.0.0.

КлассКлючевые членыРоль
FormFieldManagertextField(), checkBox(), radioButton(), button(), signatureField(), addChildField(), getHierarchy(), writeFields()Построитель полей и сериализатор (@since 1.0.0)
FormFieldобъект значения поляОтдельное поле AcroForm (@since 1.0.0)
FormFieldDictionaryBuilderbuildFieldDictionary(), applyTextFieldOptions(), applyCheckBoxOptions(), applyChoiceFieldOptions(), applyButtonOptions()Построитель словаря поля (@since 1.1.0)
FormFieldHierarchyaddChild(), getRootFieldNames(), getChildren(), getParent(), walkDepthFirst()Дерево полей parent/child (@since 2.0.0)
FormFlattenerflatten(array $fields, array $pages): FlattenResultСводит форму в статическое содержимое (@since 1.0.0)
FieldMDPtoTransformParams()Преобразование блокировки полей (FieldMDP) (@since 2.0.0)
FieldMdpAction (перечисление)requiresFieldList()Область блокировки полей (@since 2.0.0)

Запустите composer docs:generate-api-php -- --module=Form, чтобы сгенерировать полную таблицу PHPDoc.

Исходный код: examples/30-form-fields.php.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Form\FormFieldManager;
$form = new FormFieldManager();
$form->textField(name: 'applicant_name', x: 50, y: 700, w: 200, h: 18);
$form->checkBox(name: 'agree_terms', x: 50, y: 660, size: 12);
$form->radioButton(name: 'plan', x: 50, y: 620, size: 12 /* + option set */);
// The Writer invokes $form->writeFields(...) during document serialization.

Создайте набор полей для документа, который нужно подписать, затем заблокируйте подписанные поля с помощью FieldMDP.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Form\FieldMDP;
use NextPDF\Form\FieldMdpAction;
use NextPDF\Form\FormFieldManager;
$form = new FormFieldManager();
$form->textField(name: 'contract_value', x: 50, y: 700, w: 160, h: 18);
$form->signatureField(name: 'approver_sig', x: 50, y: 600, w: 200, h: 60);
// Lock only the named fields after signing.
$lock = new FieldMDP(
action: FieldMdpAction::Include,
fields: ['contract_value'],
);
$transformParams = $lock->toTransformParams();
// $transformParams is attached to the signature's transform method by the signing layer.
  • Имя поля — полный путь через FormFieldHierarchy с разделением точками. Для средства просмотра два конечных поля с одинаковым полным именем являются одним и тем же логическим полем. За уникальность отвечаете вы.
  • FieldMdpAction::requiresFieldList() сообщает, когда список полей обязателен. Действие Include/Exclude без такого списка создаёт некорректную блокировку; проверяйте этот флаг.
  • FormFlattener::flatten() намеренно удаляет интерактивность. Результат — статическое содержимое. Сохраните интерактивный исходник на случай, если он понадобится позже.
  • Потоки внешнего вида формируются для каждого виджета. Поле без внешнего вида может отображаться по-разному в разных средствах просмотра; дайте менеджеру сформировать внешний вид и не пропускайте этот шаг.
  • signatureField() создаёт только поле-заполнитель. Фактическую подпись формирует слой Security/подписания, а не этот модуль.

Создание и сериализация полей имеют сложность O(n) по числу полей; дополнительно создаётся один поток внешнего вида Form XObject на каждый виджет. Затраты на сведение растут с объёмом отрисованного содержимого, а не с числом полей. Эталонная рабочая нагрузка по умолчанию укладывается в бюджет 1500 мс по времени / 64 МБ по пиковой памяти. Профиль воспроизводимости — structural: номера объектов и /ID в трейлере различаются между запусками. Два документа с одинаковой формой структурно равны, но не идентичны байт-в-байт.

Значения полей формы — пользовательский ввод. Модуль экранирует строковые значения для сериализации PDF с помощью PdfStringEscaper, поэтому значение поля не может выйти за пределы своей строки PDF и внедрить структуру. Если форма зашифрована, шифрование документа AES-256 распространяется на содержимое полей. FieldMDP — механизм безопасности: он блокирует именованные поля от изменения после подписания. Если блокировка полей не соответствует набору подписанных полей, она подрывает этот механизм; задавайте область блокировки осознанно. Рассматривайте любое значение, извлечённое из заполненной формы, как недоверенный ввод. См. модель безопасности движка в /modules/core/security/.

Структуры формы, которые создаёт этот модуль, следуют модели интерактивной формы в ISO 32000-2 §12.7: корень AcroForm, словари полей и иерархия полей документа. Внешний вид каждого виджета формируется как Form XObject согласно §8.10 и прямо задокументирован в коде в src/Form/. tests/Unit/Form/ проверяет эти факты реализации. Это не является заявлением о сквозном соответствии PDF 2.0. Соответствие документа в целом проверяется наборами oracle и golden в /modules/core/conformance/.