Programmierung Thomas Weise

twPdf - Grundlagen

PDF-Dokumente mit PHP erzeugen

von Thomas Weise ( Blog)

Oft möchte man seinen Website-Besuchern eine Möglichkeit bieten, Informationen in Form einer PDF-Datei herunterzuladen oder einfach zu betrachten. Wie Sie PDF-Dokumente dynamisch auf Ihrer Website zur Laufzeit erzeugen, soll dieser Artikel, und bei entsprechender Nachfrage auch folgende, zeigen.

Problemstellung / Hintergrund

PDF-Dateien zu erstellen ist ja schon lange kein Problem mehr. Spätestens seit OpenOffice die Möglichkeit bot, seine Textdokumente ins PDF-Format zu konvertieren (und wohl aufgrund dessen andere namhafte Anbieter nachzogen), ist es für jedermann leicht möglich, seine Informationen in Form eines PDF-Dokumentes anzubieten.

Anders sieht das derzeit immer noch aus, wenn man mal schnell auf seiner Website aktuelle Inhalte "zur Laufzeit" dynamisch in einer PDF-Datei anbieten möchte. Beispielsweise wäre das nötig, wenn man vom Besucher eingegebene Werte in diese PDF-Datei integrieren muss. Etwa, wenn man dem Benutzer nach seinen Eingaben in einem online-Bestellformular die Möglichkeit bieten möchte, seine Bestellung als PDF-Datei ausdrucken/herunterladen zu können. Die Vorteile des PDF-Formates sollten an dieser Stelle wohl allgemein bekannt sein.

Lösungsansatz / Alternativen

Wie immer gibt es mehrere Lösungen. Hier wird die PDF-Erzeugung durch Verwendung der Klasse FPDF gezeigt. Diese Klasse ist frei erhältlich und darf sowohl für private als auch für kommerzielle Zwecke genutzt werden. Das ist der erste Grund, weshalb wir FPDF hier verwenden, der zweite ist die Stabilität. Die FPDF-Klasse wird seit 2001 entwickelt und kann sich heute auf die Fahne schreiben, eine relativ einfach zu verwendende, erprobte und stabile PHP-Klasse zu sein. Eine Doku zu FPDF gibts hier.

Als Alternative zu FPDF muss hier natürlich an erster Stelle PDFlib genannt werden. Diese Klasse ist jedoch nicht auf jedem Webserver frei verfügbar und die Einrichtung und der Umfang ansich ist auch nicht unbedingt trivial für jeden PHP-Anfänger. (wer sich die Sache trotzdem mal ansehen möchte, sei auf diese schön geschriebene Anleitung verwiesen). Eine andere interessante Alternative könnte eventuell auch TCPDF sein. Der Vollständigkeit halber sei hier noch "PDFlib Lite", "CPDF" und für das Zend-Framework "Zend_Pdf" erwähnt.

Grundlagen / eigene Klasse

Für unsere Übungen sollte auf Ihrem Webserver PHP5 laufen. Falls Sie keine Möglichkeit haben PHP5 zu nutzen, sind ein paar kleine Änderungen am Quellcode notwendig, dass die Skripte auch auf PHP4 lauffähig sind. Dazu aber am Ende mehr.

Am Besten legen Sie sich für die folgenden Versuche gleich ein neues Verzeichnis an (so können Sie es schnell wieder löschen, wenn Ihnen die Sache hier am Ende nicht gefällt ;-) ). In dieses Verzeichnis entpacken Sie die FPDF-Klasse, die Sie bitte hier herunterladen. Erstellen Sie nun ein neues Verzeichnis neben dem soeben entpackten fpdf-Verzeichnis und nennen es twpdf. Dies ist nur ein Vorschlag, und sie können dieses Verzeichnis natürlich auch anders nennen, jedoch ist es manchmal vorteilhaft, bei den selbsterstellten Verzeichnis-, Datei-, Funktions- und Variablennamen eine Art Vorzeichen anzuhängen, um im Code immer gleich schnell zu sehen, was eigene Tests und was vorgegebene, erprobte Sachen sind. Alles was wir hier in unseren Übungen "probieren" erhält die "Vorsilbe" tw, so beugen wir dem vor, beim Bearbeiten aus Versehen etwas aus der FPDF-Klasse beispielsweise zu löschen.

Am Ende sollten Sie jedenfalls eine Verzeichnisstruktur ähnlich der im folgenden Bild vorliegen haben.

Screenshot

Testklasse01

Beginnen wir mit einer kleinen Testklasse um die grundlegenden Dinge kennenzulernen und gleichzeitig eine Art Vorlage für alle späteren Arbeiten zu haben.

// unsere Testklasse erbt von der FPDF-Klasse
class Testklasse01 extends FPDF {
	
	// hier werden die Variablen für diese Klasse deklariert (also: "bekanntgemacht")
	private $twVariable01 = "";
	private $twVariable02 = ""; 
	
	
	// der Konstruktor dieser Klasse
	function __construct() {
		// Konstruktor der vererbenden Klasse aufrufen (also den von FPDF)
		parent::__construct("P", "mm", "A4"); // L=Querformat(Landscape), P=Hochformat(Portrait)
		
		// hier werden die Variablen dieser Klasse initialisiert (also: "gefüllt")
		$this->twVariable01 = "Hallo, ich bin der Probetext aus Testklasse01";
		$this->twVariable02 = date("d.m.Y");
		
		// Einstellungen für das zu erstellende PDF-Dokument
		$this->SetDisplayMode(100);      // wie groß wird Seite angezeigt(in %)
		
		// Seite erzeugen (sozusagen: starten)
		$this->AddPage(); 
	}	
	
	
	// eine Funktion zur Anzeige des Inhalts
	function Header() {
		$this->SetFont("Arial","B","16");                    // Schrift
		$this->SetTextColor(255, 000, 000);                  // Schriftfarbe
		$this->SetXY(20, 50);                                // Position                
		$this->Cell(90, 10, $this->twVariable01, 1, 1, "L"); // Box(Textbox)
	}	
	
	
	function Footer() {		
		// Farben und Schrift allgemein
		$this->SetFont("Courier","I","9");    
		$this->SetTextColor(180);             
		$this->SetXY(25, 288); 
		$this->Cell(170, 5, "dieses Dokument wurde am ". $this->twVariable02. " erstellt", 1, 1, "R");  
	}
}
// ACHTUNG: darf kein Zeichen hinter phpend sein (auch kein Leerzeichen) !!!
Testklasse01 kopieren

Diese kleine Testklasse könnte im Grund genommen noch viel einfacher aufgebaut sein, doch für umfangreichere PDF-Dokumente später ist es ratsam , sich schon gleich jetzt diesen Aufbau mit Variablendeklarationen, Konstruktor, Header uns Footer anzugewöhnen. Der abgebildete Quellcode sollte anhand der eingefügten Kommentare schon einigermaßen selbsterklärend sein. Trotzdem an dieser Stelle noch ein paar Erläuterungen zu den FPDF-Funktionen:

  • Zeile 12: Ruft den Konstruktor der (erbenden) FPDF-Klasse auf und setzt dabei gleich das Papierformat, Maßeinheit und Papiergröße.
  • Zeile 19: SetDisplayMode() legt fest, wie das Dokument angezeigt werden soll, also mit welchem Zoomfaktor.
  • Zeile 22: AddPage() Erzeugt eine neue Seite im Dokument (und somit auch überhaupt eine Seite).
  • Zeilen 26 bis 32: Header() Erzeugt den Header der Seite. Kann jedoch auch gleich für den gesamten Seiteninhalt verwendet werden.
    • SetFont() Bestimmt Schriftart, Style (B=fett, I=kursiv, U=unterstrichen) und die Schriftgröße. Die geringe Auswahl an Schriftarten ist wohl derzeit das größte Manko von FPDF, aber mal Hand aufs Herz, wieviele verschiedene Schriftarten verwendet man schon in einem Dokument?
    • SetTextColor() Bestimmt die Textfarbe. Angabe bsp. (220, 000, 110) oder nur (220) (steht für (220, 220, 220)).
    • SetXY() Position von linken oberen Seitenrand (x=horizontal, y=vertikal). Bestimmt den Punkt, wo es weitergeht.
    • Cell() Zeichnet eine neue Zelle (oder halt Box) im Dokument. Diese kann optional Text, einen Rahmen und einen Hintergrund erhalten. Die linke obere Ecke beginnt an dem zuvor mit SetXY() zugewiesenem Punkt. Die Zellenbreite und -höhe wird in den beiden ersten Parametern festgelegt.
  • Zeilen 35 bis 41: Footer() Die Fußzeile sozusagen.

php-Skript, welches das PDF-Dokument ausgibt, indem es die Testklasse01 benutzt

Auch hier wieder gleich erstmal der Code und dann ein paar Worte dazu.

// ACHTUNG: darf kein einziges Leerzeichen vor phpstart sein, wegen header !!!

// FPDF-Klasse und das Verzeichnis der FPDF-Schriftarten einbinden
define("FPDF_FONTPATH","fpdf16/font/");
include_once('fpdf16/fpdf.php');

// unsere selbsterstellte Testklasse01 einbinden
include_once("twpdf/Testklasse01.php");

// pdf erzeugen (aus unserer selbsterstellten Testklasse01)
$pdf = new Testklasse01();  

// pdf ausgeben (im Browser oder in Datei schreiben)
$pdf->Output();   // Ausgabe (wenn in Datei schreiben, dateiname in Klammer)

// ACHTUNG: in der aufgerufenen Klasse darf kein Leerzeichen hinter phpende sein!!!
testseite01 kopieren
  • Zeile 4 und 5: Hier werden die FPDF-Klasse und die Schriftarten eingebunden.
  • Zeile 8: Hier binden wir unsere selbst erstellte Klasse ein.
  • Zeile 11: Ein Objekt erzeugen von der Testklasse01.
  • Zeile 14: Output() Output gibt das PDF-Dokument aus, beziehungsweise, wenn man als Argument einen Dateiname angibt, dann wird eine PDF-Datei auf dem Server angelegt.

Wenn Sie kein PHP5 auf Ihrem Webserver nutzen können

Wenn Ihnen kein PHP5 auf Ihrem Webserver zur Verfügung steht, dann benutzen Sie für dieses Beispiel anstatt der vorgestellten 2 Dateien bitte folgende Dateien.

Der Unterschied dieser beiden Dateien zu den vorgestellten Dateien ist gering. Hier wurden eigentlich nur die "private/public-Angaben" umgeändert in "var" und Der Konstruktoraufruf der vererbenden Klasse hat hier eine andere Syntax. Diese kleinen Unterschiede in den Dateien haben jedoch keinen Einfluss auf unsere Beispiele. Also, falls Sie beim Testen unserer Beispiele eine ähnliche Fehlermeldung wie die folgende erhalten, dann läuft auf Ihrem Webserver kein PHP5!

Screenshot

ein erstes Beispiel

An dieser Stelle wollte ich eigentlich jetzt ein Beispiel anführen, doch dann dachte ich, wenn ich schon ein Beispiel neu zusammenstelle, dann sollte es auch ein Beispiel sein, das möglichst viele interessiert. Vielleicht schreiben Sie einfach einen Kommentar, was für ein Beispiel Sie sich wünschen würden. Was am meisten gewünscht wird, mach ich dann, falls es nicht zu ausgewachsene Wünsche sind. Naja, und wenn keiner etwas wünscht brauch ich nix machen ;-).

Eine Idee wäre vielleicht eine einfache Rechnung zu generieren, beispielsweise wie dieses Beispiel zeigt.

Für alle, denen es nicht schnell genug gehen kann, gibts hier auch den gesamten Quellcode als zip-Datei.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Bei Fragen, Anregungen oder dergleichen schreiben Sie doch einen Kommentar in mein Blog