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

Сведение полей формы в статическое содержимое страницы

Используйте этот рецепт, чтобы свести интерактивную форму AcroForm. NextPDF отрисовывает текущее значение каждого поля в потоке содержимого страницы как обычную графику, а затем удаляет словарь 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). Поскольку NextPDF внедряет значения непосредственно в страницу, устаревший механизм NeedAppearances не требуется.

Профиль — structural. Документ содержит в трейлере /ID; постобработка нормализует его перед сравнением двух прогонов.

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',
'email' => '[email protected]',
'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 — это внешний вид, созданный из его Cryptographic Message Syntax (CMS) SignedData, а не значение, пригодное для повторной отрисовки. Повторная растеризация создала бы статический “фантомный” рисунок, который больше не соответствует ни одной проверяемой подписи. По этой причине механизм сведения намеренно пропускает поля подписи. Сводите форму до подписания, но никогда после.
  • Истинность флажка. Флажок показывает галочку, когда его значение равно Yes/On/1/true. Пустое значение или Off отображает только рамку.
  • Шрифт для сведённого текста. Сведённый текст использует текущий шрифт. Если шрифт не задан, используется Helvetica по умолчанию. Для значений полей на китайском, японском и корейском (CJK) или с пользовательским шрифтом задайте нужный шрифт перед flattenForms().

Сведение масштабируется линейно по числу полей. Для каждого поля NextPDF добавляет небольшой блок содержимого, а затем удаляет объект AcroForm. Типичные формы с запасом укладываются в бюджет 1500 мс / 64 МБ.

Сведение делает значения полей нередактируемыми в обычных программах для чтения. Это изменение представления, а не контроль доступа. Значения остаются видимыми в содержимом страницы, и любой инструмент для работы с текстом может их извлечь. Не рассматривайте сведение как редактирование с удалением данных или как защиту конфиденциальных значений. Для конфиденциальности используйте Шифрование с правами доступа. Там же прочитайте оговорку о зависимости от поведения программы для чтения, поскольку биты прав доступа также не ограничивают чтение. Никогда не сводите подписанный документ. Сначала сведите, затем подпишите.

УтверждениеСпецификацияПунктreference_id (идентификатор ссылки)
Сведённая форма — это неинтерактивное (статическое) представление полей.ISO 32000-2§12.7
Внешний вид поля определяется статически, когда его содержимое известно заранее.ISO 32000-2§12.7
Внедрённые внешние виды делают устаревший флаг NeedAppearances ненужным.ISO 32000-2§12.7

NextPDF создаёт статическую структуру, описанную в приведённых пунктах. Он не заявляет о полном соответствии ISO 32000-2.