Salta ai contenuti
getnextpdf.com

Intestazioni, piè di pagina e documenti multipagina

Una sola pagina raramente basta. In questo tutorial si scrive un documento che cresce da solo fino a tre pagine. Si assegna inoltre a ogni pagina un’intestazione ripetuta e un piè di pagina che mostra il numero di pagina.

Si scrive un unico script, 01-multipage.php. Produce un diario di viaggio di tre pagine come file PDF (Portable Document Format):

  • Le voci del diario fluiscono automaticamente da una pagina all’altra. Non si indica mai dove finisce una pagina; decide il motore.
  • Un’intestazione è una striscia nella parte superiore della pagina che si ripete su ogni pagina. In questo caso mostra il titolo del documento.
  • Un piè di pagina è la striscia corrispondente in basso. In questo caso mostra il numero di pagina come 1 / 3, 2 / 3 e 3 / 3.

Tutto funziona con il solo pacchetto nextpdf/core: nessun file di font, nessuna estensione aggiuntiva e nessuna rete.

Due idee svolgono tutto il lavoro in questo script.

La prima è l’interruzione di pagina automatica. Mentre il motore scrive il testo, tiene traccia di un cursore: il punto della pagina in cui andrà la riga successiva. setAutoPageBreak(true, margin: 25) indica al motore di sorvegliare quel cursore. Quando arriva entro 25 punti (circa un terzo di pollice) dal bordo inferiore, il motore chiude la pagina e ne apre una nuova.

La seconda è la struttura fissa della pagina: l’intestazione e il piè di pagina. Si descrivono una sola volta, prima della prima pagina. setHeaderData() registra il titolo e una breve descrizione per la striscia superiore. Le chiamate al font e al margine scelgono i caratteri e la distanza dal bordo della pagina. Il motore disegna poi questi elementi fissi su ogni pagina che crea, comprese quelle che aggiunge da sé.

Creare 01-multipage.php nella cartella del progetto:

<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
// Make sure the output folder exists next to this script.
@mkdir(__DIR__ . '/out');
$document = Document::createStandalone();
$document->setTitle('NextPDF Travel Journal');
// Configure the header and footer BEFORE the first page.
// The engine repeats them on every page for you.
$document->setHeaderData(title: 'NextPDF Travel Journal', description: 'A multi-page tutorial document');
$document->setHeaderFont('helvetica', 10);
$document->setHeaderMargin(5);
$document->setFooterFont('helvetica', 8);
$document->setFooterMargin(10);
// Turn on automatic page breaks. When the text cursor gets within
// 25 points of the bottom edge, the engine starts a new page.
$document->setAutoPageBreak(true, margin: 25);
$document->addPage();
$document->setFont('helvetica', 'B', 18);
$document->cell(0, 12, 'Travel journal: three days on the coast', newLine: true);
$document->ln(5);
$days = [
1 => 'We followed the shoreline north and counted seventeen lighthouses.',
2 => 'Rain moved in before noon, so we sketched the harbor from a cafe window.',
3 => 'On the last morning the fog lifted and the whole bay turned silver.',
];
foreach ($days as $day => $highlight) {
$document->setFont('helvetica', 'B', 14);
$document->cell(0, 10, "Day {$day}", newLine: true);
$document->setFont('helvetica', '', 11);
for ($entry = 1; $entry <= 12; $entry++) {
$text = "Entry {$entry} of day {$day}. {$highlight} "
. 'The trail hugged the cliffs for most of the afternoon, and every '
. 'turn opened another view of the water. We stopped often to take '
. 'notes, compare maps, and argue happily about where to eat dinner. '
. 'By the time we reached the guesthouse, our boots were soaked and '
. 'our notebooks were full.';
$document->multiCell(0, 7, $text);
$document->ln(3);
}
$document->ln(5);
}
// Ask the engine how many pages the layout produced, then save.
$pages = $document->getNumPages();
$document->save(__DIR__ . '/out/travel-journal.pdf');
echo "Wrote out/travel-journal.pdf with {$pages} pages\n";

Eseguirlo con php 01-multipage.php. Lo script stampa una sola riga:

Wrote out/travel-journal.pdf with 3 pages

Aprire out/travel-journal.pdf e scorrerlo. La striscia del titolo si trova nella parte superiore di tutte e tre le pagine e i numeri di pagina aumentano in basso a destra.

Il ciclo di scrittura non menziona mai le pagine. Scrive l’intestazione di ogni giorno con cell(), che colloca una riga in un riquadro invisibile. Scrive le voci con multiCell(), che manda a capo il testo lungo su tutte le righe necessarie. Trentasei voci non entrano in una sola pagina, quindi l’interruzione di pagina automatica scatta due volte. È così che il diario diventa esattamente di tre pagine.

L’intestazione e il piè di pagina sono stati configurati prima della prima chiamata a addPage(). Quell’ordine conta: una pagina già disegnata non si aggiorna in seguito. Configurare prima gli elementi fissi e ogni pagina risulterà coerente.

Il numero di pagina non è mai stato disegnato. Il piè di pagina lo stampa in modo predefinito; se ne sono scelti soltanto il font e la distanza dal bordo della pagina. Mentre il motore scrive le pagine, non può ancora conoscere il conteggio finale. Perciò lascia un segnaposto in ogni piè di pagina e inserisce il totale reale al momento del salvataggio.

Due piccoli dettagli completano lo script. @mkdir crea la cartella out e il segno @ fa sì che PHP resti silenzioso quando la cartella esiste già. getNumPages() chiede al motore quante pagine ha prodotto il layout, così il messaggio finale può riportare il conteggio reale.

  • Un errore «failed to open stream» sulla riga require significa che lo script non ha trovato vendor/autoload.php. Eseguirlo all’interno della cartella del progetto che contiene vendor/.
  • Tutto sta in un’unica pagina e la fine del testo risulta tagliata? Allora le interruzioni di pagina automatiche sono disattivate. Mantenere la riga setAutoPageBreak(true, margin: 25) e tenerla sopra il ciclo di scrittura.
  • Un nome della famiglia di font digitato in modo errato genera un’eccezione che segnala il font mancante. Controllare l’ortografia di helvetica e consultare Font e tagging per problemi di font più complessi.
  • Per qualsiasi altro caso, l’hub di risoluzione dei problemi mette in relazione i sintomi con le cause e il riferimento agli errori spiega le eccezioni generali del motore e come recuperare da ciascuna.

I documenti possono ora crescere fino a qualsiasi lunghezza e apparire comunque completi. Nel prossimo tutorial si scrive il contenuto in HTML (Hypertext Markup Language) e si lascia che il motore lo trasformi in pagine.

Per un controllo più preciso sugli argomenti di oggi, due ricette approfondiscono: