Ir al contenido

Manifiesto de render: la solicitud portable de render

Un manifiesto de render es una descripción única y portable de qué renderizar — entrada, plantilla, fuentes, configuración regional, perfil de conformidad, política de firma, destino de salida y un indicador Fast-Web-View. Cada transporte (la CLI, una integración con un framework, una API SaaS o un futuro conector de stream) construye el mismo RenderManifest y lo envía. El contrato es determinista: dos manifiestos iguales se serializan como JSON idéntico byte a byte, y cada manifiesto lleva una clave de idempotencia derivada para que el mismo render pueda reconocerse y deduplicarse aguas abajo.

El manifiesto forma parte del contrato de Core. Define el esquema; el motor y el procesador de stream premium lo ejecutan.

Ventana de terminal
composer require nextpdf/core:^3

La forma estable de construir un manifiesto es usar el builder (o RenderManifest::fromArray() para un manifiesto deserializado). El constructor directo es @internal: los campos opcionales nuevos se añaden con valores predeterminados, por lo que el builder y fromArray() los absorben sin romper los puntos de llamada existentes.

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();
CampoSignificado
jobIdIdentificador lógico estable del invocador, reflejado en eventos y recibos. Excluido de la clave de idempotencia.
idempotencyKeyClave de deduplicación determinista (ver más abajo).
inputOrigen de los datos del render — una carga útil en línea, un URI o una referencia a un conjunto de datos más un hash del contenido.
templateEl front end de renderizado y un id de plantilla opcional.
fontsConjunto de fuentes declarado (vacío de forma predeterminada).
localeUna etiqueta de idioma BCP-47 (en-US de forma predeterminada).
conformanceProfileUn id de perfil estable (none de forma predeterminada).
signaturePolicyUn id de política estable (none de forma predeterminada).
targetClave del objeto de salida, formato y política de sobrescritura.
linearizeIndicador Fast-Web-View; se combina con la linealización.
metadataMapa key/value escalar y opaco que se refleja en los eventos.

IdempotencyKey::derive() calcula el hash solo sobre el subconjunto determinante del render del manifiesto — plantilla, hash del contenido de entrada, fuentes, configuración regional, conformidad, política de firma, el indicador de linealización y la clave del destino. Excluye deliberadamente jobId y metadata, de modo que dos solicitudes con entradas determinantes del render idénticas — incluido el destino de salida — comparten una clave y pueden deduplicarse, aunque difieran sus ids de trabajo o sus metadatos de seguimiento. Un invocador también puede suministrar una clave explícita; isDerived() indica qué vía la generó.

La versión del esquema está fijada por RenderManifest::SCHEMA_VERSION (actualmente 1.0). La evolución es solo aditiva dentro de una versión mayor: un lector tolera claves desconocidas de una versión menor del esquema más reciente, mientras que rechaza una versión mayor más reciente. SchemaCompatibility::assertReadable() impone esto en fromArray(), y canRead() / isForwardRead() permiten a un invocador comprobar la compatibilidad sin lanzar excepciones.

Como el manifiesto es un DTO readonly cuyo constructor es @internal, debe construirse mediante el builder o fromArray(). Los campos nuevos llegan como parámetros aditivos del constructor y con valores predeterminados, de modo que añadir un campo no rompe esos puntos de llamada.

RenderManifestValidator::validate() no lanza excepciones y recopila todos los problemas: devuelve una lista con cada problema encontrado, en lugar de fallar en el primero. Rechaza claves de salida inseguras (traversal, rutas absolutas, wrappers de stream), más de una fuente de entrada, un id de perfil de conformidad desconocido, una configuración regional BCP-47 inválida y una discrepancia en la política de sobrescritura. warnings() devuelve notas consultivas no bloqueantes.

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

SingleDocumentRenderer convierte un manifiesto en un PDF de forma determinista. La operación es pura: devuelve los bytes junto con su digest sha-256 y no escribe ningún archivo, de modo que el staging y el commit exactamente-una-vez siguen siendo responsabilidad del invocador (o del procesador de stream).

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;
TipoClaseMiembros claveEstabilidadDesde
RenderManifestDTO readonlytoArray(), toJson(), fromArray(), canonicalDigestInput(), SCHEMA_VERSIONestable3.2.0
RenderManifestBuilderbuildercreate(), with*(), linearized(), build()estable3.2.0
IdempotencyKeyobjeto de valorof(), derive(), equals(), isDerived()estable3.2.0
SchemaCompatibilityhelpercanRead(), isForwardRead(), assertReadable()estable3.2.0
RenderManifestValidatorserviciovalidate(), warnings()estable3.2.0
SingleDocumentRendererserviciorender(): RenderOutcomeestable3.2.0

fromArray() lanza RenderManifestException ante un campo requerido ausente o una versión de esquema no legible.