Ir al contenido

Migrar de Dompdf a NextPDF

Esta guía muestra cómo migrar una base de código basada en Dompdf a la canalización Html de NextPDF. Dompdf y NextPDF comparten el mismo patrón —cargar HTML, renderizar y emitir un PDF—, por lo que la mayoría de los puntos de llamada se trasladan de forma mecánica. El trabajo principal está en el mapa de opciones y en la diferencia de compatibilidad CSS. NextPDF y Dompdf son motores independientes; por eso, un diseño producido por Dompdf es compatible con el resultado de NextPDF, no idéntico byte a byte. Esta guía cubre el mapeo de verbos, el mapeo de claves de opciones, las diferencias de comportamiento y una secuencia de migración segura.

El hecho de que NextPDF sea compatible con una característica de HTML/CSS no garantiza que un documento de Dompdf determinado se reproduzca píxel por píxel. La matriz de compatibilidad CSS es la autoridad sobre qué características están Verificadas. Esta guía describe el comportamiento; no afirma equivalencia visual.

Ventana de terminal
composer require nextpdf/core:^3

Mantener dompdf/dompdf instalado durante la transición (la secuencia de migración segura ejecuta ambos en paralelo hasta que cada punto de llamada esté migrado); luego, quitarlo una vez completada la migración.

El objeto Dompdf de Dompdf es una fachada única que posee el DOM, la hoja de estilos, el árbol de frames y el lienzo. NextPDF separa estas responsabilidades: un NextPDF\Core\Document posee el modelo de página y la salida, y un único método, writeHtml(), impulsa la canalización HTML. No existe un paso independiente en dos fases para «renderizar y luego emitir». writeHtml() compone el contenido a medida que lo escribe, y el documento se emite con save(), output() o getPdfData().

El contenido de página que escribe NextPDF se expresa como operaciones de pintado en el flujo de contenido de ISO 32000-2 (ISO 32000-2 §8, iso32000_2_sec8#x1.x3.p14). La geometría de página que controla la opción de tamaño de papel se asigna al MediaBox del objeto de página (ISO 32000-2 §7, iso32000_2_sec7#x1.x104.p10). Son fundamentos del motor compartidos por cualquier escritor conforme. Sin embargo, el algoritmo de diseño que convierte el CSS en ese contenido es propio de NextPDF y difiere del de Dompdf (véase Diferencias de comportamiento).

La API Html de NextPDF está documentada en la referencia del módulo Html (autogenerada a partir de PHPDoc). Los puntos de entrada esenciales usados a continuación son: Document::createStandalone(), Document::writeHtml(string $html): static, Document::writeHtmlCell(...), Document::output(?string, OutputDestination), Document::save(string $path): void, Document::getPdfData(): string y el objeto de valor NextPDF\Core\Config (pageSize, margins, fontsDirectory).

Los nombres de la API pública de Dompdf que aparecen a continuación están verificados frente al repositorio público original (dompdf/dompdf, master); véase el sidecar de provenance _source-sidecar-upstream-api.md del repositorio. No se reproduce ningún texto de la documentación original.

DompdfNextPDFNotas
new Dompdf($options)Document::createStandalone($config)Dompdf toma un objeto Options; NextPDF toma un NextPDF\Core\Config. Para workers de larga duración, usar DocumentFactory en lugar de createStandalone().
$dompdf->loadHtml($html, $encoding)$doc->writeHtml($html)NextPDF trata la entrada como UTF-8; transcodificar la entrada que no sea UTF-8 antes de la llamada, en lugar de pasar un argumento de codificación.
$dompdf->loadHtmlFile($file)$doc->writeHtml(file_get_contents($file))NextPDF no tiene una variante de carga de archivos; leer el archivo desde el código de la aplicación para que la política de E/S quede en esa capa.
$dompdf->setPaper($size, $orientation)ConfigpageSize (un objeto de valor PageSize)Consultar el mapa de opciones.
$dompdf->render()(implícito)NextPDF compone el diseño durante writeHtml(); no hay una fase de renderizado separada. Eliminar la llamada a render().
$dompdf->output()$doc->getPdfData()Devuelve los bytes del PDF.
$dompdf->stream($name, $opts)$doc->output($name, OutputDestination::Download)NextPDF separa el destino mediante la enumeración OutputDestination.
$dompdf->setBasePath($p) / setProtocol() / setBaseHost()(la resolución de recursos difiere)NextPDF resuelve los recursos relativos contra el conjunto de trabajo del documento, no contra una tripleta base de path/protocol —consulta Diferencias de comportamiento.
$dompdf->addInfo($label, $value)$doc->setTitle() / setAuthor() / API de metadatosLos pares de información de formato libre de Dompdf se asignan a los setters de metadatos tipados (ISO 32000-2 §14 información del documento, iso32000_2_sec14#x1.x5.p5).
$dompdf->setHttpContext($ctx)(sin equivalente)NextPDF no obtiene recursos remotos a través de un contexto de flujo; consultar No compatible / sin equivalente directo.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
// Dompdf:
// $dompdf = new Dompdf();
// $dompdf->loadHtml('<h1>Invoice</h1>');
// $dompdf->setPaper('A4', 'portrait');
// $dompdf->render();
// file_put_contents('out.pdf', $dompdf->output());
// NextPDF — the createStandalone() default page size is A4 portrait:
$doc = Document::createStandalone();
$doc->setTitle('Invoice');
$doc->addPage();
$doc->writeHtml('<h1>Invoice</h1>');
$doc->save(__DIR__ . '/out.pdf');
echo "Wrote out.pdf\n";

Esto refleja examples/08-html-basic.php (el ejemplo ejecutable que respalda esta guía), con un tamaño de papel y unos márgenes explícitos distintos de los predeterminados. Es el equivalente de un setPaper() de Dompdf más una configuración de márgenes de Options.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Contracts\OutputDestination;
use NextPDF\Core\Config;
use NextPDF\Core\Document;
use NextPDF\ValueObjects\Margin;
use NextPDF\ValueObjects\PageSize;
// Equivalent of: $dompdf->setPaper('letter','portrait') + margin options.
// US Letter portrait = 612 x 792 pt.
// Margin constructor order is (top, right, bottom, left) — all 0.5in here.
$config = new Config(
pageSize: new PageSize(612.0, 792.0, 'Letter'),
margins: new Margin(36.0, 36.0, 36.0, 36.0), // top,right,bottom,left; 0.5in in points
);
$doc = Document::createStandalone($config);
$doc->setTitle('Quarterly Report');
$doc->setAuthor('Finance');
$doc->addPage();
$html = <<<'HTML'
<h1 style="color:#1E3A8A;">Quarterly Report</h1>
<p>This report renders through the NextPDF Html pipeline. The CSS subset that
is <strong>Verified</strong> for production is the support-matrix authority,
not this page.</p>
<table border="1">
<tr><th>Region</th><th>Total</th></tr>
<tr><td>EMEA</td><td>1,204</td></tr>
</table>
HTML;
$doc->writeHtml($html);
// Equivalent of $dompdf->stream('report.pdf'):
$doc->output('report.pdf', OutputDestination::Download);
  • Sin renderizado en dos fases. El código de Dompdf que inspecciona el estado entre render() y output() (por ejemplo leer el número de páginas) no tiene análogo en NextPDF en ese mismo punto de integración. En su lugar, consultar el documento después de writeHtml().
  • Codificación. NextPDF elimina el parámetro $encoding de Dompdf: convertir la entrada a UTF-8 antes de writeHtml(). Pasar bytes Latin-1 produce mojibake, no un error.
  • render() dejado en su sitio. Una llamada de tipo $dompdf->render() que permanezca en el código no tiene método en NextPDF y será un «undefined method» fatal. Eliminarla durante la migración; no sustituirla por un stub.
  • PHP en línea. El enable_php de Dompdf evalúa <script type="text/php">. NextPDF no tiene ninguna ejecución de PHP dentro del documento por diseño (es una superficie de inyección). Mover esa lógica al PHP de la aplicación antes de writeHtml().
  • Resolución de recursos relativos. Dompdf resuelve <img src> contra la tripleta base de path/protocol/host. NextPDF resuelve contra el conjunto de trabajo del documento. Durante la migración, pasar rutas absolutas o URI de datos previamente resueltas para eliminar esa variable.

writeHtml() compone el diseño en una única pasada de streaming (ADR-001). No se conserva ningún objeto intermedio del árbol de frames después del diseño, por lo que la memoria máxima sigue el tamaño del documento en lugar del número de nodos del DOM. El presupuesto de rendimiento para el ejemplo de esta guía es wall_ms: 2000, peak_mb: 128. Documentos grandes: dividir el HTML en límites de addPage() en lugar de construir una única cadena de varios megabytes.

  • Sin obtención remota por contexto de flujo. NextPDF no implementa la vía de obtención remota setHttpContext() / enable_remote de Dompdf. Resolver y validar los recursos remotos en la aplicación, y luego pasar los bytes o las URI de datos. Esto elimina la superficie de SSRF asociada a enable_remote.
  • Sin ejecución de código dentro del documento. La ausencia de un equivalente a enable_php es un endurecimiento deliberado, no una falta de funcionalidad.
  • Los metadatos del documento que se establecen mediante los setters tipados se escriben en el diccionario de información / XMP de ISO 32000-2 §14 (iso32000_2_sec14#x1.x5.p5). No colocar secretos ahí.
DeclaraciónEspecificaciónCláusulareference_id
El contenido de página se expresa como operaciones de pintado en el flujo de contenido del modelo opaque/transparent.ISO 32000-2§8
El tamaño de papel se asigna a la caja delimitadora del objeto de página.ISO 32000-2§7
Las fuentes HTML se escriben como programas de fuentes embedded/subset.ISO 32000-2§9
El procesamiento de espacios en blanco / salto de línea es específico del motor.CSS Text 3§6.5

NextPDF produce contenido ISO 32000-2. No afirma que un documento de Dompdf migrado sea visualmente idéntico. Un cambio de renderer siempre requiere revisar de nuevo la salida.

No aplicable. Core cubre la vía de migración de HTML a PDF que se describe aquí.


Detalle de migración (secciones requeridas por R6)

Sección titulada «Detalle de migración (secciones requeridas por R6)»

Equipos que ejecutan dompdf/dompdf para HTML a PDF del lado del servidor y que quieren adoptar el motor NextPDF. Si solo se llama a loadHtml / setPaper / render / output, el mapeo de verbos cubre toda la superficie.

Dentro del alcance: los verbos de la fachada Dompdf, las claves Options, las expectativas de paridad de características CSS, la resolución de recursos y los metadatos. Fuera del alcance: los objetos internos FrameTree/Canvas/Stylesheet de Dompdf (NextPDF no tiene análogos públicos —no migrar código que acceda a ellos; reemplazarlo por la API pública).

La cobertura es compatibilidad de comportamiento, no un shim drop-in. NextPDF no tiene un shim de clase Dompdf (a diferencia de la vía de TCPDF —consulta /migration/tcpdf-compat/). Reescribir cada punto de llamada usando el mapeo de verbos. Las filas Verificadas de la matriz de compatibilidad CSS determinan por completo la expectativa de características CSS. Esta guía no vuelve a exponer el estado por propiedad.

Opción de Dompdf (clave / setter)NextPDFNotas
default_paper_size / setDefaultPaperSize() ; setPaper($size,...)Config->pageSize (VO PageSize)Los tamaños con nombre se convierten en dimensiones de puntos explícitas; new PageSize(595.276, 841.890, 'A4') es el valor predeterminado de createStandalone().
default_paper_orientation / setDefaultPaperOrientation()intercambia el PageSize (width/height)NextPDF no tiene una marca de orientación; una página apaisada es un PageSize con ancho > alto.
dpi / setDpi()(no es un control global)NextPDF trabaja en puntos PDF (1/72 in); el dimensionado de imágenes es por imagen, no un multiplicador de DPI del documento. Recalcular los tamaños de píxeles fijos a puntos.
enable_remote / setIsRemoteEnabled()(sin equivalente — por diseño)Resolver los recursos remotos en el código de la aplicación; consultar Notas de seguridad.
enable_html5_parser / setIsHtml5ParserEnabled()(siempre analiza el HTML)No hay interruptor; el analizador forma parte de la canalización.
enable_php / setIsPhpEnabled()(sin equivalente — por diseño)El PHP dentro del documento no es compatible; sacar la lógica de la plantilla.
font_dir / setFontDir()Config->fontsDirectoryCadena única del directorio de fuentes.
chroot(resuelve en la app)NextPDF no toma una opción de jaula de sistema de archivos; validar la ruta antes de pasar los bytes.
default_font / setDefaultFont()CSS font-family / fuente registradaEstablecer el valor predeterminado a través de la hoja de estilos base o del registro de fuentes, no de una opción global.
enable_font_subsetting / setIsFontSubsettingEnabled()(siempre crea subconjuntos)NextPDF siempre crea subconjuntos de las fuentes incrustadas (ISO 32000-2 §9, iso32000_2_sec9#x1.x45.p7); no hay una opción «off» —una vía de Dompdf con la marca desactivada no tiene equivalente y no se necesita.
  • Motor de diseño. Dompdf y NextPDF son implementaciones independientes del diseño CSS. El colapso de espacios en blanco y el salto de línea están especificados, pero son sensibles al motor (CSS Text 3 §6.5, css_text_3#x1.x6.x5.p20). Esperar diferencias de salto de línea y de paginación en texto denso. Regenerar las referencias de los diffs visuales tras la migración.
  • Costura de renderizado. Sin separación en dos fases render()/output() (ver Casos límite).
  • Resolución de recursos. Base-path/protocol/host frente al conjunto de trabajo del documento.
  • Modelo de DPI. Puntos frente al multiplicador de DPI de Dompdf.
  • Metadatos. Pares de formato libre addInfo() frente a setters tipados (ISO 32000-2 §14, iso32000_2_sec14#x1.x5.p5).

Estas son diferencias de comportamiento documentadas, no defectos en ninguno de los dos motores.

  • enable_php (PHP dentro del documento) — ausente de forma intencionada.
  • setHttpContext() / enable_remote para obtención remota — ausente de forma intencionada.
  • Acceso público a FrameTree / Canvas / Stylesheet — sin análogo público.
  • dpi como multiplicador global del documento — no modelado.

El código que depende de estos elementos no «migra». Debe eliminarse o reexpresarse en código de aplicación según las filas de arriba.

  1. Añadir nextpdf/core junto a dompdf/dompdf (no quitar Dompdf todavía).
  2. Elegir un documento de bajo riesgo. Reescribir su punto de llamada con el mapeo de verbos; eliminar la llamada a render().
  3. Generar ambos PDF para la misma entrada y compararlos visualmente. Tratar las diferencias como esperadas (motores independientes) y decidir la aceptación por documento.
  4. Convertir el uso de opciones mediante el mapa de opciones; recalcular los tamaños derivados de DPI a puntos.
  5. Resolver previamente los recursos remote/relative a rutas absolutas o URI de datos para eliminar la variable de resolución.
  6. Repetir por documento, de menor a mayor riesgo. Mantener ambos motores instalados hasta que el último punto de llamada se haya migrado.
  7. Quitar dompdf/dompdf de composer.json solo después de la última migración.
  • Capturar la salida de Dompdf de documentos representativos antes de cambiar el código (entradas de referencia, no bytes de referencia —los bytes diferirán).
  • Para cada documento migrado, pasar la salida de NextPDF por la comprobación de aceptación propia (diff visual, aserciones de extracción de texto). El comportamiento de la propia canalización HTML de NextPDF está cubierto por examples/08-html-basic.php y la suite Html de tests/ del core. La aceptación de la migración es específica de cada documento y debe afirmarse en cada caso.
  • Añadir una prueba de regresión por cada documento migrado para detectar futuras actualizaciones del motor.

Cada declaración de comportamiento de NextPDF en esta página está respaldada por una prueba, un ejemplo, una firma de origen o un ADR del repositorio —o, cuando se trata de una propiedad del formato PDF, por las cláusulas de ISO 32000-2 / CSS fijadas con RAG en el citations: del front-matter y la tabla de Conformidad. El comportamiento de dompdf se describe únicamente como «motor independiente — esperar diferencias documentadas». No se afirma ninguna paridad que un artefacto del repositorio no demuestre.

Declaración de comportamiento de NextPDFEvidencia en el repositorio (ruta)
createStandalone() usa A4 vertical (595.276 × 841.890 pt) como página predeterminada.src/Core/Config.php (PageSize(595.276, 841.890, 'A4') predeterminado); tests/Unit/Core/DocumentCreateStandaloneAndConfigWithersEdgeCaseTest.php (createStandaloneWithNullConfigBuildsDocumentWithA4Defaults).
writeHtml() compone el diseño en una única pasada de streaming; sin conservar el DOM tras el diseño.docs/architecture/adr/ADR-001-stream-based-rendering-pipeline.md; src/Core/Concerns/HasTextOutput.php (writeHtml()).
writeHtml() crea automáticamente la primera página cuando no existe ninguna.tests/Unit/Core/Concerns/DocumentTextOutputFontSubsettingAndBorderEdgeCaseTest.php (writeHtmlAutoCreatesFirstPageWhenNoPagesExist).
output() / save() / getPdfData() son los verbos de emisión (sin las dos fases render/output).src/Core/Concerns/HasOutput.php (output(), save(), getPdfData()); tests/Unit/Core/Concerns/DocumentOutputDestinationDispatchTest.php.
El destino de salida es la enumeración NextPDF\Contracts\OutputDestination (Inline/Download/File/String).src/Contracts/OutputDestination.php; tests/Unit/Core/Concerns/DocumentOutputDestinationDispatchTest.php.
Las fuentes HTML siempre se escriben como programas embedded/subset.tests/Unit/Core/Concerns/DocumentTextOutputFontSubsettingAndBorderEdgeCaseTest.php (recordUsedCharactersAffectsFontSubsetting); ISO 32000-2 §9 (citations: del front-matter).
Los setters de metadatos tipados (setTitle/setAuthor) reemplazan al addInfo() de formato libre.src/Core/Concerns/HasMetadata.php (setTitle(), setAuthor()); tests/Unit/Core/Concerns/DocumentInfoMetadataSetterBaselineTest.php.
Canalización HTML de extremo a extremo (el ejemplo ejecutable que respalda esta guía).examples/08-html-basic.php; la suite tests/Unit/Html/ del core.
El espacio en blanco / salto de línea es específico del motor (delta de diseño).CSS Text 3 §6.5 (citations: del front-matter + Conformidad).

Como ambos paquetes permanecen instalados hasta la migración final, revertir un punto de llamada no convertido significa devolver ese punto de llamada concreto a la vía de Dompdf. Tras la migración final, revertir significa restaurar dompdf/dompdf y el punto de llamada anterior desde el control de versiones. No interviene ninguna migración de datos —solo código.

Ver Rendimiento. El modelo de una sola pasada significa que la migración no introduce un costo de retención del árbol de frames. El principal cambio de costo por documento es la resolución anticipada de los recursos (paso 5), que puede almacenarse en caché.

  • Dejar render() en su sitio («undefined method» fatal).
  • Pasar bytes que no sean UTF-8 tras eliminar $encoding (mojibake silencioso).
  • Esperar una salida idéntica byte a byte o píxel a píxel (motores independientes —esta guía nunca afirma un drop-in ni una compatibilidad del 100%).
  • Depender de plantillas enable_php (deben refactorizarse y eliminarse).
  • Tratar la matriz de compatibilidad CSS como orientativa —es la autoridad de características Verificadas sobre lo que se debe esperar.