FPDF-Tutorial: Ein PDF erstellen und Text ausgeben

FPDF-Tutorial: Ein PDF erstellen und Text ausgeben
Von Lars Ebert am 12.08.13, 11:00
Kategorien: Allgemein, PHP and Programmieren

Mit FPDF kann man sehr flexibel automatisch PDF-Dateien generieren. Damit lassen sich viele Aufgaben automatisieren, wie zum Beispiel die Generierung von Rechnungen und anderen Dokumenten. FPDF ist sehr flexibel und kompliziert, was aber dazu führt, dass beliebig komplexe PDFs erstellt werden können.

In diesem Artikel möchte ich Dir am Beispiel einer Rechnung zeigen, wie Du mit FPDF arbeiten kannst. In den folgenden Artikeln werde ich immer komplexere Anwendungsbeispiele durchgehen, sodass immer neue Probleme gelöst werden. Nun beginnen wir aber zur Einführung mit einer einfachen Rechnung.

Artikelserie: FPDF-Tutorial - PDF-Generierung mit PHP

Dieser Artikel ist Teil einer mehrteiligen Artikelserie. Lies dir auch die restlichen Teile durch!

  1. FPDF-Tutorial: Ein PDF erstellen und Text ausgeben
  2. FPDF-Tutorial: Blocksatz und Fließtext
  3. FPDF-Tutorial - Rechnungs-Posten und mehrspaltiger Text

Schritt 1: Download von FPDF

Bevor wir beginnen können, musst Du dir FPDF herunterladen. Besuche dazu die Download-Seite von fpdf und lade die aktuellste Version (momentan Version 1.7) herunter.

Schritt 2: Eine Klasse für Rechnungs-PDFs

FPDF biete uns nun eine abstrakte Klasse, welche uns die grundlegenden Werkzeuge zur Erstellung von PDFs an die Hand gibt. Diese Klasse müssen wir nun zu unser eigenen Klasse erweitern, damit wir mit dieser dann Rechnungs-PDFs generieren können.

<?php
	
	require_once('fpdf17/fpdf.php');
	
	class invoice extends fpdf
	{
		
	}
	
?>

Schritt 3: PDF einrichten und erste Seite anlegen

<?php
	
	require_once('fpdf17/fpdf.php');
	
	class invoice extends fpdf
	{
		private $invoiceNumber, $date, $sum = 0;
		private
			$rightColumnX = 150,
			$leftColumnWidth,
			$gutter = 6,
			$leftMargin = 20,
			$topMargin = 40,
			$rythm = 4.7;
		
		public function __construct($invoiceNumber, $date) {
			$this->invoiceNumber = $invoiceNumber;
			$this->date = $date;
			
			$this->leftColumnWidth = $this->rightColumnX - $this->leftMargin - $this->gutter;
			
			parent::__construct();
			
			$this->SetDrawColor(0, 0, 0);
			$this->SetTextColor(0, 0, 0);
			
			$this->SetLeftMargin($this->leftMargin);
			$this->SetTopMargin($this->topMargin);
			$this->addPage();
		}
	}
	
?>

Die Rechnung wird die Eigenschaften Rechnungs-Nummer, Datum und Summe haben, für diese haben wir jeweils eine Eigenschaft angelegt. Außerdem definieren wir eine Reihe von Maßen für das spätere PDF. Die Maße werden alle in Pt angegeben.

Dem Konstruktor können später Rechnungs-Nummer und -Datum übergeben werden. Außerdem werden die Schrift- und Zeichenfarbe auf Schwarz gesetzt und die Seitenränder definiert. Schließlich legen wir mit addPage() die erste Seite des PDFs an.

Schritt 4: Header des PDFs

Am Anfang und Ende jeder Seite werden automatisch die Methoden Header und Footer aufgerufen. In der Klasse FPDF tun diese Methoden gar nichts. Aber in unserer Kind-Klasse können wir diese Methoden übeschreiben und so dafür sorgen, dass ein Kopf und Fuß angezeigt werden.

public function Header() {
	$this->SetFont('Helvetica', 'B', 16);
	$this->Cell($this->leftColumnWidth + $this->gutter, 0, 'Rechnung ' . $this->invoiceNumber);
	
	$this->SetFont('Helvetica', '', 7);
	$this->Cell(0, 0, $this->date->format('d. F Y'));
	
	$this->ln($this->rythm * 3);
}

Die Methode SetFont legt die verwendete Schriftart fest. FPDF liefert schon eine kleine Anzahl an Schriften mit. Welche das sind, kannst Du Dir im Ordner »fonts« ansehen. In unserem Fall definieren wir als Schriftart Helvetica. Mit dem zweiten Parameter können wir zusätzlich noch bold und italic aktivieren. Der dritte Parameter schließlich defninert die Schriftgröße in Pt.

Mit der Methode Cell können wir schließlich Text in das PDF schreiben. Hierbei definiert der erste Parameter die Breite dieser Zelle, der zweite Parameter die Höhe der Zelle und der dritte Parameter den Text, der angezeigt werden soll.

Mit der Methode ln können wir einen Zeilenumbruch erzwingen. Der Parameter definiert dabei, wie weit nach unten die nächste Zeile rutschen soll.

Schritt 5: Benutzen der Rechnungs-Klasse

Bisher haben wir nur eine Klasse definiert, die eine Rechnung erstelle kann. Um nun eine Rechnung zu erstellen, müssen wir diese Klasse auch benutzen.

Dazu legen wir nun die neue Datei an.

<?php
	
	$items = array(
		array(
			'name' => 'Produkt 1',
			'description' => 'Lorem ipsum ad qui amet dolore, vitae cetero quaerendum mel ea. Facilis fastidii duo no.',
			'unitprice' => 5.2,
			'quantity' => 3
		),
		array(
			'name' => 'Produkt 2',
			'description' => 'Lorem ipsum ad qui amet dolore, vitae cetero quaerendum mel ea. Facilis fastidii duo no.',
			'unitprice' => 1,
			'quantity' => 9
		),
		array(
			'name' => 'Produkt 3',
			'description' => 'Lorem ipsum ad qui amet dolore, vitae cetero quaerendum mel ea. Facilis fastidii duo no.',
			'unitprice' => .99,
			'quantity' => 18
		)
	);
	
	$invoiceNumber = date('Ymd') . '-' . rand(0, 100);
	$date = new DateTime();
	
	require_once('invoice.php');
	
	$invoice = new Invoice($invoiceNumber, $date);
	
	$invoice->output();
	
?>

Die relevanten Zeilen hier sind die Zeilen 27 bis 31. Hier inkludieren wir unsere eben erstellte Klasse, erstellen eine Instanz dieser Klasse (als eine Rechnung), welcher wir sofort das Datum und die Rechnungsnummer übergeben, und schließlich sorgen wir mit der Methode output dafür, dass das PDF ausgegeben wird.

Rufen wir diese Datei jetzt auf, wird das PDF generiert und uns direkt angezeigt.

Bis hierhin scheint alles sehr gut zu funktionieren. Allerdings haben wir ein kleines Problem, was nicht auf den ersten Blick auffällt. Die Übeschrift und das Darum haben wir in die gleiche Zeile geschrieben, aber diese werden anhand der vertikalen Mitte ausgerichtet, nicht an ihrer Grundlinie. Um dieses Problem deutlich sichtbar zu machen, verändern wir den Code ein wenig:

$this->Cell($this->leftColumnWidth + $this->gutter - 65, 0, 'Rechnung ' . $this->invoiceNumber);

Ich habe hier dafür gesorgt, dass die Zelle, in der die Überschrift ausgegeben wird, etwas schmaler wird.

Hinweis: Denk unbedingt daran, diese Änderung am Endes des Artikels wieder rückgängig zu machen. Dies ist schließlich nur ein Test.

Die beiden Text-Elemente werden anhand ihrer virtuellen Mitte ausgerichtet, nicht anhand der Grundlinie. Die beiden Text-Elemente werden anhand ihrer virtuellen Mitte ausgerichtet, nicht anhand der Grundlinie.

Dieses kleine Problem müssen wir nun erst einmal beheben.

Schritt 6: Anpassen von FPDF-Methoden

Um dafür zu sorgen, dass alle Texte an ihrer Grundlinie ausgerichtet werden, können wir die Cell-Methode von FPDF sehr leicht anpassen.

Dazu überschreiben wir diese einfach.

public function Cell($w, $h=0, $text='', $border=0, $ln=0, $align='', $fill=false, $link='') {
	$startX = $this->GetX();
	$startY = $this->GetY();
	
	$this->SetY($startY - $this->FontSize / 2 * .6);
	$this->SetX($startX);
	
	parent::Cell($w, $h, $text, $border, $ln, $align, $fill, $link);
	
	$endX = $this->GetX();
	$endY = $this->GetY();
	
	$this->SetY($startY);
	$this->SetX($endX);
}

Wichtig ist, dass die neue Methode die gleichen Parameter akzeptieren muss, wie die bisherige Methode. Diese können wir einfach so stehen lassen.

Alle Texte müssen so nach oben verschoben werden, und zwar um genau die Differenz zwischen Grundlinie und Mittellinie.

Bevor wir beginnen, die aktuelle Position zu verändern, speichern wir diese in den Variablen $startX und $startY. Die aktuelle Position könnnen wir mit den Methoden GetX und GetY ermitteln.

Anschließend verschieben wir die aktuelle Position um den benötigten Betrag nach oben. Danach müssen wir die X-Position auch neu setzen, denn durch das Setzen der Y-Position wird diese wieder nach ganz links verschoben. Nun können wir die Original-Methode Cell benutzen, um den Text auszugeben. Danach setzen wir die Y-Position wieder zurück.

Schauen wir uns das PDF nun erneut an, stellen wir fest, dass nun der Text korrekt an der Grundlinie ausgerichtet wird.

Wie geht es weiter?

Im nächsten Teil dieser Artikelserie werden wir uns darum kümmern, die Posten der Rechnung und den Rechnungs-Text auszugeben. Dazu werden wir uns außerdem ansehen, wie man in FPDF einen Blocksatz ausgeben lassen kann.

Nächster Artikel der Serie

Dieser Artikel ist Teil der Artikelserie »FPDF-Tutorial - PDF-Generierung mit PHP«.

Hier geht es zum nächsten Artikel der Serie: FPDF-Tutorial: Blocksatz und Fließtext