Migrar de Dompdf a NextPDF
De un vistazo
Sección titulada «De un vistazo»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.
Instalación
Sección titulada «Instalación»composer require nextpdf/core:^3Mantener 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.
Resumen conceptual
Sección titulada «Resumen conceptual»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).
Superficie de la API
Sección titulada «Superficie de la API»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).
Mapeo de verbos de la API
Sección titulada «Mapeo de verbos de la API»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.
| Dompdf | NextPDF | Notas |
|---|---|---|
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 metadatos | Los 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. |
Ejemplo de código — Inicio rápido
Sección titulada «Ejemplo de código — Inicio rápido»<?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";Ejemplo de código — Producción
Sección titulada «Ejemplo de código — Producció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 thatis <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);Casos límite y trampas
Sección titulada «Casos límite y trampas»- Sin renderizado en dos fases. El código de Dompdf que inspecciona el estado entre
render()youtput()(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 dewriteHtml(). - Codificación. NextPDF elimina el parámetro
$encodingde Dompdf: convertir la entrada a UTF-8 antes dewriteHtml(). 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_phpde 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 dewriteHtml(). - 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.
Rendimiento
Sección titulada «Rendimiento»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.
Notas de seguridad
Sección titulada «Notas de seguridad»- Sin obtención remota por contexto de flujo. NextPDF no implementa la vía de obtención remota
setHttpContext()/enable_remotede 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 aenable_remote. - Sin ejecución de código dentro del documento. La ausencia de un equivalente a
enable_phpes 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í.
Conformidad
Sección titulada «Conformidad»| Declaración | Especificación | Cláusula | reference_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.
Contexto comercial
Sección titulada «Contexto comercial»No aplicable. Core cubre la vía de migración de HTML a PDF que se describe aquí.
Ver también
Sección titulada «Ver también»Detalle de migración (secciones requeridas por R6)
Sección titulada «Detalle de migración (secciones requeridas por R6)»Para quién es esto
Sección titulada «Para quién es esto»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.
Alcance
Sección titulada «Alcance»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).
Mapa de compatibilidad
Sección titulada «Mapa de compatibilidad»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.
Mapa de opciones y de configuración
Sección titulada «Mapa de opciones y de configuración»| Opción de Dompdf (clave / setter) | NextPDF | Notas |
|---|---|---|
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->fontsDirectory | Cadena ú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 registrada | Establecer 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. |
Diferencias de comportamiento
Sección titulada «Diferencias de comportamiento»- 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.
No compatible / sin equivalente directo
Sección titulada «No compatible / sin equivalente directo»enable_php(PHP dentro del documento) — ausente de forma intencionada.setHttpContext()/enable_remotepara obtención remota — ausente de forma intencionada.- Acceso público a
FrameTree/Canvas/Stylesheet— sin análogo público. dpicomo 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.
Secuencia de migración segura
Sección titulada «Secuencia de migración segura»- Añadir
nextpdf/corejunto adompdf/dompdf(no quitar Dompdf todavía). - Elegir un documento de bajo riesgo. Reescribir su punto de llamada con el mapeo de verbos; eliminar la llamada a
render(). - Generar ambos PDF para la misma entrada y compararlos visualmente. Tratar las diferencias como esperadas (motores independientes) y decidir la aceptación por documento.
- Convertir el uso de opciones mediante el mapa de opciones; recalcular los tamaños derivados de DPI a puntos.
- Resolver previamente los recursos remote/relative a rutas absolutas o URI de datos para eliminar la variable de resolución.
- Repetir por documento, de menor a mayor riesgo. Mantener ambos motores instalados hasta que el último punto de llamada se haya migrado.
- Quitar
dompdf/dompdfdecomposer.jsonsolo después de la última migración.
Probar la migración
Sección titulada «Probar la 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.phpy la suite Html detests/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.
Evidencia / trazabilidad
Sección titulada «Evidencia / trazabilidad»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 NextPDF | Evidencia 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). |
Reversión
Sección titulada «Reversión»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.
Consideraciones de rendimiento
Sección titulada «Consideraciones de rendimiento»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é.
Trampas comunes
Sección titulada «Trampas comunes»- 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.