am 28. Oktober 2009
Vernünftig formatierte und druckfertige PDF-Dokumente mit PHP zu erzeugen ist keine leichte Aufgabe. Für gewöhnlich werden dabei zwei Ansätze unterschieden. Mit ausreichend Zeit und Geduld führen sie zwar beide mehr oder weniger ans Ziel, allerdings lassen sie auch einiges zu wünschen übrig.
HTML-zu-PDF-Konvertierung: Dieser Ansatz kommt auf breiter Front zum Einsatz. Dabei wird ein HTML-Dokument programmatisch erzeugt und dann mit einer der vielen freien Bibliotheken 1 zu PDF konvertiert. Da es sich bei HTML jedoch im Gegensatz zu PDF nicht um ein seitenorientiertes Format handelt, ist es unmöglich das Ausgangsdokument 1-zu-1 auf das Zieldokument abzubilden. In der Textverarbeitung übliche Dinge, wie Kopf- und Fußzeilen oder Absatzkontrolle bei Seitenumbrüchen (Schusterjungen und Hurenkinder) sind in HTML schlicht nicht umsetzbar.
Programmatischer Ansatz: Diese Herangehensweise verspricht absolute Kontrolle über den Prozess der PDF-Erzeugung. Allerdings ist der Preis dafür ein extrem hoher Aufwand; jede Textzeile, jedes Objekt, wie Bilder oder Tabellen, muss einzeln durch Festsetzen ihrer bzw. seiner Koordinaten im Dokument positioniert werden 2. Dieser Aufwand ist – abgesehen von minimalen Korrekturen – bei jeder Änderung des Dokuments wieder zu treiben.
Ein neuer Ansatz
Dieser Artikel stellt einen neuen, dritten Ansatz vor. Er basiert auf Templates, die in einer WYSIWYG-Anwendung, wie z.B. Microsoft® Word oder Open Office erstellt und dann mittels PHP mit Daten gefüllt werden. Das resultierende Dokument kann nicht nur als PDF sondern zusätzlich auch als DOCX, DOC und RTF gespeichert werden.
Bevor sich der Artikel der Funktionsweise dieses Ansatzes widmet, noch ein kleines Anwendungsbeispiel vorweg. Der folgende PHP5-Code zeigt exemplarisch die PDF-Erzeugung, indem die Felder software, licensee und company in dem Template template.docx [46.7 KB] mit Daten gefüllt werden. Das resultierende Dokument document.pdf [104.7 KB] wird generiert und auf der Festplatte gespeichert.
$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge(
array (
'username' => 'yourUsername',
'password' => 'yourPassword'
)
);
$phpLiveDocx->setLocalTemplate('template.docx');
$phpLiveDocx->assign('software', 'Magic Graphical Compression Suite v1.9');
$phpLiveDocx->assign('licensee', 'Henry Döner-Meyer');
$phpLiveDocx->assign('company', 'Co-Operation');
$phpLiveDocx->createDocument();
$document = $phpLiveDocx->retrieveDocument('pdf');
file_put_contents('document.pdf', $document);
unset($phpLiveDocx);
Der Beispiel-Code in diesem Artikel liegt der nächsten Version des Zend Frameworks bei. Diese Version wird die Nummer 1.10 tragen. Zwar gibt es noch keinen offiziellen Termin für die Veröffentlichung, allerdings wird allgemein erwartet, dass es noch dieses Jahr geschieht. Bis es soweit ist, kann per SVN eine Beta-Version aus dem Standard Incubator ausgecheckt werden.
Der Webservice LiveDocx
LiveDocx ist ein SOAP-Webservice zur Dokumentenerzeugung, der auf der marktführenden Textverarbeitungskomponente TX Text Control .NET basiert. Mit LiveDocx ist es möglich, Templates mit jeder Programmiersprache, die SOAP unterstützt, mit Daten zu füllen. Die resultierenden Dokumente können jeweils in allen unterstützten Formaten gespeichert werden. Dieser Artikel beleuchtet ausschließlich das Zusammenspiel von LiveDocx und PHP.
In der Standardversion des Zend Frameworks befinden sich die LiveDocx-Komponenten unterhalb des Pfads /Zend/Service/LiveDocx/. Es ist natürlich auch möglich, LiveDocx ohne das Zend Framework direkt mit dem PHP5-SoapClient zu benutzen. Genauso mit der Bibliothek NuSOAP – damit sogar in Verbindung mit PHP4. Dieser Artikel beschreibt lediglich die Arbeit mit den offiziellen Zend Framework-Komponenten in Verbindung mit PHP5.
Templates und Dokumente
Der Artikel bedient sich recht häufig der Begriffe Template und Dokument. Daher ist es wichtig zu verstehen, was genau damit gemeint ist.
Template: Der Begriff bezeichnet ein formatiertes Ausgangsdokument, lies: Input-, das Felder (Platzhalter) enthält. Ein Template kann in einem der folgenden Formate vorliegen:
- DOC – Microsoft® Word DOC Format
- DOCX – Office Open XML Format
- RTF – Microsoft® Rich Text Format
- TXD – TX Text Control® Format
Templates können entweder lokal auf dem Client-Rechner (von wo aus der SOAP-Request gestartet wird) oder auf dem LiveDocx-Server gespeichert werden. Welche dieser beiden Möglichkeiten sinnvoller ist, hängt vom jeweiligen Anwendugsfall ab.
Bei lokaler Speicherung des Templates muss es bei jedem Vorgang zusammen mit den Daten zum Server übertragen werden. Dies ist äußerst ineffizient, falls das Template über mehrere Vorgänge hinweg dasselbe ist. Daher bietet es sich in solch einem Fall an, das Template zum LiveDocx-Server zu übertragen und dann dort zu speichern. Für den jeweiligen Vorgang reicht es dann aus, lediglich noch die entsprechenden Daten zusammen mit dem Namen des zu verwendenden Templates an den Server zu schicken. Für die meisten Anwendungsfälle ist dies die Methode der Wahl.
Im Falle von Templates, die sich ständig ändern, oder Anwendungen, die es Benutzern erlauben, eigene Templates zu verwenden, kann es sinnvoll sein, das Template für jeden Vorgang zusammen mit den Daten an den LiveDocx-Server zu übertragen. Natürlich kostet dieses Vorgehen aufgrund der höheren Datenmenge mehr Zeit.
Dokument: Der Begriff Dokument bezeichnet im LiveDocx-Kontext eine vom Webservice erzeugte Datei, also ein mit Daten gefülltes Template. Ein Dokument kann in folgenden Formaten erzeugt werden:
- DOC – Microsoft® Word DOC Format
- DOCX – Office Open XML Format
- HTML – XHTML 1.0 Transitional Format
- PDF – Adobe® Portable Document Format
- RTF – Microsoft® Rich Text Format
- TXD – TX Text Control® Format
- TXT – ANSI-Textformat
Zusätzlich zu den oben genannten Textverarbeitungs-Dateiformaten sind noch folgende Bildformate als Zielformate verfügbar:
- BMP – Bitmap Image Format
- GIF – Graphics Interchange Format
- JPG – Joint Photographic Experts Group Format
- PNG – Portable Network Graphics Format
- TIFF – Tagged Image File Format
- WMF – Windows Meta File Format
LiveDocx im Einsatz
Dieser Abschnitt beschreibt den Prozess der Dokumentenerzeugung im Ganzen.
Template-Erzeugung in Microsoft® Word 2007
Der erste Schritt jedes LiveDocx-Projekts besteht darin, ein Template zu erzeugen. Dazu dienen entweder Open Office oder Microsoft® Word. Um den Artikel nicht unnötig in die Länge zu ziehen, sei an dieser Stelle lediglich die Template-Erzeugung mit Microsoft® Word 2007 beschrieben. Eine Anleitung für Open Office findet sich im LiveDocx Blog.

Der Prozess beginnt mit der Erzeugung einer neuen Datei in Microsoft® Word 2007. Diese wird beispielsweise unter dem Namen template.docx gespeichert. Es folgt der Inhalt des Dokuments: Text, Bilder, Felder. Die nebenstehende Abbildung zeigt den Dialog zum Einfügen von Feldern.
Sobald das Template template.docx [46 KB] fertiggestellt ist, muss es nochmals gespeichert werden. Die folgende Abbildung zeigt das fertige Template in Microsoft® Word 2007. Die Felder haben die Form { MERGEFIELD name }. Für diese Darstellung in Microsoft® Word 2007 ist es unter Umständen notwendig, die Tastkombination Alt-F9 zu drücken:

Templates mit Daten füllen
Nach Fertigstellung des Templates kann zum nächsten Prozessschritt übergangen werden: dem Füllen des Templates mit Daten. Der folgende Beispiel-Code zeigt, wie das Template mit Daten gefüllt wird:
$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge(
array (
'username' => 'yourUsername',
'password' => 'yourPassword'
)
);
$phpLiveDocx->setLocalTemplate('template.docx');
$phpLiveDocx->assign('software', 'Magic Graphical Compression Suite v1.9');
$phpLiveDocx->assign('licensee', 'Henry Döner-Meyer');
$phpLiveDocx->assign('company', 'Co-Operation');
$phpLiveDocx->assign('date', 'September 10, 2009');
$phpLiveDocx->assign('time', '7:17:48 AM CEST');
$phpLiveDocx->assign('city', 'Hamburg');
$phpLiveDocx->assign('country', 'Germany');
$phpLiveDocx->createDocument();
$document = $phpLiveDocx->retrieveDocument('pdf');
file_put_contents('document.pdf', $document);
unset($phpLiveDocx);
Besonders dann, wenn der Dokumentenerstellungsprozess zu Zwecken der Archivierung angestoßen wurde, natürlich aber auch durchaus in anderen Fällen ist es wünschenswert, eine erzeugte PDF-Datei mit Metadaten zu versehen. Die Methode setDocumentProperties() bettet diese Metadaten, die als assoziatives Array vorliegen müssen, in das PDF ein:
$documentProperties = array(
'title' => 'Magic Graphical Compression Suite v1.9',
'author' => 'Megasoft Co-operation',
'subject' => 'Magic Graphical Compression Suite v1.9',
'keywords' => 'Graphics, Magical, Compress, Suite, License'
);
$phpLiveDocx->setDocumentProperties($documentProperties);
Der Aufruf von setDocumentProperties() erfolgt vor dem von createDocument(). Das resultierende PDF-Dokument document.pdf [104 KB] wird auf die Festplatte geschrieben und kann nun mit einem beliebigen PDF-Viewer geöffnet werden:

Blockdaten an LiveDocx übergeben
Zusätzlich zu den skalaren Datentypen aus dem obigen Beispiel, kann LiveDocx auch mit zusammengesetzten Datentypen, wie assoziativen Arrays, umgehen. Als Beispiel hierfür dienen das Template template.doc [20.5 KB] und das resultierende Dokument document.pdf [77.6 KB] [77.6 KB]. Besonderes Augenmerk sei auf folgenden Abschnitt des Templates gelegt:

Dieser von Lesezeichen (
) eingefasste Abschnitt wird wiederholt in das resultierende Dokument eingefügt, so dass sich daraus mehrere Zeilen einer Tabelle ergeben. Die Tabellenzeilen sind als zweidimensionales Array abgebildet. Dabei entspricht jede Zeile einem Array der zweiten Ordnung.
Der folgende PHP5-Code nutzt dieses Konzept, um die Verbindungsdatentabelle einer fiktiven Telefonrechnung zu erzeugen. Der Übersichtlichkeit halber ist hier nur der Code-Abschnitt aufgeführt, der die Tabelle erzeugt. Die LiveDocx-Initialisierung, die Dokumentenerzeugung und das Herunterladen des resultierenden Dokuments funktionieren genau wie im obigen Beispiel:
// instantiate LiveDocx
$billConnections = array(
array(
'connection_number' => '+49 (0)421 3359101',
'connection_duration' => '00:01:01',
'fee' => '1.15'
),
array(
'connection_number' => '+49 (0)421 3359102',
'connection_duration' => '00:01:02',
'fee' => '1.15'
),
array(
'connection_number' => '+49 (0)421 3359103',
'connection_duration' => '00:01:03',
'fee' => '1.15'
),
array(
'connection_number' => '+49 (0)421 3359104',
'connection_duration' => '00:01:04',
'fee' => '1.15'
)
);
$phpLiveDocx->assign('connection', $billConnections);
// create and retrieve document
Das resultierende Dokument enthält nun eine Tabelle mit den ihr zugewiesenen Daten:

Erzeugen von Bilddateien mit LiveDocx
Zusätzlich zu den oben genannten Dokumentenformaten kann LiveDocx die Seiten eines Dokuments auch als Bilddateien speichern. Dazu bietet Zend_Service_LiveDocx_MailMerge die Methoden getAllBitmaps() und getBitmaps() an:
// instantiate LiveDocx
// get all bitmaps
// (zoomFactor, format)
$bitmaps = $phpLiveDocx->getAllBitmaps(100, 'png');
Bilder lediglich für bestimmte Seiten zu erzeugen, funktioniert ganz ähnlich:
// get just bitmaps in specified range
// (fromPage, toPage, zoomFactor, format)
$bitmaps = $phpLiveDocx->getBitmaps(2, 2, 100, 'png');
Dabei ist der Parameter zoomFactor zu beachten. Dabei handelt es sich um eine Prozentangabe, die sich auf die Originalgröße des Dokuments bezieht. Der Wertebereich erstreckt sich von 10-400%. Die beiden Methoden eignen sich hervorragend zur Erzeugung von Vorschaubildern.
Die erzeugten Bilddaten können mit einer einfachen Schleifenfunktion auf die Festplatte geschrieben werden. Das Array, das die Methoden zurückliefern enthält die einzelnen Seiten des Dokuments als Binärdaten:
// write to disk
// (one page per record)
foreach ($bitmaps as $pageNumber => $bitmapData) {
$filename = sprintf('documentPage%d.png', $pageNumber);
file_put_contents($filename, $bitmapData);
printf('Written %d bytes to disk as %s.%s', filesize($filename), $filename, PHP_EOL);
}
LiveDocx in eigenen Anwendungen einsetzen
Der LiveDocx-PHP-Code im Zend Framework steht unter der Free BSD Lizenz und kann daher in den meisten Anwendungen problemlos eingesetzt werden. Bei dem Server-Teil von LiveDocx hingegen handelt es sich um proprietäre Software. Es bestehen daher drei Szenarien für den Einsatz von LiveDocx:
- Kostenloser LiveDocx-Zugang
Diese Variante reicht für die meisten Anwendungen aus. Die LiveDocx-Klassen im Zend Framework referenzieren den Standard-LiveDocx-Server. Dieser Server kann kostenlos genutzt werden. Das gilt auch für kommerzielle Anwendungen. Die Registrierung ist kostenlos.
- Premium Service
Für Anwendungen, die mehr als ein paar Hundert Dokumente am Tag erzeugen, bietet es sich an, gegen eine monatliche Gebühr einen eigenen LiveDocx-Server zu mieten. Ein solcher Server bietet im Gegensatz zum kostenlosen Standard-Server garantierte Verfügbarkeit, Antwortzeiten und Bandbreite.
- Eigene LiveDocx-Lizenz
Anwendungen, die mehrere Tausend Dokumente pro Stunde erzeugen oder die sensible Daten verarbeiten, greifen am besten auf einen LiveDocx-Server zu, der im eigenen Netz hinter der Firewall läuft. Diese Variante ermöglicht die höchste Durchsatzrate, da sie alle Möglichkeiten zur Optimierung des Anwendungsaufbaus bietet.
Weiterführende Informationen
Dieser Artikel bietet lediglich einen Überblick über die Möglichkeiten, die LiveDocx bietet. Für weitere Informationen über diese neue Art der Dokumentenerzeugung lohnt ein Blick auf folgende (englische) Webseiten:
Für Fragen oder Anregungen sind entweder direkt beim Autoren oder auch im offiziellen Support-Forum gut aufgehoben.
Fußnoten
[1] domPDF, HTML 2 (F)PDF, HTML_ToPDF, mPDF usw.
[2] Zend_Pdf, PDFlib, FPDF, Cpdf usw.