stabilité: Expérimental
PageBackfill : tampon de page conservé
Prévisualisation opt-in. Le tampon de page conservé est désactivé par défaut. Lorsqu’il est désactivé, le writer est le sérialiseur en streaming qu’il a toujours été — octet pour octet identique. Ne l’activez que lorsque vous avez réellement besoin de dessiner sur une page antérieure, et lisez d’abord la liste fail-closed ci-dessous.
Par défaut, le writer diffuse les pages en streaming et les vide dans l’ordre ; une fois qu’une page est vidée, elle ne peut plus être dessinée. Le tampon de page conservé est l’opt-in qui retient les pages vidées afin qu’une page précédemment vidée puisse être remplie a posteriori — dessinée sur une page antérieure — avant que le document ne soit sérialisé. L’usage classique est un total ou une boîte de synthèse que vous ne pouvez placer qu’après la mise en page des pages ultérieures.
Installation
Section intitulée « Installation »composer require nextpdf/core:^3Le tampon de page conservé est livré dans le paquet core.
Config::withRetainedPageBuffer() et les méthodes de remplissage a posteriori de
Document sont @since 6.1.0. La valeur par défaut reste le writer en streaming.
ADR-037, qui avait précédemment reporté cette capacité, est désormais consignée
comme implémentée.
Aperçu conceptuel
Section intitulée « Aperçu conceptuel »Config::withRetainedPageBuffer() fait entrer un document dans le mode de pages
conservées. Une fois activé, Document::setActiveBackfillPage(int $pageIndex)
redirige le dessin vers une page antérieure déjà vidée ;
Document::endPageBackfill() ramène le dessin à la position d’ajout normale. Le
contenu que vous écrivez entre les deux appels atterrit sur la page antérieure. Le
tampon retient les pages jusqu’à save(), de sorte que le remplissage a posteriori
est appliqué avant l’écriture de la table de références croisées et du trailer
(ISO 32000-2 §7.5).
Frontière fail-closed — combinaisons refusées
Section intitulée « Frontière fail-closed — combinaisons refusées »Le remplissage a posteriori est une opération à accès aléatoire, et plusieurs fonctionnalités de document supposent des octets en ajout seul, diffusés en streaming. Le tampon de page conservé refuse de se combiner avec n’importe laquelle d’entre elles, indépendamment de l’ordre et avant la sérialisation, afin qu’il ne puisse jamais casser silencieusement une signature ou une revendication de conformité :
- Une signature numérique.
- Le PDF balisé (arbre de structure).
- PDF/A.
- La linéarisation.
- L’empaquetage en flux d’objets.
- Le chiffrement.
- Le mode de rendu CSS Safe.
Un budget d’octets non compressés par document plafonne la quantité que le tampon peut retenir ; un document qui le dépasse échoue durement plutôt que de consommer une mémoire non bornée. Le défaut streaming échoue toujours en mode fail-closed dès qu’un appelant tente un basculement en accès aléatoire sans l’opt-in — activer le tampon est le seul moyen d’obtenir le remplissage a posteriori, et il est incompatible par construction avec les fonctionnalités ci-dessus.
Surface d’API
Section intitulée « Surface d’API »| Symbole | Emplacement | Rôle |
|---|---|---|
Config::withRetainedPageBuffer(bool $enabled = true): self | src/Core/Config.php | Fait entrer un document dans le tampon de page conservé. |
Document::setActiveBackfillPage(int $pageIndex): static | src/Core/Document.php | Redirige le dessin vers une page antérieure déjà vidée. |
Document::endPageBackfill(): static | src/Core/Document.php | Ramène le dessin à la position d’ajout normale. |
Une tentative de remplissage a posteriori qui viole une combinaison refusée lève une exception de configuration typée à la frontière, pas un document corrompu.
Exemple de code — Démarrage rapide
Section intitulée « Exemple de code — Démarrage rapide »Réservez un emplacement sur la page un, remplissez le reste du document, puis remplissez a posteriori l’emplacement réservé avec une valeur calculée à la fin.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;use NextPDF\Core\Document;
$config = (new Config())->withRetainedPageBuffer();
$doc = Document::createStandalone($config);$doc->addPage(); // page 0 — leaves room for a grand total$doc->writeHtml('<h1>Invoice</h1>');
$doc->addPage(); // page 1 — line items$doc->writeHtml('<p>Line items…</p>');$total = 1234.56; // computed after laying out the items
$doc->setActiveBackfillPage(0); // draw back onto page 0$doc->writeHtml('<p>Grand total: ' . number_format($total, 2) . '</p>');$doc->endPageBackfill();
$doc->save(__DIR__ . '/invoice.pdf');Exemple de code — Production
Section intitulée « Exemple de code — Production »Gardez le tampon désactivé pour tout document signé, balisé, PDF/A, linéarisé, chiffré ou en flux d’objets — ce sont exactement les combinaisons que le tampon refuse. Choisissez un chemin explicitement.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;use NextPDF\Core\Document;
function renderReport(bool $needsBackfill, bool $mustBeSigned): Document{ if ($needsBackfill && $mustBeSigned) { // The buffer refuses to combine with signing. Resolve the requirement // before building: pre-compute the value, or sign a separate pass. throw new \LogicException('Back-fill and signing are mutually exclusive.'); }
$config = new Config(); if ($needsBackfill) { $config = $config->withRetainedPageBuffer(); }
return Document::createStandalone($config);}Cas limites et pièges
Section intitulée « Cas limites et pièges »- Désactivé, c’est octet pour octet identique. Avec le tampon désactivé, le writer diffuse en streaming comme avant.
- Mutuellement exclusif avec la signature, le balisage, PDF/A, la linéarisation, les flux d’objets, le chiffrement et le mode de rendu CSS Safe. Le refus est indépendant de l’ordre et se déclenche avant la sérialisation. Planifiez le document pour un mode ou pour l’autre.
- Un budget d’octets échoue durement. Le tampon conservé est borné ; un document qui dépasse le budget d’octets non compressés échoue plutôt que de croître sans limite.
- Appariez les appels. Chaque
setActiveBackfillPage()devrait être apparié à unendPageBackfill()afin que le contenu ultérieur s’ajoute normalement. - Le défaut streaming refuse l’accès aléatoire. Sans l’opt-in, un basculement en accès aléatoire échoue en mode fail-closed. Le tampon est le seul chemin pris en charge.
Performance
Section intitulée « Performance »Le tampon de page conservé échange de la mémoire contre la capacité de remplissage
a posteriori : il retient les pages vidées jusqu’à save(), borné par le budget
d’octets non compressés par document. Le profil mémoire plat du writer en streaming
ne s’applique qu’avec le tampon désactivé. Le performance_budget
(wall_ms: 1500, peak_mb: 128) reflète le plafond mémoire plus élevé du chemin
conservé.
Notes de sécurité
Section intitulée « Notes de sécurité »Le tampon de page conservé n’élargit pas la surface d’entrée ; il change le moment où les octets sont sérialisés, pas ce qui est ingéré. Son refus de se combiner avec le chiffrement et la signature est une propriété de sûreté : un remplissage a posteriori ne peut jamais altérer des octets signés ou chiffrés après coup, car les deux ne peuvent pas être activés ensemble. Le budget d’octets borne la mémoire face à un document hostile.
Conformité
Section intitulée « Conformité »| Énoncé | Spécification | Clause |
|---|---|---|
| Le writer sérialise le corps, la structure de références croisées et le trailer au moment de l’enregistrement. | ISO 32000-2 | §7.5 |
Il s’agit d’une capacité de prévisualisation. NextPDF refuse le tampon de remplissage a posteriori pour les documents signés, balisés, PDF/A, linéarisés, chiffrés et en flux d’objets, de sorte qu’il ne fait aucune revendication de conformité pour ces profils via ce chemin. Aucun texte de norme n’est reproduit.
Adaptateur Compat (TCPDF)
Section intitulée « Adaptateur Compat (TCPDF) »L’adaptateur de compatibilité TCPDF expose cette capacité comme une extension de
constructeur. Construisez l’adaptateur avec retainedPageBuffer: true, puis un
appel setPage() ou lastPage() qui cible une page antérieure délègue au
remplissage a posteriori du core au lieu de lever
UnsupportedFeatureException du streaming. Cet argument de constructeur est une
extension NextPDF, pas une parité avec le TCPDF historique — le TCPDF
historique n’a pas un tel indicateur. Les mêmes refus fail-closed s’appliquent.
Consultez la page tampon de page conservé de l’adaptateur compat pour les détails
côté adaptateur.