Aller au contenu

Render manifest : la requête de rendu portable

Un render manifest est une description unique et portable de ce qui doit être rendu : entrée, template, polices, locale, profil de conformité, politique de signature, cible de sortie et indicateur Fast-Web-View. Chaque transport (CLI, intégration à un framework, API SaaS, futur connecteur de flux) construit le même RenderManifest et le soumet. Le contrat est déterministe : deux manifests égaux se sérialisent en un JSON identique à l’octet près, et chaque manifest porte une clé d’idempotence dérivée, ce qui permet de reconnaître et de dédupliquer le même rendu en aval.

Le manifest est un contrat Core. Il définit le schéma ; le moteur et le processeur de flux premium l’exécutent.

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

La voie de construction stable passe par le builder (ou par RenderManifest::fromArray() pour un manifest désérialisé). Le constructeur direct est @internal : les nouveaux champs optionnels sont ajoutés avec des valeurs par défaut, si bien que le builder et fromArray() les absorbent sans casser tes sites d’appel.

examples/manifest/build.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Manifest\OutputObjectKey;
use NextPDF\Manifest\RenderManifestBuilder;
use NextPDF\Manifest\TemplateRef;
$manifest = RenderManifestBuilder::create('invoice-2026-0001')
->withInlineInput('<h1>Invoice 2026-0001</h1>')
->withTemplate(TemplateRef::html())
->withOutputKey(OutputObjectKey::file('invoices', '2026-0001.pdf'))
->withLocale('en-US')
->linearized()
->build();
// Deterministic, canonical-key-order JSON — equal manifests are byte-identical.
$json = $manifest->toJson();
ChampSignification
jobIdIdentifiant logique stable fourni par l’appelant, repris dans les événements et les reçus. Exclu de la clé d’idempotence.
idempotencyKeyClé de déduplication déterministe (voir ci-dessous).
inputSource des données de rendu : payload inline, URI ou référence à un jeu de données accompagnée d’un hash de contenu.
templateFront-end de rendu et identifiant de template optionnel.
fontsEnsemble déclaré de polices (vide par défaut).
localeUne balise de langue BCP-47 (en-US par défaut).
conformanceProfileUn identifiant de profil stable (none par défaut).
signaturePolicyUn identifiant de politique stable (none par défaut).
targetClé de l’objet de sortie, format et politique d’écrasement.
linearizeIndicateur Fast-Web-View ; il se combine avec la linéarisation.
metadataMap key/value de scalaires opaques, reprise dans les événements.

IdempotencyKey::derive() ne hache que le sous-ensemble du manifest déterminant pour le rendu : template, hash du contenu d’entrée, polices, locale, conformité, politique de signature, indicateur linearize et clé de cible. Il exclut délibérément jobId et metadata, si bien que deux requêtes dont les entrées déterminantes pour le rendu sont identiques — y compris la cible de sortie — partagent une clé et peuvent être dédupliquées, même lorsque leurs identifiants de job ou leurs métadonnées de suivi diffèrent. Un appelant peut aussi fournir une clé explicite ; isDerived() indique quelle voie l’a produite.

La version du schéma est fixée par RenderManifest::SCHEMA_VERSION (actuellement 1.0). L’évolution est strictement additive au sein d’une version majeure : un lecteur tolère les clés inconnues d’un schéma mineur plus récent, tandis qu’une version majeure plus récente est rejetée. SchemaCompatibility::assertReadable() applique cette règle lors de fromArray(), et canRead() / isForwardRead() permettent à un appelant de tester la compatibilité sans lever d’exception.

Comme le manifest est un DTO readonly dont le constructeur est @internal, construis-le via le builder ou fromArray(). Les nouveaux champs sont ajoutés comme paramètres de constructeur additifs, avec des valeurs par défaut, si bien que l’ajout d’un champ n’est pas un changement cassant pour ces sites d’appel.

RenderManifestValidator::validate() ne lève pas d’exception et collecte tous les problèmes : il renvoie la liste complète des problèmes trouvés plutôt que d’échouer au premier. Il rejette les clés de sortie dangereuses (traversée, chemins absolus, wrappers de flux), plus d’une source d’entrée, un identifiant de profil de conformité inconnu, une locale BCP-47 invalide et une incohérence de politique d’écrasement. warnings() renvoie des notes indicatives non bloquantes.

use NextPDF\Manifest\RenderManifestValidator;
$problems = (new RenderManifestValidator())->validate($manifest);
if ($problems !== []) {
// Each entry is a stable, human-readable problem string.
}

SingleDocumentRenderer transforme un manifest en un PDF de façon déterministe. Il est pur : il renvoie des octets accompagnés de leur empreinte sha-256 et n’écrit aucun fichier, de sorte que le staging et le commit exactly-once restent du ressort de l’appelant (ou du processeur de flux).

use NextPDF\Manifest\Render\SingleDocumentRenderer;
use NextPDF\Manifest\Render\StandaloneDocumentFactory;
$renderer = new SingleDocumentRenderer(new StandaloneDocumentFactory());
$outcome = $renderer->render($manifest);
$bytes = $outcome->bytes;
$digest = $outcome->sha256;
$pages = $outcome->pageCount;
TypeGenreMembres clésStabilitéDepuis
RenderManifestDTO readonlytoArray(), toJson(), fromArray(), canonicalDigestInput(), SCHEMA_VERSIONstable3.2.0
RenderManifestBuilderbuildercreate(), with*(), linearized(), build()stable3.2.0
IdempotencyKeyvalue objectof(), derive(), equals(), isDerived()stable3.2.0
SchemaCompatibilityhelpercanRead(), isForwardRead(), assertReadable()stable3.2.0
RenderManifestValidatorservicevalidate(), warnings()stable3.2.0
SingleDocumentRendererservicerender(): RenderOutcomestable3.2.0

fromArray() lève RenderManifestException en cas de champ requis manquant ou de version de schéma illisible.