Paginar HTML extenso en varias páginas
De un vistazo
Sección titulada «De un vistazo»Distribuye contenido extenso en varias páginas con saltos de página automáticos. Añade un esquema para que el lector pueda saltar entre secciones. Esta recipe toma como referencia examples/12-bookmarks-and-toc.php.
Instalación
Sección titulada «Instalación»composer require nextpdf/core:^3La restricción corresponde al paquete nextpdf/core. El ejemplo se ejecuta en PHP 8.4.
Resumen conceptual
Sección titulada «Resumen conceptual»setAutoPageBreak(true, $margin) indica al motor que inicie una página nueva cada vez que el contenido vaya a sobrepasar el umbral del margen inferior. El motor fragmenta en ese límite el texto extenso escrito mediante multiCell() o writeHtml(). El módulo CSS Fragmentation (css_break_3) está calificado como Verified en la matriz de compatibilidad y respalda el comportamiento de los saltos para la pipeline HTML.
bookmark($title, $level) añade un elemento de esquema que apunta a la posición actual. Un elemento de esquema del PDF asocia un destino para que el usuario pueda saltar directamente a una página (ISO 32000-2). El motor escribe ese destino como la entrada Dest del elemento (ISO 32000-2). El argumento level anida los elementos en una tabla de contenidos jerárquica dentro de la barra lateral del lector.
La pipeline funciona en una sola pasada (ADR-001). La paginación se decide a medida que se emite el flujo, no mediante un árbol de maquetación retenido.
Superficie de la API
Sección titulada «Superficie de la API»setAutoPageBreak(bool $enabled, float $margin = 20): static—NextPDF\Core\Concerns\HasPages.bookmark(string $title, int $level = 0, float $y = -1): static—NextPDF\Core\Concerns\HasNavigation.multiCell(...)/writeHtml(string $html): static—NextPDF\Core\Concerns\HasTextOutput.
La tabla completa de PHPDoc se genera a partir del código fuente.
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;
$doc = Document::createStandalone();$doc->setAutoPageBreak(true, margin: 25);$doc->addPage();$doc->bookmark('Section 1', level: 0);$doc->setFont('helvetica', '', 11);
for ($i = 1; $i <= 80; $i++) { $doc->multiCell(0, 7, "Paragraph {$i} of a long flowing document.");}
$doc->save(__DIR__ . '/out.pdf');Ejemplo de código — Producción
Sección titulada «Ejemplo de código — Producción»Este ejemplo es autónomo y puede ejecutarse con el harness. Construye un documento de varios capítulos con un esquema anidado y saltos de página automáticos, y reproduce examples/12-bookmarks-and-toc.php.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Bookmarks and Navigation');$doc->setPrintHeader(false);$doc->setPrintFooter(false);$doc->setAutoPageBreak(true, margin: 25);
$chapters = [ 'Chapter 1: Introduction' => ['What is NextPDF?', 'Key Features'], 'Chapter 2: Getting Started' => ['Installation', 'Your First PDF'], 'Chapter 3: Advanced Topics' => ['Worker-safe Architecture', 'Streaming Output'],];
$body = 'NextPDF is a modern PDF 2.0 library for PHP. This paragraph is ' . 'repeated so the content overflows the page and the engine inserts ' . 'an automatic page break at the bottom-margin threshold.';
foreach ($chapters as $chapter => $sections) { $doc->addPage(); $doc->bookmark($chapter, level: 0); $doc->setFont('helvetica', 'B', 18); $doc->cell(0, 12, $chapter, newLine: true); $doc->ln(3);
foreach ($sections as $section) { $doc->bookmark($section, level: 1); $doc->setFont('helvetica', 'B', 14); $doc->cell(0, 10, $section, newLine: true); $doc->setFont('helvetica', '', 11); for ($i = 0; $i < 12; $i++) { $doc->multiCell(0, 7, $body); } $doc->ln(4); }}
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');$doc->save($out !== false ? $out : __DIR__ . '/paginate-long-html.pdf');
echo "Wrote paginate-long-html.pdf\n";STDOUT esperado:
Wrote paginate-long-html.pdfCasos límite y trampas
Sección titulada «Casos límite y trampas»- Desactivarlo y olvidarlo. Cuando el salto de página automático está desactivado, el motor recorta el contenido que sobrepasa el margen inferior en lugar de distribuirlo. Volver a activarlo antes de emitir contenido extenso.
- Contenido indivisible. Un único bloque más alto que la altura útil de la página puede provocar
UnsplittableContentException. Entre las causas están una fila de tabla muy alta o una imagen grande. Dividir el contenido de origen. - Marcador antes del contenido. Llamar a
bookmark()en la posición a la que debe apuntar el destino. Colocarlo justo antes del encabezado que se escribe a continuación, en la página deseada. - El encabezado y el pie reservan espacio. Un encabezado o un pie de impresión reduce la altura útil del contenido, y el umbral de salto lo tiene en cuenta. Al desactivar ambos, como hace el ejemplo, se obtiene la altura completa del cuerpo.
- Anidamiento del esquema.
leveles la profundidad de anidamiento. Un hijo enlevel: 1debe seguir a un padre enlevel: 0. De lo contrario, el lector aplana el árbol del esquema.
Rendimiento
Sección titulada «Rendimiento»El motor decide la paginación durante la única pasada de emisión. El costo es lineal respecto de la longitud del contenido, O(n). El presupuesto es wall_ms: 2000, peak_mb: 96. El tiempo de pared es ligeramente mayor que en las recipes de una sola página, debido al ensamblaje del xref de varias páginas y del esquema. El modelo de streaming mantiene la memoria acotada, y el esquema es una lista plana pequeña.
Extracto de la matriz de compatibilidad de CSS (solo filas Verified)
Sección titulada «Extracto de la matriz de compatibilidad de CSS (solo filas Verified)»Solo se reproducen las filas Verified de la matriz de compatibilidad de CSS auditada en cuanto a veracidad.
| Módulo del W3C | Nivel | Estado | Evidencia |
|---|---|---|---|
CSS Fragmentation (css_break_3) | 3 | Verified | src/Html/Fragmentation/, tests/Unit/Html/PagedMedia/ |
CSS Table (css_tables_3) | 3 | Verified | src/Html/Table/ + PDF de referencia |
CSS Cascading and Inheritance (css_cascade_3) | 3 | Verified | src/Html/Cascade/ |
@page proporciona selectores de página con nombre que forman parte de CSS Paged Media. Consultar la matriz para conocer la calificación actual de ese módulo antes de depender de él.
Restricciones del streaming de una sola pasada (ADR-001)
Sección titulada «Restricciones del streaming de una sola pasada (ADR-001)»El motor emite los saltos de página a medida que fluye el stream. No existe un árbol retenido para redistribuir, así que una decisión de salto es definitiva una vez tomada. Cierto contenido necesita su número de página definitivo después de la maquetación, por ejemplo una referencia cruzada. Ese contenido está restringido, así que conviene escribirlo teniendo presente esa limitación.
Contratos de capa (ADR-010)
Sección titulada «Contratos de capa (ADR-010)»La paginación pertenece al controlador de saltos de página, no al analizador. El analizador no emite operadores de transición de página en crudo; solicita un salto mediante el contrato del controlador.
Presupuesto de memoria para documentos extensos
Sección titulada «Presupuesto de memoria para documentos extensos»El modelo de streaming mantiene el búfer de la página actual más la lista plana del esquema, no todas las páginas a la vez. Un documento muy extenso se mantiene dentro del límite de ADR-020 porque el motor descarga las páginas terminadas. Las tablas y los contenedores flex siguen obedeciendo el límite de 5,000 nodos por contexto.
Notas de seguridad
Sección titulada «Notas de seguridad»Un documento hostil no puede forzar un uso de memoria ilimitado. Los límites de elementos y de anidamiento (ADR-001) y el presupuesto de nodos por contexto (ADR-020) acotan el trabajo. Validar la longitud y la estructura del contenido extenso proporcionado por el usuario. El motor renderiza un título de esquema controlado por un atacante como texto, sin interpretarlo nunca.
Conformidad
Sección titulada «Conformidad»| Afirmación | Especificación | Cláusula | reference_id |
|---|---|---|---|
| Cada elemento de esquema puede asociarse con un destino para que el usuario salte directamente a él. | ISO 32000-2 | iso32000_2_sec12#x1.x5.p4 | |
| La entrada Dest de un elemento de esquema nombra el destino que se muestra cuando el elemento se activa. | ISO 32000-2 | iso32000_2_sec12#x1.x11.p30 |
Esta recipe muestra cómo NextPDF distribuye contenido extenso y construye un esquema. CSS Fragmentation está calificado como Verified en la matriz de compatibilidad.
Contexto comercial
Sección titulada «Contexto comercial»No aplica.