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

Создание и предварительное заполнение PDF-формы

AcroForm — это интерактивная форма в PDF. В этом рецепте вы создаёте такую форму и предварительно заполняете её поля начальными значениями. Трейт HasFormFields из Core — API для создания формы: каждое поле создаётся, а его значение задаётся в том же вызове. Для текстовых полей используйте аргумент default, для полей выбора — selected, для флажков — checked. PDF открывается с уже заполненными полями, которые в совместимых программах просмотра остаются редактируемыми. Любой пользователь, открывший файл, по-прежнему сможет изменить эти поля. Этот рецепт основан на примере examples/30-form-fields.php.

Границы области применения. Core создаёт и заполняет поля формы при построении документа. Он не считывает форму, уже существующую в стороннем PDF, и не объединяет её с картой значений. Здесь «заполнение» означает создание формы со значениями, а не загрузку и заполнение внешнего PDF. Полный цикл обработки внешней формы — это возможность Premium и server, а не публичный API Core.

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

Поле AcroForm хранит текущее значение в записи V словаря поля (ISO 32000-2 §12.7). Необязательное значение по умолчанию может храниться в DV; к нему поле возвращается при сбросе формы. NextPDF задаёт V из значения, переданного в конструктор каждого поля. Для отрисовки текста используется строка оформления по умолчанию (DA).

Профиль — structural, потому что документ содержит массив /ID в трейлере. Постобработка нормализует этот изменяемый идентификатор перед сравнением.

NextPDF\Core\Concerns\HasFormFields (подмешан в Document):

  • textField(string $name, float $x, float $y, float $w, float $h, string $default = '', array $options = []): static
  • checkBox(string $name, float $x, float $y, float $size, bool $checked = false): static
  • radioButton(string $name, float $x, float $y, float $size, string $value, string $group): static
  • comboBox(string $name, float $x, float $y, float $w, float $h, array $items, string $selected = ''): static
  • listBox(string $name, float $x, float $y, float $w, float $h, array $items, string $selected = ''): static
  • button(string $name, float $x, float $y, float $w, float $h, string $caption, string $action = ''): static

Аргументы default, checked и selected задают значения для предварительного заполнения.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Pre-filled Form');
$doc->addPage();
// Text field pre-filled with a value (sets the field dictionary /V entry).
$doc->textField(name: 'full_name', x: 20, y: 30, w: 90, h: 8, default: 'Ada Lovelace');
// Choice field pre-selected.
$doc->comboBox(
name: 'country',
x: 20, y: 45, w: 90, h: 8,
items: ['United Kingdom', 'Taiwan', 'Japan'],
selected: 'Taiwan',
);
// Checkbox pre-checked.
$doc->checkBox(name: 'newsletter', x: 20, y: 60, size: 5, checked: true);
$doc->save(__DIR__ . '/prefilled-form.pdf');
echo "Wrote prefilled-form.pdf\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 — Pre-filled');
$doc->addPage();
$doc->setFont('helvetica', 'B', 20);
$doc->cell(0, 14, 'Customer Registration Form', newLine: true);
$doc->ln(4);
$leftMargin = 15.0;
$fieldX = 70.0;
$fieldW = 120.0;
$fieldH = 8.0;
$rowSpacing = 12.0;
// --- Personal information, pre-filled ---
$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,
options: ['maxLen' => 80],
);
$y += $rowSpacing;
}
// --- Choice field, pre-selected ---
$y += 6;
$doc->setXY($leftMargin, $y);
$doc->cell(50, $fieldH, 'Country:');
$doc->comboBox(
name: 'country',
x: $fieldX,
y: $y,
w: $fieldW,
h: $fieldH,
items: ['United States', 'United Kingdom', 'Germany', 'Japan', 'Taiwan'],
selected: 'United Kingdom',
);
// --- Checkboxes, pre-set ---
$y += $rowSpacing + 6;
$doc->setXY($leftMargin, $y);
$doc->cell(0, 7, 'Subscribe to newsletter');
$doc->checkBox(name: 'newsletter', x: $leftMargin + 70, y: $y, size: 5, checked: true);
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');
$doc->save($out !== false ? $out : __DIR__ . '/registration-prefilled.pdf');
echo "Wrote pre-filled registration form\n";

Ожидаемый вывод:

Wrote pre-filled registration form

При открытии PDF каждое поле уже заполнено и остаётся доступным для редактирования.

  • Имена полей должны быть уникальными. Два поля с одинаковым именем в совместимых программах просмотра становятся одним логическим полем с общим значением. Это полезно для связанных полей, но в остальных случаях может оказаться неожиданным.
  • Семантика группы переключателей. radioButton() привязывает каждый вариант к group. Выбранным становится тот вариант, у которого value совпадает со значением группы. В каждой группе одновременно может быть включён только один вариант.
  • maxLen — это подсказка. Параметр maxLen ограничивает длину ввода в совместимых программах просмотра. Он не ограничивает сохранённое значение, которым вы предварительно заполняете поле.
  • В API координаты отсчитываются от верхнего левого угла. Трейт сам преобразует их к принятой в PDF точке отсчёта в нижнем левом углу, поэтому передавайте координаты от верхнего левого угла, как показано в примере.
  • Нет заполнения внешнего PDF. Ни один метод Core не загружает существующую стороннюю форму и не применяет к ней карту значений. См. раздел о границах области применения выше.

Создание формы масштабируется линейно по числу полей. Каждое поле добавляет одну аннотацию-виджет и одно оформление. Несколько сотен полей с запасом укладываются в бюджет 1500 ms / 64 MB.

Предварительно заполненные значения записываются в словарь поля без изменений. Экранируйте или проверяйте любое значение из недоверенного источника, прежде чем помещать его в распространяемый документ. Предварительно заполненная форма сама по себе не защищена: любой, кто может открыть PDF, может прочитать и изменить значения. Если содержимое формы конфиденциально, используйте этот рецепт вместе с Шифрованием с разрешениями и учитывайте указанную там оговорку о зависимости от программы просмотра.

УтверждениеСпецификацияРазделидентификатор ссылки (reference_id)
Текущее значение поля хранится в записи V словаря поля.ISO 32000-2§12.7
Значение по умолчанию хранится в записи DV и восстанавливается при сбросе формы.ISO 32000-2§12.7
Для форматирования текста поля используется строка оформления по умолчанию DA.ISO 32000-2§12.7

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