Ga naar inhoud
getnextpdf.com

Kopteksten, voetteksten en documenten met meerdere pagina's

Eén pagina is zelden genoeg. In deze tutorial schrijf je een document dat vanzelf uitgroeit tot drie pagina’s. Je geeft elke pagina ook een terugkerende koptekst en een voettekst die het paginanummer toont.

Je schrijft één script, 01-multipage.php. Het produceert een reisdagboek van drie pagina’s als een PDF-bestand (Portable Document Format):

  • De dagboeknotities lopen automatisch van pagina naar pagina door. Je geeft nooit aan waar een pagina eindigt; de engine beslist dat.
  • Een koptekst is een strook boven aan een pagina die op elke pagina wordt herhaald. De jouwe toont de documenttitel.
  • Een voettekst is de bijbehorende strook onderaan. De jouwe toont het paginanummer als 1 / 3, 2 / 3 en 3 / 3.

Alles draait alleen met het nextpdf/core-pakket: geen lettertypebestanden, geen extra extensies en geen netwerk.

Twee ideeën doen al het werk in dit script.

Het eerste is het automatische pagina-einde. Terwijl de engine tekst schrijft, houdt hij een cursor bij: de plek op de pagina waar de volgende regel terechtkomt. setAutoPageBreak(true, margin: 25) vertelt de engine om die cursor in de gaten te houden. Wanneer die binnen 25 punten (ongeveer een derde inch) van de onderrand komt, sluit de engine de pagina en begint een nieuwe.

Het tweede zijn de pagina-elementen: de koptekst en de voettekst. Je beschrijft ze één keer, vóór de eerste pagina. setHeaderData() legt de titel en een korte beschrijving voor de bovenste strook vast. De font- en margin-aanroepen kiezen het lettertype en de afstand tot de paginarand. De engine tekent deze elementen vervolgens op elke pagina die hij aanmaakt, inclusief de pagina’s die hij zelf toevoegt.

Maak 01-multipage.php aan in je projectmap:

<?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";

Voer het uit met php 01-multipage.php. Het script print één regel:

Wrote out/travel-journal.pdf with 3 pages

Open out/travel-journal.pdf en scroll erdoorheen. De titelstrook staat boven aan alle drie de pagina’s en de paginanummers lopen rechtsonder op.

De schrijflus noemt nooit pagina’s. Hij schrijft elke dagkop met cell(), die één regel in een onzichtbaar kader plaatst. Hij schrijft de notities met multiCell(), die lange tekst over zoveel regels als nodig laat teruglopen. Zesendertig notities passen niet op één pagina, dus het automatische pagina-einde treedt twee keer in werking. Zo wordt het dagboek precies drie pagina’s.

De koptekst en voettekst zijn geconfigureerd vóór de eerste addPage()-aanroep. Die volgorde is belangrijk: een pagina die al is getekend, wordt daarna niet meer bijgewerkt. Configureer de elementen eerst, dan komt elke pagina consistent uit.

Je hebt het paginanummer nooit zelf getekend. De voettekst print het standaard; je koos alleen het lettertype en de afstand tot de paginarand. Terwijl de engine pagina’s schrijft, kent hij het uiteindelijke aantal nog niet. Daarom laat hij in elke voettekst een tijdelijke aanduiding staan en vult hij het echte totaal in wanneer je opslaat.

Twee kleine details maken het script compleet. @mkdir maakt de map out aan, en het @-teken houdt PHP stil wanneer de map al bestaat. getNumPages() vraagt de engine hoeveel pagina’s de lay-out heeft opgeleverd, zodat het slotbericht het echte aantal kan melden.

  • Een “failed to open stream”-fout op de require-regel betekent dat het script vendor/autoload.php niet kon vinden. Voer het uit in de projectmap die vendor/ bevat.
  • Staat alles op één pagina en is het einde van de tekst afgekapt? Dan staan automatische pagina-einden uit. Behoud de regel setAutoPageBreak(true, margin: 25) en plaats hem boven de schrijflus.
  • Een verkeerd getypte lettertypefamilie gooit een exception die het lettertype noemt dat niet gevonden kon worden. Controleer de spelling van helvetica en zie Lettertypen en tagging voor diepere lettertypeproblemen.
  • Voor al het andere koppelt de probleemoplossingshub symptomen aan oorzaken, en legt de foutreferentie de algemene exceptions van de engine uit en hoe je van elke fout herstelt.

Je documenten kunnen nu tot elke lengte uitgroeien en er toch afgewerkt uitzien. In de volgende tutorial schrijf je je inhoud in HTML (Hypertext Markup Language) en laat je de engine er pagina’s van maken.

Wanneer je meer controle wilt over de onderwerpen uit deze tutorial, gaan twee recipes dieper: