Imágenes, tablas y listas
El texto por sí solo rara vez da como resultado un documento terminado. En este tutorial se añaden tres elementos cotidianos: una imagen, una tabla y una lista con viñetas. Se escriben dos scripts pequeños y cada uno produce un archivo PDF (formato de documento portátil) real que se puede abrir de inmediato.
Lo que se va a crear
Sección titulada «Lo que se va a crear»01-image.php: un PDF de una página con un encabezado y una imagen de un cuadrado ámbar, colocada en un punto exacto de la página.02-table-and-lists.php: un PDF de una página con una pequeña tabla de libros y una lista con viñetas debajo.
Ambos scripts son programas completos. Se debe seguir usando la carpeta del
proyecto del
primer tutorial
y guardar cada script junto a composer.json.
Paso 1: colocar una imagen en la página
Sección titulada «Paso 1: colocar una imagen en la página»Este script lleva consigo su propia imagen. Una diminuta imagen PNG (gráficos de red portátiles) de 8 x 8 píxeles viaja dentro del script como una cadena Base64. Base64 es una forma de escribir datos binarios en texto sin formato, por lo que puede figurar en el código fuente. En un proyecto real se omitiría esa parte, porque el archivo de imagen ya existe en el disco.
Guardar esto como 01-image.php y ejecutarlo con php 01-image.php:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
// A tiny 8 x 8 pixel amber PNG, stored as text inside this script.// In a real project the image file already exists on disk, so you// would skip this block and point image() at your own file.$pngBase64 = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAEUlEQVR42mP4Oo8bK2IYWhIAq6BngWh/dt4AAAAASUVORK5CYII=';
@mkdir(__DIR__ . '/out');
$pngPath = __DIR__ . '/out/amber-square.png';$pngBytes = base64_decode($pngBase64, true);if ($pngBytes === false) { fwrite(STDERR, "The embedded image data is damaged.\n"); exit(1);}file_put_contents($pngPath, $pngBytes);
$document = Document::createStandalone();$document->setTitle('Tutorial: images');$document->addPage();
$document->setFont('helvetica', 'B', 20);$document->cell(0, 26, 'A picture inside a PDF', newLine: true);
$document->setFont('helvetica', '', 12);$document->cell(0, 18, 'The amber square below comes from a tiny PNG file.', newLine: true);
// Place the image 72 points (one inch) from the left edge and// 160 points down from the top, printed as a 96 x 96 point square.$document->image($pngPath, x: 72, y: 160, width: 96, height: 96);
$document->save(__DIR__ . '/out/image.pdf');
echo "Wrote out/image.pdf\n";En la pantalla debería aparecer Wrote out/image.pdf. Al abrir
out/image.pdf se encontrará el encabezado, una línea de texto y un cuadrado
ámbar.
Qué acaba de ocurrir
Sección titulada «Qué acaba de ocurrir»- El script primero decodifica la cadena Base64 de nuevo en bytes de imagen y
los escribe en
out/amber-square.png. Eso es solo un truco para que el tutorial sea autónomo. La lección empieza en la llamada aimage(), que lee del mismo modo cualquier archivo PNG o JPEG (Joint Photographic Experts Group) existente. @mkdir(__DIR__ . '/out')crea la carpeta de salida. El signo@oculta la advertencia inofensiva que se obtendría cuando la carpeta ya existe, de modo que el script puede ejecutarse dos veces seguidas.image()recibe una ruta de archivo, además de una posición y un tamaño de impresión. Las posiciones y los tamaños se miden en puntos, y 72 puntos equivalen a una pulgada. El origen de la página es la esquina superior izquierda, por lo quey: 160significa 160 puntos hacia abajo desde la parte superior.- Los píxeles y los puntos son cosas distintas. La imagen mide solo 8 x 8
píxeles, pero
width: 96, height: 96la imprime como un cuadrado de una pulgada y un tercio de ancho. El tamaño de impresión lo decide quien programa; no el número de píxeles. image()coloca la imagen en el punto exacto que se indica. No mueve la posición de escritura que usacell(). Escribir primero el texto y colocar después las imágenes evita que ambos se solapen.- NextPDF lee la imagen únicamente desde un archivo local, nunca desde una dirección web. Comprueba que el archivo sea una imagen real y compatible antes de incrustarla. Esa protección resulta útil cuando los nombres de archivo provienen de los usuarios.
Paso 2: añadir una tabla y una lista con viñetas
Sección titulada «Paso 2: añadir una tabla y una lista con viñetas»Las tablas y las listas son contenido estructurado. La forma más rápida de describir la estructura es HTML (lenguaje de marcado de hipertexto), el mismo marcado que usan las páginas web. NextPDF renderiza un subconjunto compatible de HTML directamente en la página PDF. No interviene ningún navegador.
Guardar esto como 02-table-and-lists.php y ejecutarlo con
php 02-table-and-lists.php:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
@mkdir(__DIR__ . '/out');
$document = Document::createStandalone();$document->setTitle('Tutorial: tables and lists');$document->addPage();
$document->setFont('helvetica', 'B', 20);$document->cell(0, 26, 'A reading list, two ways', newLine: true);$document->ln(8);
$html = <<<'HTML'<h2>The books as a table</h2><table border="1" cellpadding="6" style="width: 100%;"> <thead> <tr style="background-color: #1E3A8A; color: #FFFFFF;"> <th style="width: 50%;">Title</th> <th style="width: 20%; text-align: center;">Year</th> <th style="width: 30%; text-align: right;">Pages</th> </tr> </thead> <tbody> <tr> <td>The Paper Office</td> <td style="text-align: center;">2019</td> <td style="text-align: right;">312</td> </tr> <tr style="background-color: #F8FAFC;"> <td>Ink and Pixels</td> <td style="text-align: center;">2023</td> <td style="text-align: right;">208</td> </tr> </tbody></table>
<h2>Why these two books</h2><ul> <li>Short chapters that fit into a lunch break</li> <li>Worked examples on every page</li> <li>No jargon without an explanation</li></ul>HTML;
$document->writeHtml($html);
$document->save(__DIR__ . '/out/table-and-lists.pdf');
echo "Wrote out/table-and-lists.pdf\n";Debería aparecer Wrote out/table-and-lists.pdf. El PDF contiene un
encabezado, una tabla de tres columnas con una fila de cabecera oscura y una
lista con viñetas.
Qué acaba de ocurrir
Sección titulada «Qué acaba de ocurrir»- El script combina ambos estilos de escritura en una misma página.
cell()imprime el encabezado grande en la posición de escritura actual. Después,writeHtml()va distribuyendo la tabla y la lista por la página, debajo de él. ln(8)añade un pequeño espacio vertical, de ocho puntos de alto, entre el encabezado y el contenido HTML. Sin él, ambos quedarían muy juntos.- La tabla usa el marcado de tabla habitual:
<thead>para la fila de cabecera,<tbody>para las filas de datos,<th>para las celdas de cabecera y<td>para las celdas de datos.border="1"dibuja las líneas de la cuadrícula ycellpadding="6"añade un margen interior en cada celda. - Los anchos de columna son porcentajes, como
width: 50%. Reparten el ancho total de la tabla, de modo que el diseño se mantiene ante un cambio de tamaño de página. La receta Componer una tabla HTML trata en profundidad las cabeceras, los pies y el dimensionado de columnas. - Los atributos
styleusan declaraciones CSS (hojas de estilo en cascada), el lenguaje de estilos de la web. Los colores, la alineación y los anchos funcionan tal como se muestra aquí. Antes de depender de otras propiedades, conviene consultar la matriz de compatibilidad de CSS. - La lista con viñetas es simplemente
<ul>con un<li>por elemento. NextPDF dibuja las marcas de viñeta y la sangría automáticamente.
Si algo salió mal
Sección titulada «Si algo salió mal»- Un error que menciona
ImageProcessingExceptionsignifica que el archivo de imagen no se pudo leer ni decodificar. Conviene comprobar la ruta y verificar que el archivo tenga un formato compatible, como PNG o JPEG. - Un error que menciona
PageLayoutExceptionsignifica que se rechazó una posición o un tamaño. El ancho y el alto deben ser mayores que cero, y la ruta debe apuntar a un archivo local, no a una dirección web. - Ambos errores se describen en la referencia de errores del motor.
- Si la tabla se renderiza de forma extraña, conviene revisar primero el
marcado. Cada fila
<tr>y cada celda<td>necesita su etiqueta de cierre. - Para cualquier otra cosa, conviene empezar por la guía de resolución de problemas.
Siguiente
Sección titulada «Siguiente»Ahora las páginas pueden llevar imágenes, tablas y listas. En el siguiente tutorial se deja que un documento crezca más allá de una página y se mantiene ordenado con encabezados, pies de página y números de página. Para profundizar en los temas de hoy, la receta Incrustar imágenes en un documento trata los formatos de imagen y las reglas de dimensionado.