Aller au contenu

Aplatir les champs de formulaire en contenu de page statique

Cette recette aplatit un formulaire AcroForm interactif. Elle dessine la valeur courante de chaque champ dans le flux de contenu de la page, sous forme d’éléments graphiques ordinaires, puis supprime le dictionnaire AcroForm. Le résultat est un formulaire non interactif : une représentation statique des champs dont le rendu est identique partout, même dans un lecteur sans prise en charge des formulaires (ISO 32000-2 §12.7). La recette construit le formulaire à partir de examples/30-form-fields.php, puis appelle flattenForms().

Fenêtre de terminal
composer require nextpdf/core:^3

L’aplatissement « imprime » chaque widget sur sa page. Les champs de texte sont convertis en texte BT … Tj … ET. Les cases à cocher et les boutons radio deviennent des tracés dessinés. Les champs de choix affichent l’élément sélectionné. Les boutons-poussoirs affichent une boîte statique en forme de bouton. Ce comportement correspond au modèle de la spécification : une apparence définie statiquement, utilisée lorsque le contenu du champ est connu à l’avance (ISO 32000-2 §12.7). Comme les valeurs sont figées, le mécanisme NeedAppearances déprécié n’est pas nécessaire.

Le profil de reproductibilité est structural. Le document contient un /ID de trailer que la passe finale normalise avant de comparer deux exécutions.

NextPDF\Core\Concerns\HasFormFields::flattenForms(): static aplatit chaque champ créé dans le document en contenu de page statique et supprime l’AcroForm. S’il n’y a aucun champ, elle ne fait rien. En interne, elle délègue l’opération à NextPDF\Form\FormFlattener.

Construis le formulaire avec les constructeurs de champs. Pour le détail des étapes, consulte Construire et préremplir un formulaire PDF. Appelle ensuite flattenForms() avant 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";

L’exemple complet ci-dessous construit le formulaire multi-sections à partir de examples/30-form-fields.php. Il préremplit le formulaire, l’aplatit, puis écrit la sortie dans NEXTPDF_COOKBOOK_OUTPUT pour le harnais.

<?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";

Sortie attendue :

Wrote flattened registration form

La sortie affiche les mêmes valeurs, mais sans champs interactifs. Un lecteur sans prise en charge des formulaires l’affiche de la même façon.

  • L’aplatissement est irréversible. Après l’appel à save(), les champs interactifs ont disparu. Conserve la source non aplatie si tu dois modifier les valeurs plus tard.
  • Ordre des appels. Exécute flattenForms() après avoir créé les champs et avant save(). L’appeler sans champ ne fait rien, ce qui est sans danger.
  • Les champs de signature ne sont pas aplatis. La surface visuelle d’un champ /Sig est l’apparence produite à partir de sa structure CMS SignedData, et non une valeur pouvant être réaffichée. La redessiner créerait un graphique « fantôme » statique qui ne correspondrait plus à aucune signature vérifiable. Pour cette raison, l’outil d’aplatissement ignore délibérément les champs de signature. Aplatis le formulaire avant de signer, jamais après.
  • Valeurs considérées comme cochées. Une case à cocher affiche sa coche quand sa valeur vaut Yes/On/1/true. Une valeur vide ou Off n’affiche que la boîte.
  • Police du texte aplati. Le texte aplati utilise la police courante. Si aucune police n’est définie, il utilise Helvetica par défaut. Pour des valeurs de champ en CJK ou avec une police personnalisée, définis la police voulue avant flattenForms().

L’aplatissement évolue linéairement avec le nombre de champs. Pour chaque champ, il ajoute un bloc de contenu délimité, puis supprime l’objet AcroForm. Sur des formulaires courants, il reste largement dans le budget de 1500 ms / 64 Mo.

L’aplatissement rend les valeurs des champs non modifiables dans les lecteurs ordinaires. C’est un changement de présentation, pas un contrôle d’accès. Les valeurs restent visibles dans le contenu de la page, et n’importe quel outil de texte peut les extraire. Ne considère pas l’aplatissement comme un caviardage ni comme une protection des valeurs sensibles. Pour la confidentialité, utilise Chiffrer avec des permissions. Lis aussi la mise en garde sur la coopération du lecteur présentée dans cette page, puisque les bits de permission n’imposent pas non plus de restrictions de lecture. N’aplatis jamais un document signé. Aplatis d’abord, puis signe.

DéclarationSpécificationArticlereference_id
Un formulaire aplati est une représentation non interactive (statique) des champs.ISO 32000-2§12.7
L’apparence du champ est définie statiquement lorsque son contenu est connu à l’avance.ISO 32000-2§12.7
Les apparences figées rendent inutile le drapeau NeedAppearances déprécié.ISO 32000-2§12.7

NextPDF produit la structure statique décrite par les articles cités. Il ne revendique pas de conformité globale à ISO 32000-2.