DomPDF header / footer
Bis jetzt habe ich immer FPDF verwendet, allerdings ist es in FPDF nur schwer möglich (bzw. ich habe keine gute Lösung gefunden) Bilder in einer Zelle unterzubringen.
Mit DOMPDF ist dies einfacher zu realisieren, da HTML interpretiert wird.
(INFO: ich nutze Codeigniter als PHP MVC Framework)
Nun zum Problem
- in DOMPDF ist ein Header oder Footer nur mit Inline-Code realisierbar
- Anforderung 1: kein Inline-Code für den Header
- Anforderung 2: den Header mit einem Controller steuern.
- Anforderung 3: ein Text, ein Bild und eine Linie im Header
Die Seitennummerierung erfolgt im Moment mit Inline-PHP-Code
Dieser Code befindet sich ganz normal in einer HTML / PHP Seite
<body>
<script type="text/php">
if ( isset($pdf) ) {
$font = Font_Metrics::get_font("verdana");
// If verdana isn't available, we'll use sans-serif.
if (!isset($font)) { Font_Metrics::get_font("sans-serif"); }
$size = 6;
$color = array(0,0,0);
$text_height = Font_Metrics::get_font_height($font, $size);
$foot = $pdf->open_object();
$w = $pdf->get_width();
$h = $pdf->get_height();
// Draw a line along the bottom
$y = $h - 2 * $text_height - 24;
$pdf->line(45, $y, $w - 16, $y, $color, 1);
$y += $text_height;
$pdf->close_object();
$pdf->add_object($foot, "all");
$text = "Page {PAGE_NUM} of {PAGE_COUNT}";
// Center the text
$width = Font_Metrics::get_text_width("Page 1 of 2", $font, $size);
$pdf->page_text($w / 2 - $width / 2, $y, $text, $font, $size, $color);
}
</script>
....html tags und Codeigniter Variablen
</body>
</html>
Dompdf interpretiert erst alle HTML Elemente, normale PHP Tags werden wie immer vorher interpretiert (<? echo „dies und das“; ?>)
Danach geht dompdf erneut durch den Code und bearbeitet die im mit <script type=“text/php“> </script> gekennzeichneten Abschnitte.
Nun zur Header Lösung ohne Inline-PHP-Code (Workaround)
Damit das ganze funktioniert, muss ein wenig Vorarbeit geleistet werden.
Der DOMPDF Ordner befindet sich in system->application->libraries->dompdf
Es ist im nächsten Schritt zu ermitteln, welcher PDF-Adapter verwendet wird, ich nutze cpdf (wird ein anderer genutzt, kann die Änderung analog vorgenommen werden)
Danach wird die Datei geöffnet: system->application->libraries->dompdf->include->cpdf_adapter.cls.php
In der Datei ist bereits eine Funktion „page_text“ zu finden, mit ihr kann Text auf jeder beliebigen Seite einfügt werden
* Writes text at the specified x and y coordinates on every page
*
* The strings '{PAGE_NUM}' and '{PAGE_COUNT}' are automatically replaced
* with their current values.
*
* See {@link Style::munge_colour()} for the format of the colour array.
*
* @param float $x
* @param float $y
* @param string $text the text to write
* @param string $font the font file to use
* @param float $size the font size, in points
* @param array $color
* @param float $adjust word spacing adjustment
* @param float $angle angle to write the text at, measured CW starting from the x-axis
*/
function page_text($x, $y, $text, $font, $size, $color = array(0,0,0),
$adjust = 0, $angle = 0) {
$_t = "text";
$this->_page_text[] = compact("_t", "x", "y", "text", "font", "size", "color", "adjust", "angle");
}
Neben Text benötige ich noch eine Linie und ein Bild im Header.
Deswegen werden nun die folgenden Funktionen/Methoden angefügt
* Processes a line on every page
*
*
*/
function page_line($x1, $y1, $x2, $y2, $color, $width, $style = array(),
$blend = "Normal", $opacity = 1.0) {
$_t = "line";
$this->_page_text[] = compact("_t", "x1", "y1", "x2", "y2", "color", "width", "style",
"blend", "opacity");
}
//........................................................................
/**
* Processes a image on every page
*
*/
function page_image($img_url, $img_type, $x, $y, $w, $h) {
$_t = "image";
$this->_page_text[] = compact("_t", "img_url", "img_type", "x", "y", "w", "h");
}
//........................................................................
Dann werden die Methode gesucht, in der die Daten verarbeitet werden (_add_page_text)
Die Methode muss folgendermaßen angepasst werden
* Add text to each page after rendering is complete
*/
protected function _add_page_text() {
if ( !count($this->_page_text) )
return;
$page_number = 1;
$eval = null;
foreach ($this->_pages as $pid) {
$this->reopen_object($pid);
foreach ($this->_page_text as $pt) {
extract($pt);
switch ($_t) {
case "text":
$text = str_replace(array("{PAGE_NUM}","{PAGE_COUNT}"),
array($page_number, $this->_page_count), $text);
$this->text($x, $y, $text, $font, $size, $color, $adjust, $angle);
break;
case "script":
if (!$eval) {
$eval = new PHP_Evaluator($this);
}
$eval->evaluate($code, array('PAGE_NUM' => $page_number, 'PAGE_COUNT' => $this->_page_count));
break;
//-----neu--------
case "line":
$this->line($x1, $y1, $x2, $y2, $color, $width, $style = array(),
$blend, $opacity );
break;
case "image":
$this->image($img_url, $img_type, $x, $y, $w, $h);
break;
}
}
$this->close_object();
$page_number++;
}
}
Das Ganze ist noch nciht 100 % perfekt, aber funktioniert erstmal (besser ist es, wenn Klassen abgeleitet werden)
Wie wird dies jetzt in Codeigniter genutzt?
Als Beispiel soll uns ein einfacher Controller dienen
.....
function export_lack_2_pdf(){
require_once(APPPATH . 'libraries/dompdf/dompdf_config.inc.php');
/* man hat irgendwo sein HTML Template liegen
*das lässt man erstmal mit dem view-handler
*von codeigniter verarbeiten
*/
$html = $this->load->view("content/mangel/templates/export_html.php", $this->data,true);
$my_font_family = "Arial";
$dompdf = new DOMPDF();
$dompdf->set_paper('A4');
$dompdf->load_html($html);
$dompdf->render();
//nun kommt der Header-Teil
$font = Font_Metrics::get_font($my_font_family);
$left = 45;
$text = $this->lang->line('ein_beispieltext_aus_der_lang_datei');
$size = 14;
$color = array(0,0,0);
//canvas holen (das liegt beim inline code bereits vor bzw. wurde übergeben)
$pdf = $dompdf->get_canvas();
//ein Text einfügen (das ist standard)
$pdf->page_text($left, 35, $text, $font, $size, $color);
//nun ein Bild
//FCPATH wird in Codeigniter bereitgestellt
$bild = FCPATH."/img/logo.png";
//Größe verändern
$info = getimagesize( $bild );
//
//es soll auf Breite 100px skaliert werden
$w = 100;
$b = ceil($w * $info[1] / $info[0]);
$pdf->page_image($bild, "png", 450, 15,$w, $b);
//nun noch eine Linie
$pdf->page_line($left, 100, 530, 100, array(0,0,0), 1);
//jetzt der Export
$time = time();
// $dompdf->stream("mangel_".$time.".pdf",array("Attachment" => 0));
$dompdf->stream("mangel_".$time.".pdf");
}
.....
}
Ich hoffe ich es hilft jemandem, für Verbesserungen und Tipps bin ich offen
mfg Robert
Hallo Robert!
Dieser Blog-Eintrag half mir ein Problem mit DOMPdf nach etwa 60 Stunden Suche zu lösen.
Tausend Dank
Frohe Weihnacht und alles beste für 2011
lg
Mario
Hallo zusammen,
einen simplen header / footer habe ich nun hinbekommen.
Nun möchte ich das Ganze aber so anpassen, das der header erst ab der zweiten Seite zum tragen kommt. Alsoauf der ersten Seite Vereinslogo, Sitz usw. Dann den ersten Fließtext.
Geht der über mehr als eine Seite, nur ein verkleinertes Vereinslogo oben, mittig und dann weiteren Fliesstext.
Beste Grüße
Ollie