Salta ai contenuti
getnextpdf.com

Immagini, tabelle ed elenchi

Il testo da solo raramente basta a comporre un documento finito. In questo tutorial si aggiungono tre elementi costitutivi di uso quotidiano: un’immagine, una tabella e un elenco puntato. Si scrivono due piccoli script e ciascuno produce un vero file PDF (Portable Document Format) che si può aprire immediatamente.

  • 01-image.php — un PDF di una sola pagina con un titolo e un’immagine quadrata color ambra, collocata in un punto preciso della pagina.
  • 02-table-and-lists.php — un PDF di una sola pagina con una piccola tabella di libri e, sotto di essa, un elenco puntato.

Entrambi gli script sono programmi completi. Continuare a usare la cartella di progetto del primo tutorial e salvare ciascuno script accanto a composer.json.

Questo script porta con sé la propria immagine. Una minuscola immagine PNG (Portable Network Graphics) di 8 x 8 pixel viaggia all’interno dello script come stringa Base64. Base64 è una trascrizione in testo semplice di dati binari, quindi può stare nel codice sorgente. In un progetto reale questa parte si ometterebbe, perché il file immagine esiste già su disco.

Salvare questo file come 01-image.php ed eseguirlo 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";

Sullo schermo dovrebbe comparire Wrote out/image.pdf. Aprendo out/image.pdf si trovano il titolo, una riga di testo e un quadrato color ambra.

  • Lo script decodifica dapprima la stringa Base64 riconvertendola nei byte dell’immagine e li scrive in out/amber-square.png. È soltanto l’espediente che rende il tutorial autosufficiente. La lezione inizia dalla chiamata image(), che legge allo stesso modo qualsiasi file PNG o JPEG (Joint Photographic Experts Group) già esistente.
  • @mkdir(__DIR__ . '/out') crea la cartella di output. Il segno @ nasconde l’innocuo avviso che comparirebbe quando la cartella esiste già, così lo script può essere eseguito due volte di seguito.
  • image() accetta il percorso di un file più una posizione e una dimensione di stampa. Posizioni e dimensioni sono misurate in punti, e 72 punti equivalgono a un pollice. L’origine della pagina è l’angolo in alto a sinistra, quindi y: 160 significa 160 punti al di sotto del bordo superiore.
  • Pixel e punti sono cose diverse. L’immagine è di appena 8 x 8 pixel, ma width: 96, height: 96 la stampa come un quadrato largo un pollice e un terzo. È la dimensione di stampa scelta a contare, non il numero di pixel.
  • image() colloca l’immagine nel punto esatto indicato. Non sposta la posizione di scrittura usata da cell(). Scrivere prima il testo e collocare poi le immagini evita che i due elementi si sovrappongano.
  • NextPDF legge l’immagine solo da un file locale, mai da un indirizzo web. Verifica che il file sia un’immagine reale e supportata prima di incorporarla. Questa protezione è utile quando i nomi dei file provengono dagli utenti.

Passo 2: aggiungere una tabella e un elenco puntato

Sezione intitolata “Passo 2: aggiungere una tabella e un elenco puntato”

Tabelle ed elenchi sono contenuti strutturati. Il modo più rapido per descrivere una struttura è l’HTML (Hypertext Markup Language), lo stesso markup usato dalle pagine web. NextPDF esegue il rendering di un insieme supportato di HTML direttamente sulla pagina PDF. Non è coinvolto alcun browser.

Salvare questo file come 02-table-and-lists.php ed eseguirlo 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";

Sullo schermo dovrebbe comparire Wrote out/table-and-lists.pdf. Il PDF contiene un titolo, una tabella a tre colonne con una riga di intestazione scura e un elenco puntato.

  • Lo script combina entrambi gli stili di scrittura in un’unica pagina. cell() stampa il titolo grande alla posizione di scrittura corrente. writeHtml() dispone poi la tabella e l’elenco lungo la pagina, al di sotto di esso.
  • ln(8) aggiunge un piccolo spazio verticale, alto otto punti, tra il titolo e il contenuto HTML. Senza di esso i due elementi risulterebbero appiccicati.
  • La tabella usa il consueto markup delle tabelle: <thead> per la riga di intestazione, <tbody> per le righe di dati, <th> per le celle di intestazione e <td> per le celle di dati. border="1" disegna le linee della griglia e cellpadding="6" aggiunge spazio all’interno di ogni cella.
  • Le larghezze delle colonne sono percentuali, come width: 50%. Suddividono l’intera larghezza della tabella, così che l’impaginazione regga a un cambio di formato pagina. La ricetta Impaginare una tabella HTML tratta in modo approfondito intestazioni, piè di pagina e dimensionamento delle colonne.
  • Gli attributi style usano dichiarazioni CSS (Cascading Style Sheets), il linguaggio di stile del web. Colori, allineamento e larghezze funzionano come mostrato qui. Prima di affidarsi ad altre proprietà, consultare la matrice di supporto CSS.
  • L’elenco puntato è semplicemente <ul> con un <li> per ogni voce. NextPDF disegna automaticamente i punti elenco e il rientro.
  • Un errore che menziona ImageProcessingException indica che il file immagine non è stato letto o decodificato. Controllare il percorso e verificare che il file sia in un formato supportato come PNG o JPEG.
  • Un errore che menziona PageLayoutException indica che una posizione o una dimensione è stata rifiutata. Larghezza e altezza devono essere maggiori di zero e il percorso deve puntare a un file locale, non a un indirizzo web.
  • Entrambi gli errori sono descritti nel riferimento agli errori del motore.
  • Se la tabella viene visualizzata in modo strano, controllare prima il markup. Ogni riga <tr> e ogni cella <td> necessita del proprio tag di chiusura.
  • Per qualsiasi altro caso, iniziare dalla guida alla risoluzione dei problemi.

Le pagine possono ora contenere immagini, tabelle ed elenchi. Nel tutorial successivo si lascia crescere un documento oltre la singola pagina, mantenendolo ordinato con intestazioni, piè di pagina e numeri di pagina. Per approfondire gli argomenti di oggi, la ricetta Incorporare immagini in un documento tratta i formati immagine e le regole di dimensionamento.