![]() | ||||||||
|
PDF-Dateien mit PHP erstellen (FPDF)Sie können mit PHP on-the-fly PDF-Dateien erstellen, die auf aktuellen Daten z.B. aus Ihrer Datenbank basieren. Der gängige Weg hierfür ist die Zuhilfenahme der PDFLib. Diese Erweiterung soll hier nicht zum Einsatz kommen, da nicht alle Provider (eher die wenigsten) diese Erweiterung anbieten. Stattdessen wird hier die freie Klasse FPDF von Olivier PLATHEY, die Sie auf jedem Webserver mit PHP-Unterstützung einsetzen können, verwendet und vorgestellt. Ziel dieses kleinen Tutorials ist es, Ihnen die Grundlagen im Umgang mit dieser Klasse zu erläutern, da es auf der zur Klasse gehörenden Webseite keine deutsche Einführung gibt. Für die vertiefende Beschäftigung mit dieser Klasse steht eine komplette deutsche Übersetzung aller Methoden, das Manual, bereit. Die zu dieser Klasse gehörende Webseite ist zu haben unter: Ein deutsches Portal zu dieser Klasse gibt es unter: Im Bereich Downloads der Webseite finden Sie sowohl die deutsche Beschreibung (Manual) als auch die Klasse selbst. Mit der Klasse können Sie relativ schnell einfache PDF-Dateien erstellen, allerdings werden viele Features des PDF-Formats noch nicht unterstützt. So können Sie z.B. die erstellten PDF-Dateien nicht schützen lassen. Auch ist es nicht möglich, vorhandene PDF-Dateien einzulesen und dann abzuändern. Wir verwenden in unserem Beispiel die Version 1.52 von FPDF Hier in diesem Tutorial wird eine einfache PDF-Datei erstellt, die aus einer Datenbanktabelle das jeweils ausgewählte Immobilienangebot darstellt. Zugegeben, der vorhandene Informationsumfang über die Immobilie ist etwas rudimentär, aber es geht hier ja nicht darum, eine perfekte, fertige Lösung zu liefern, sondern darum, den prinzipiellen Weg darzustellen. Inhalt
VorüberlegungWir gehen davon aus, dass es eine HTML-Seite gibt, auf der das Immobilienangebot angezeigt wird. Auf dieser Seite verweist ein Link auf die PHP-Datei, die das PDF-Dokument für das ausgewählte Immobilienangebot erstellt. Mit diesem Link wird die Datenbank-ID-Nummer des darzustellenden Immobilienangebots übergeben (tut_pdf.php?ID=4711). Anhand dieser ID werden die anzuzeigenden Informationen des Immobilienangebots für das PDF-Dokument aus der Datenbank ausgelesen - diese Informationen werden also evtl. mehrmals aus der Datenbank ermittelt, einmal für die HTML-Seite und dann noch einmal für das PDF-Dokument. Anschließend wird das PDF-Dokument mit diesen Informationen erstellt und an den Browser geschickt. Die PHP-Datei zum Erstellen des PDF-Dokuments teilt sich folglich sinnvoller Weise in zwei Bereiche - Auslesen der Informationen und Erstellen der PDF-Datei. HinweisBedenken Sie bei Ihren Planungen, dass Sie HTML- und PDF-Seiten nicht mixen können, da dem Browser über die Header mitgeteilt wird, welche Art von Datei gesendet wird. Mit der Headerinformation wird u.a. festgelegt, dass der Browser den Akrobat Reader zur Anzeige des PDF-Dokuments startet. Außerdem soll es laut Webseite von FPDF beim Internet Explorer zu Problemen führen, wenn Sie ein und die gleiche PHP-Datei verwenden (z.B. über einen GET-Parameter gesteuert: datei.php?anzeige=html oder datei.php?anzeige=pdf), um mal HTML-Seiten und mal PDF-Dokumente auszuliefern. Die Informationen über die Immobilienangebote werden aus folgender Tabelle ausgelesen:
Die Feldinhalte sollten über die Feldnamen eigentlich selbsterklärend sein, nur ein Satz zum Feld bildurl: hier wird die URL zum Bild - und nicht das Bild selber - des Immobilienangebots gespeichert. Verwenden Sie hier relative URLs und bedenken Sie, dass die Pfadangabe evtl. auf das PDF-Dokument angepasst werden muss. Wir gehen hier davon aus, dass die Bilddateien im gleichen Verzeichnis wie die PDF-Datei liegen. Wie wird die PDF-Seite aussehenDie PDF-Datei wird aus einem Kopfbereich (in Word würde man von der Kopfzeile reden) mit zwei Bildern, einem statischen Text und der Überschrift aus der Datenbank und einem Fußbereich (Fußzeile) mit statischem Text bestehen. Auf der eigentlichen Seite wird zunächst rechtsbündig die in der Datenbank festgelegte Grafik angezeigt. Links von dieser Grafik wird die Kurzbeschreibung und die Adresse der Immobilie gesetzt. Unter diesen Elementen folgt die Langbeschreibung. Hier können Sie sich das Wunderwerk mit Beispieltexten anschauen. Der komplette CodeNachfolgen finden Sie den kompletten Code unseres Beispiels. Die Erklärung finden Sie in den nachfolgenden Abschnitten:
<?php FPDF ready for take offNach dem Entpacken der Zip-Datei müssen Sie die Datei fpdf.php und den Ordner font auf Ihren Webserver kopieren. Legen Sie diese Datei und den Ordner so ab, dass Sie in Ihren Scripten darauf zugreifen können. Für dieses Tutorial gehen wir davon aus, dass sowohl der Ordner font als auch die Datei fpdf.php im selben Verzeichnis wie die PHP-Datei liegt, die das PDF-Dokument erstellt (diese Datei nennen wir nachfolgend tut_pdf.php). Im Ordner font befinden sich PHP-Dateien, die von FPDF benötigt werden, um Schriften im PDF-Dokument anzuzeigen. Von Haus aus sind folgende Schriften berücksichtigt: courier, helvetica, symbol, times und zapfdingbats. Der Zugriff auf diese "beiden" wird in tut_pdf.php mit folgenden Zeilen festgelegt:
define('FPDF_FONTPATH','font/'); Mit define('FPDF_FONTPATH','font/'); legen Sie den Pfad in den kopierten Ordner mit den Schriftdateien fest. Beachten Sie den Slash am Ende der Pfadangabe und dass der Ordnername mit angegeben wird. Über require('fpdf.php'); wird die Datei mit der eigentlichen Klasse FPDF eingebunden. Auslesen der anzuzeigenden DatenBevor wir jetzt mit dem Erstellen des PDF-Dokuments beginnen, müssen wir zunächst ermitteln, welche Informationen angezeigt werden sollen. Diese Informationen lesen wir aus der Datenbanktabelle immo aus. Dieser Teil von tut_pdf.php sieht dann wie folgt aus:
//Übergebenen Wert testen Zunächst wird mit Hilfe eines regulären Ausdrucks getestet, ob $_GET['ID'] aus Ziffern besteht und somit überhaupt eine ID-Nummer sein kann. Sollte der Test nicht bestanden werden, wird mit die() eine Fehlermeldung ausgegeben und die Abarbeitung des Scripts abgebrochen.
Mit Hilfe des zusammengesetzten SQL-Statements wird der gewünschte Datensatz ausgelesen und dem Array $ergebnis zugewiesen. Auch hier wird bei Fehlern die Abarbeitung des Scripts abgebrochen und eine Fehlermeldung ausgegeben. Das PDF-Dokument beginnenDa wir auf unserer PDF-Seite Kopf- und Fußbereiche vorgesehen haben, müssen wir die vorhandene Klasse FPDF erweitern, so dass wir nachfolgend die erweiterte Klasse einsetzen werden. Die Erklärung, wie wir die Elemente im Kopf- und Fußbereich erstellen, folgt in den Abschnitten Die Kopfzeile hinzufügen und Die Fußzeile hinzufügen.
//Klasse erweitern Nachdem wir die Basisklasse erweitert haben, beginnen Sie ein PDF-Dokument, indem Sie ein neues Objekt der erweiterten Klasse erstellen: $pdf = new PDF(); Sie können beim Erstellen des neuen Objektes drei optionale Parameter übergeben:
Hier im Beispiel erstellen wir also ein Objekt mit Standardwerten (Hochformat, Millimeter und A4). HinweisSie können die Zeichenfarbe und sonstige Eigenschaften auch für jedes Element explizit angeben, indem Sie diese Eigenschaften vor dem Erstellen des betreffenden Elements setzen. Da das Beispieldokument aber schlicht gehalten ist, reicht es, diese Eigenschaften einmal für das gesamte Dokument zu setzen. Wichtig ist es, diese Eigenschaften vor dem Aufruf von $pdf->AddPage(); festzulegen, damit sie auch für die Elemente des Kopfbereichs gelten. Die Methode zum Erstellen des Kopfbereichs wird automatisch mit AddPage() aufgerufen. Da die nächsten zwei Werte für das gesamte Dokument gelten sollen, setzen wir sie, bevor wir die erste Seite erstellen.
$pdf->SetDrawColor(100); Mit $pdf->SetDrawColor(100); wird die Zeichenfarbe festgelegt. Die Methode erwartet bis zu drei Parameter. Wenn nur ein Parameter - wie hier im Beispiel -übergeben wird, legen Sie damit den Grauwert fest (0 für Weiß und 255 für Schwarz). Bei drei Parametern setzen Sie in der Reihenfolge Rot, Gelb, Blau die RGB-Werte der Farbe. Mit SetLineWidth(2) wird die Dicke der gezeichneten Linien im Dokument festgelegt. Da wir als Maßeinheit Millimeter gesetzt haben, werden die Linien 2 Millimeter breit gezeichnet. HinweisDie Zeichenfarbe unterscheidet sich von der Textfarbe (SetTextColor()). Der Standardwert für die Textfarbe ist Schwarz. Zu beachten ist aber, dass sowohl die festgelegte Zeichenfarbe als auch die Linienbreite für einen Rahmen um Textbereiche verwendet werden. Jetzt setzen wir den Platzhalter für die Gesamt-Seitenzahl, um Ausgaben wie Seite 3 von 5 zu ermöglichen. Dieser Platzhalter wird in der Fußzeile verwendet. Ist dieser Platzhalter gesetzt, wird die Gesamt-Seitenzahl anstatt des Platzhalters eingesetzt. Da wir diese Methode aufrufen, ohne einen Platzhalter explizit anzugeben, wird der Standardwert {nb} verwendet.
$pdf->AliasNbPages(); Mit $pdf->SetAutoPageBreak(TRUE, 23); überlassen Sie der Klasse FPDF die Aufgabe, sich um den Seitenumbruch zu kümmern. Mit dem zweiten Parameter wird angegeben wie groß der untere Seitenrand ist. Im Beispiel setzen wir ihn auf 23 mm (Standardwert 20 mm), um ausreichend Platz für die Fußzeile zu haben. Die Fußzeile wird in den unteren Seitenrand gesetzt. HinweisSie könnten mit SetMargins(links, oben, rechts) die Seitenränder explizit angeben. Den unteren Seitenrand bestimmen Sie mit SetAutoPageBreak(). Wir belassen es im Beispiel bei den Standardrändern von 10 mm. Nach diesen vorbereiteten Schritten kann es jetzt mit der ersten Seite losgehen. Sie erzeugen eine Seite mit: $pdf->AddPage(); Wie bereits im Hinweis erwähnt, wird mit AddPage() automatisch die Methode zum Erstellen des Kopfbereichs aufgerufen. Um die Langbeschreibung unter den linken Text (Kurzbeschreibung und Adresse) und unter die nachfolgend erstellte rechtsbündige Grafik setzen zu können, weisen wir die aktuelle Y-Position für spätere Verwendung $y1 zu. $y1 = $pdf->GetY(); Sie positionieren Elemente auf der Seite, indem Sie die Y- und X-Position der linken oberen Ecke des Elements angeben. Hierbei wird die festgelegte Maßeinheit verwendet, wobei die linke obere Ecke der Seite die Position 0,0 hat. Beim Festlegen der Position unterscheiden sich die Elemente, entweder Sie geben beim Erstellen des Elements die gewünschte Position explizit an (z.B. bei Grafiken) oder die aktuelle Position auf dem Dokument (ähnlich dem Cursor in Textdokumenten) wird verwendet (wie bei Textbereichen Cell() und MultiCell()). Sie ermitteln die aktuelle Position mit GetY() und GetX(). Die aktuelle Position wird durch das Erstellen von Textbereichen (Cell() und MultiCell()) automatisch geändert oder Sie setzen sie explizit mit SetY(), SetX() bzw SetXY(). Zeichenelemente wie Grafiken oder Linien ändern die aktuelle Position nicht. Das Bild der Immobilie (Pfad in $ergebnis['bildurl']) wird mit einer Breite von 90 mm an den rechten Rand gesetzt. Die Originalmaße der Grafik werden benötigt, um die Höhe der Grafik nach dem Skalieren ($bildneuhoch) zu berechnen. Die neue Höhe wird benötigen, um die ausführliche Beschreibung der Immobilie unter die Grafik setzen zu können.
$imgeinfo = getimagesize ( $ergebnis['bildurl']); getimagesize() gibt ein Array mit Informationen über die angegebene Grafik zurück ([0] = Breite, [1] = Höhe). Anschließend wird die passende Höhe ($bildneuhoch) für die gewünschten Breite ($bildneubreit) der skalierten Grafik berechnet. Hierbei wird mit ceil() aufgerundet, um ganze Zahlen zu erhalten. $pdf->Image($ergebnis['bildurl'], 200-$bildneubreit, $y1, $bildneubreit, $bildneuhoch); Mit Image() wird ein Bild im Dokument platziert. Der erste Parameter gibt den Pfad zur Datei an ($ergebnis['bildurl']). Der zweite Parameter gibt die X-Position der Linken oberen Ecke des Bildes an. Da das Bild rechtsbündig gesetzt werden soll, wird vom rechten Rand (200mm) die Breite des Bildes ($bildneubreit) abgezogen. Der dritte Parameter bestimmt die Y-Position der linken oberen Ecke des Bildes. Dieser Y-Wert wurde zuvor $y1 zugewiesen. Die nächsten beiden Parameter erwarten die Breite und Höhe des Bildes. HinweisDie Methode Image() ist in der Lage das Bild zu skalieren. Sofern nur eine Angabe (Breite oder Höhe) angegeben wird, wird die andere Angabe berechnet. Da im Beispiel die Höhe der Grafik benötigt wird, um die nachfolgenden Elemente zu positionieren, wird sie zuvor berechnet und diese Aufgabe nicht Image() überlassen. Geben Sie weder Höhe noch Breite der Grafik an, wird die Grafik in Originalgröße mit einer Auflösung von 72 dpi eingefügt. Die Methode Image() hat noch zwei weitere optionale Parameter, den Dateityp (JPG, JPEG, PNG) und einen Link (URL oder interner Kennzeichner eines Verweisziels innerhalb des Dokuments). Wird der Dateityp nicht angegeben, wird er anhand der Dateiendung ermittelt. Es werden JPEG- und PNG-Grafiken unterstützt, wobei Interlacing und Alpha-Kanal nicht unterstützt werden. Jetzt wird der linksbündige Text neben der Grafik erstellt:
$textlinks = $ergebnis['kurzbeschreibung']."\n\n".$ergebnis['strasse']."\n".$ergebnis['plz'].' '.$ergebnis['ort']; Zunächst wird der gesamte Text in $textlinks zusammengesetzt. Beachten Sie hierbei, dass Zeilenumbrüche mit \n hinzugefügt werden. Anschließend wird die zu verwendende Schrift festgelegt (Times mit einer Schriftgröße von 12). Mit der Methode MultiCell() wird der Text auf das Dokument geschrieben. Der Text beginnt an der aktuellen Position. Da die aktuelle Position durch die Grafik nicht geändert wurde, wird der Text links oben unter die Kopfzeile gesetzt. Die Methode MultiCell() erwartet folgende Parameter (von Links nach Rechts):
Die aktuelle Position wird durch den Einsatz der Methode MultiCell() automatisch an die untere Linke Ecke des Textbereichs verschoben. Der aktuelle Y-Wert der Position wird benötigt, um die ausführliche Beschreibung zu platzieren und deswegen $y2 zugewiesen: $y2 = $pdf->GetY(); Damit die ausführliche Beschreibung unter der Grafik und der Kurzbeschreibung platziert wird (je nachdem, welches Element weiter nach unten reicht), wird die Y-Position wie folgt gesetzt: $pdf->SetY(max($y2,$y1 + $bildneuhoch)); Als neue Y-Position wird der größere Wert (über max()) aus $y2 (Y-Wert unter der Kurzbeschreibung) und $y1 (obere Ecke des Bildes) + die Höhe des Bildes (also insgesamt untere Ecke des Bildes) verwendet. $pdf->SetY($pdf->GetY() + 4); Anschließend werden noch ein Abstand von 4 mm sowie die ausführliche Beschreibung ($ergebnis['langbeschreibung']) mit der Methode MultiCell() rechtsbündig hinzugefügt.
$pdf->MultiCell(0,7,$ergebnis['langbeschreibung'],0,'R',0); Fertig ist das PDF-Dokument, es wird mit Output() an den Browser gesendet. Die Beschreibung ist aber noch nicht fertig, es fehlen noch die Kopf- und Fußzeile. HinweisMit Output() haben Sie die Möglichkeit, das PDF-Dokument an den Browser zu schicken oder als Datei zu speichern. Im ersten Parameter können Sie einen Dateinamen festlegen und mit dem zweiten Parameter das Ziel bestimmen. Hier die wichtigsten Ziele:
Die Kopfzeile hinzufügenWie am Anfang bereits erwähnt, ist es für Kopf- und Fußzeilen notwendig, die Klasse FPDF zu erweitern. Die Methoden Header() und Footer() müssen mit Leben - also mit den Befehlen zum Anzeigen der gewünschten Elemente - gefüllt werden.
class PDF extends FPDF Zunächst wird wie oben bereits beschrieben ein Logo auf die rechte Seite der Kopfzeile gesetzt. Beachten Sie, dass die Methoden und Attribute der Klasse über das Schlüsselwort $this angesprochen werden, da hier 'innerhalb' der Klasse gearbeitet wird. Anschließend wird das zweite Logo auf die rechte Seite der Kopfzeile platziert:
$pfadbild = 'brainlogo.jpg'; Zunächst wird eine größere (15) und fette (B) Schrift ausgewählt, und anschließend ein statischer Text zentriert zwischen die Grafiken gesetzt.
$this->SetFont('Times','B',15); Der Zeilenvorschub $this->Ln(6); schafft etwas Platz, um eine Linie über die Überschrift der Immobilie zu zeichnen:
$this->Ln(6); Die Methode Line() erwartet vier Parameter: Die Position des Startpunkts und des Endpunkts. Die Linie wird vom X-Wert 10 bis zum X-Wert 200 gezogen. Als Y-Wert wird die über GetY() ermittelte aktuelle Y-Position verwendet - sowohl für den Startpunkt als auch für den Zielpunkt, damit die Linie waagerecht verläuft. Nach der Linie folgt die Überschrift. Damit innerhalb der Klasse auf das Ergebnisarray der Datenbankabfrage zugegriffen werden kann, muss $ergebnis als GLOBAL erklärt werden.
GLOBAL $ergebnis; In der gleichen Schriftart wie der statische Text wird mit Cell() die einzeilige Überschrift gesetzt. Diese Methode erwartet folgende Parameter (von links nach rechts):
Nach der unterstrichenen Überschrift wird noch etwas Platz geschaffen (5 mm). Die Fußzeile hinzufügenAnschließend geht's an die Fußzeile:
function Footer() Wenn SetY() mit einer negativen Angabe aufgerufen wird, wird dieser Abstand vom unteren Seitenrand berechnet. Im Beispiel wird also eine Position 20 mm entfernt vom unteren Seitenrand gesetzt.
$istY = $this->GetY(); An diese Position wird eine Linie über die gesamte Breite (zwischen den Seitenrändern) der Seite gezeichnet. $this->SetY($istY + 2); Anschließend wird die aktuelle Position unter die Linie verschoben und der linksbündige statische Text platziert:
$texthohe = 4; Auf die rechte Seite der Fußzeile soll die Seitenzahl in die Höhe der letzten Zeile des statischen Textes gesetzt werden. Deswegen wird von der aktuellen Y-Position (unter dem statischen Text) die Höhe einer Zeile abgezogen. $this->SetY($this->GetY() - $texthohe); Der Text für die Seitenzahl wird zusammengesetzt. Die aktuelle Seitenzahl wird von $this->PageNo() zurückgegeben. Die Gesamt-Seitenzahl wird - wie oben über AliasNbPages() festgelegt - für {nb} eingesetzt. $seite = 'Seite '.$this->PageNo().'/{nb}'; Um die Seitenzahl rechtsbündig zu setzen, ohne den linksbündigen Text zu überschreiben, wird die Länge des Strings berechnet und die Seitenangabe in einen Textbereich gesetzt, der erst ziemlich weit rechts auf der Seite beginnt. Aus Gründen der Vereinfachung wird dabei nicht auf den Millimeter geachtet, deswegen wird die Länge des Strings von 190 (Seitenrand 200) subtrahiert. An diese berechnete X-Position wird die aktuelle Position gesetzt.
$breite = $this->GetStringWidth($seite); Anschließend wird die Seitenangabe rechtsbündig an den Seitenrand gesetzt. Es folgen die schließenden Klammern für die Methode und die erweiterte Klasse:
$this->Cell(0,$texthohe,$seite,0,0,'R'); HinweisWenn Sie genau hinschauen, sehen Sie, dass der Text (sowohl die Seitenzahl als auch die anderen Textelemente) nicht ganz rechtsbündig endet bzw. linksbündig beginnen. Dies liegt daran, dass die Klasse FPDF die möglichen Rahmen um die Textelemente berücksichtigt. Im Beispiel ist die Dicke dieser Rahmen für das ganze Dokument auf 2 mm gesetzt, also enden bzw. beginnen die Textelemente am rechten und linken Rand mit 2 mm Luft. Möchten Sie dieses Phänomen ändern, können Sie entweder die Rahmendicke von allen Textelementen auf 0 setzen und vor dem Zeichnen der Linien wieder auf 2 mm, oder Sie zeichnen die Linien etwas kürzer (auf jeder Seite 2 mm), dann fällt dieser 'Einzug' nicht auf. © Copyright 2005 by Christine Peyton , Andre Möller |
![]() ![]() Ein paar Links: |