Ga naar inhoud
getnextpdf.com

Afbeeldingen, tabellen en lijsten

Alleen tekst maakt zelden een afgewerkt document. In deze tutorial voeg je drie alledaagse bouwstenen toe: een afbeelding, een tabel en een lijst met opsommingstekens. Je schrijft twee kleine scripts, en elk daarvan levert een echt PDF-bestand (Portable Document Format) op dat je meteen kunt openen.

  • 01-image.php — een PDF van één pagina met een kop en een amberkleurige vierkante afbeelding, op een exacte plek op de pagina geplaatst.
  • 02-table-and-lists.php — een PDF van één pagina met een kleine tabel met boeken en daaronder een lijst met opsommingstekens.

Beide scripts zijn complete programma’s. Blijf de projectmap uit de eerste tutorial gebruiken en sla elk script naast composer.json op.

Dit script draagt zijn eigen afbeelding mee. Een piepklein PNG-beeld (Portable Network Graphics) van 8 x 8 pixels reist in het script mee als een Base64-string. Base64 is een schrijfwijze van binaire data in platte tekst, zodat het in broncode kan staan. In een echt project zou je dat deel overslaan, omdat je afbeeldingsbestand al op schijf staat.

Sla dit op als 01-image.php en voer het uit met 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";

Je zou Wrote out/image.pdf op het scherm moeten zien. Open out/image.pdf en je vindt de kop, één regel tekst en een amberkleurig vierkant.

  • Het script decodeert eerst de Base64-string terug naar afbeeldingsbytes en schrijft die naar out/amber-square.png. Dat is alleen een trucje om de tutorial op zichzelf te laten staan. De les begint bij de aanroep van image(), die elk bestaand PNG- of JPEG-bestand (Joint Photographic Experts Group) op dezelfde manier inleest.
  • @mkdir(__DIR__ . '/out') maakt de uitvoermap aan. Het @-teken verbergt de onschuldige waarschuwing die je zou krijgen wanneer de map al bestaat, zodat het script twee keer achter elkaar kan draaien.
  • image() verwacht een bestandspad plus een positie en een afgedrukt formaat. Posities en formaten worden in punten gemeten, en 72 punten zijn gelijk aan één inch. De oorsprong van de pagina is de linkerbovenhoek, dus y: 160 betekent 160 punten omlaag vanaf de bovenkant.
  • Pixels en punten zijn verschillende dingen. De afbeelding is maar 8 x 8 pixels, maar width: 96, height: 96 drukt hem af als een vierkant van één en een derde inch breed. Jij kiest het afgedrukte formaat, niet het aantal pixels.
  • image() plaatst de afbeelding op de exacte plek die je opgeeft. De schrijfpositie die cell() gebruikt, laat het ongemoeid. Eerst de tekst schrijven en daarna de afbeeldingen plaatsen voorkomt dat de twee botsen.
  • NextPDF leest de afbeelding alleen uit een lokaal bestand, nooit vanaf een webadres. Het controleert of het bestand een echt, ondersteund beeld is voordat het wordt ingesloten. Die beveiliging beschermt je wanneer bestandsnamen van gebruikers afkomstig zijn.

Stap 2: Voeg een tabel en een lijst met opsommingstekens toe

Sectie met titel “Stap 2: Voeg een tabel en een lijst met opsommingstekens toe”

Tabellen en lijsten zijn gestructureerde inhoud. De snelste manier om structuur te beschrijven is HTML (Hypertext Markup Language), dezelfde opmaak die webpagina’s gebruiken. NextPDF rendert een ondersteunde set HTML rechtstreeks op de PDF-pagina. Er komt geen browser aan te pas.

Sla dit op als 02-table-and-lists.php en voer het uit met 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";

Je zou Wrote out/table-and-lists.pdf moeten zien. De PDF bevat een kop, een tabel van drie kolommen met een donkere kopregel, en een lijst met opsommingstekens.

  • Het script combineert beide schrijfstijlen op één pagina. cell() drukt de grote kop op de huidige schrijfpositie af. writeHtml() laat vervolgens de tabel en de lijst eronder over de pagina lopen.
  • ln(8) voegt een kleine verticale ruimte van acht punten toe tussen de kop en de HTML-inhoud. Zonder die ruimte zouden de twee dicht tegen elkaar zitten.
  • De tabel gebruikt gewone tabelopmaak: <thead> voor de kopregel, <tbody> voor de datarijen, <th> voor kopcellen en <td> voor datacellen. border="1" tekent de rasterlijnen, en cellpadding="6" voegt wat ademruimte binnen elke cel toe.
  • Kolombreedtes zijn percentages, zoals width: 50%. Ze verdelen de volle breedte van de tabel, zodat de opmaak een verandering van paginaformaat overleeft. Het recept Een HTML-tabel opmaken behandelt koppen, voetteksten en kolombreedtes in detail.
  • De style-attributen gebruiken CSS-declaraties (Cascading Style Sheets), de opmaaktaal van het web. Kleuren, uitlijning en breedtes werken zoals hier getoond. Voordat je op andere eigenschappen vertrouwt, raadpleeg je de CSS-ondersteuningsmatrix.
  • De lijst met opsommingstekens is gewoon <ul> met één <li> per item. NextPDF tekent de opsommingstekens en de inspringing voor je.
  • Een fout die ImageProcessingException vermeldt, betekent dat het afbeeldingsbestand niet gelezen of gedecodeerd kon worden. Controleer het pad, en controleer of het bestand een ondersteund formaat is zoals PNG of JPEG.
  • Een fout die PageLayoutException vermeldt, betekent dat een positie of formaat is afgewezen. Breedte en hoogte moeten groter dan nul zijn, en het pad moet naar een lokaal bestand wijzen, niet naar een webadres.
  • Beide fouten worden beschreven in de referentie voor engine-fouten.
  • Als de tabel er vreemd uitziet, controleer dan eerst de opmaak. Elke <tr>-rij en <td>-cel heeft zijn afsluitende tag nodig.
  • Begin voor al het overige bij de probleemoplossingsgids.

Je pagina’s kunnen nu afbeeldingen, tabellen en lijsten bevatten. In de volgende tutorial laat je een document over meer dan één pagina groeien en houd je het netjes met kopteksten, voetteksten en paginanummers. Voor een diepere duik in de onderwerpen van vandaag behandelt het recept Afbeeldingen in een document insluiten beeldformaten en formaatregels.