Printing with DOMPDF

My last programming problem was about printing a report from a web application. In the past I solved it using Internet Explorer’s print templates, but that solution had 2 drawbacks: the first was that it required IE 5.5 or later, the second was that the page customizations (margins, orientation, header and footers) required downloading an ActiveX. This was an easy requirement at the time due to the intranet use of the application.
Now that I have moved to Linux and Open Source software that is no more feasible. I had to find another solution.
The IT market is full of reporting tools for the web but most of them are expensive and require some kind of plug-in, since the browser alone is not capable of giving a precise rendering of the printed page. Yes, CSS has something to say about print media but these properties are mostly ignored by the current bunch of browsers.
And then there is my main requirement: all the software used must be Open Source.
After some thoughts I decided to produce a PDF print for my reports. A quick google search gave me a number of products to try. I could divide them in 3 categories:

  1. raw PDF libraries
  2. XSL-FO
  3. conversion tool from other format (i.e. HTML)

I didn’t even think to take into consideration the first solution. XSL-FO looked appealing in beginning, but when I looked more deeply to what was it about, I gave up. BTW just reading the word XML was enough to make me shiver.
The third approach seemed much simpler. Write the report in HTML, give it to the converter program and send the result to the user. Too good to be true: I didn’t have to learn another language and could even reuse the old reports written for IE print templates. The best known of such tools is htmldoc but unfortunately this is a very crude product. It interprets only HTML 3.2 and no CSS. Not very useful. Other products that I downloaded did not look better that htmldoc. I was somewhat amazed by the fact that such a simple and useful concept, an HTML to PDF converter, did not found a supporter in the Open Source that could produce a decent utility. Until I discovered dompdf. It is an impressive library. It supports most of the CSS directives (the notably exceptions being absolute positioning and floating). The first report that I tried worked like a charm. I took my HTML, passed through this utility and my PDF was there. Ok, I have been too enthusiastic. I found a couple of problems when I tried to bend it to some special needs that I had but nothing that some search in the documentation and in the forum couldn’t solve.
So, to help others that might encounter the same problems I thought to add a few points here to the dompdf FAQ:

1. how can I make it faster?
Up to version 0.5.1, there is a line in the library that uses a call to the uniqid() php function. Since this call is slow and it is done once for each dom node in the document, it slows down the translation in a sensible way. The workaround consists in changing the line 171 in file frame.cls.class:

$this->set_id(uniqid(rand()));  
with :
global $dompdf_unique_id;
if (isset($dompdf_unique_id)){
    $dompdf_unique_id++;
}else{
    $dompdf_unique_id = 1;
}
$this->set_id( $dompdf_unique_id );

Alternatively, change the same line with this:

uniqid ('', true) 

2. how can I put some data coming from the DB into the header/footer?
See Q.4 in the official FAQ. In the script, declare the variable you want to use as global, like this:

global $my_var;

3. how can I put a background on every page?

if ($draft)         // if TRUE print "DRAFT" across every page
{
    $obj_draft = $pdf->open_object();
    $pdf->text(200, $h - 300, "DRAFT",
               Font_Metrics::get_font("verdana", "bold"),
               110, array(0.8, 0.8, 0.8), 0, -52, "Darken", 1);
    $pdf->close_object();
    $pdf->add_object ($obj_draft, "all");
}

4. I followed the instructions in Q.4 but it doesn’t work?
Check that the tag

<script type="text/php">

is INSIDE the body tag.

5. how do I print a page generated from PHP?
All the examples in the official FAQ use the

$dompdf->load_html($html);

function, where $html is a string containing the document to print. But what if the document is the result of the current PHP page. Here the trick consists in buffering the PHP output and then using the load_html() on the content of the buffer. Like this:


<?php
ob_start();    // start buffering
...
// whatever
...
$dompdf = new DOMPDF();
$out = ob_get_clean();   // get the content of the buffer and clear it
$dompdf->load_html($out);
$dompdf->render();
$dompdf->stream ("Filename.pdf");
?>

6. ERROR: Unable to stream pdf: headers already sent
I came across this error few times. The reason was always due to 3 non visible characters at the beginning of the file, as a consequence of using an editor set with a different character encoding (e.g UTF-8, Latin 1, …).
Try to run the command

hexdump -C filename | less

and see what the initial characters are.
Beware that few editors allow to remove them. Emacs is one of these.

7. ERROR: Nesting level too deep - recursive dependency? in (…)/dompdf/include/table_frame_decorator.cls.php on line 143
This error often occurs when a table spans 2 or more pages. DOMPDF tries to split it and repeat the THEAD on the following page. In doing so, it calls the PHP in_array() function, which gives this error. There are 2 workarounds: one is deleting the TBODY tag, the other is patching the split() function found in table_frame_decorator.cls.php, and adding a 3rd argument (true) to the 3 in_array function calls found there. More or less like the following code:

    // If $child is a header or if it is the first non-header row, do
    // not duplicate headers, simply move the table to the next page.
    if ( count($this->_headers) && !in_array($child, $this->_headers, true) &&
         !in_array($child->get_prev_sibling(), $this->_headers, true) ) {

    ...

    } else if ( in_array($child->get_style()->display, self::$ROW_GROUPS, true) ) {

8. ERROR: Frame not found in cellmap
I encountered it when using the CSS attribute ‘page-break-inside: avoid’. A possible workaround is reported in the DOMPDF forum and consists in replacing all occurrences of

throw new DOMPDF_Internal_Exception("Frame not found in cellmap");

with

return false;

I don’t know any possible side effects, but it worked for me till now.
Another fix that worked for me in one occasion was replacing the markup used with the ‘page-break-inside: avoid’, in that case from DIV to P.

19 Responses to “Printing with DOMPDF”

  1. psychoactive Says:

    thanks! I have been using dompdf for about two years now, and i know in the beginning I ran into every problem addressed in this post. This should be helpful, and hopefully it’ll stir up more interest in dompdf from developers… i only wish i were better at programming… benj is amazing!

  2. Luca Priorelli Says:

    Thank you for the encouragement, psychoactive! I will try to update this FAQ as I progress in the use of this library.

  3. barrat Says:

    Thanks! I’ll be aware of your explanations. i’ve got problems rendering img in the footer.

  4. Felix Says:

    Hi.

    I have a tedious problem that I couldn’t to resolve at dompf. I want justify all my html into my flags, I have: my longtext.

    Thanks in advance.

  5. Luca Priorelli Says:

    Hi Felix,

    I am not sure I understand your question. Could you give an example of what you are trying to do?

    Luca

  6. Felix Says:

    Hi Lucas.

    I have a HTML page, it has justify paragraphs but DOMPDF is not rendering this style.
    How I can justify the paragraphs correctly?

    It seems DOMPDF cannot understand the css style that I’ve defined to.

    This is my css:

    p {
    text-align:justify;
    font-size:1em;
    margin:0.2em;
    padding:5px;
    }

    Thanks for your reply.

  7. Luca Priorelli Says:

    Hi Felix,

    I tried your style but it runs fine here. That is, it justifies correctly. Can you post the whole page you are trying to print?

    Luca

  8. Felix Says:

    Hi Luca.

    This is the html code that works for me:

    setNumero($monto);

    $html =

    Untitled Document

     
    Nº “.$codigo.”
    Mérida, “.$fecha.”

    SEÑORES:
    “.$contratista.”Ciudad.

    Por medio de la presente me dirijo a Usted, en la oportunidad de notificarle que se le (s) ha asignado la ejecución de la obra que a continuación se refiere:
    Objeto del Contrato de obra: “.$obra.”
    Ubicado en el Municipio: “.$munici.” DEL ESTADO MÉRIDA. PROGRAMA: FIDES 2007.
    Código Presupuestario: 04-27-02-12-10-02-4,04-02-02-10 , Monto Sin IVA Bs.: 362.918.379,17
    Código Presupuestario I.V.A: 04-27-02-00-00-02-4,03-18-01-01, Bs. 0,00
    Monto total de la Obra: El monto a contratar será hasta por la cantidad de ” .$aletra->letra() .” (BS.: “.$monto.”) cuya forma de pago se hará conforme a Ley de Condiciones Generales para la Contratación de Obras, según Decreto Nro 1417, Publicado en Gaceta Oficial del Nro. 5096 de fecha 16 de septiembre de 1996. A fin de proceder a la respectiva contratación le agradezco ponerse en comunicación con la Gerencia de planificación  y Gestión del INMIVI, el cual tiene como domicilio la Av. Cardenal Quintero Centro Comercial El Viaducto Nivel Mezzanina a objeto de formalizar todo lo relativo a la contratación respectiva, en un lapso perentorio de 15 días continuos contados a partir de la fecha de la entrega de la presente comunicación, de lo contrario la Asignación queda sin efecto de inmediato, y será reasignada a otro beneficiario.     En caso de ser imposible la notificación de la presente queda rescindida de pleno derecho la presente carta asignación, si no se lograre su notificación dentro de los 5 días hábiles siguientes a la emisión de la presente.      La administración del Instituto Merideño de Infraestructura y Vialidad  puede dejar sin efecto la presente carta asignación, cuando a bien lo considere no dando lugar a indemnización alguna a favor de quien se emite la presente carta asignación, bastando para ello notificar al beneficiario de la presente Carta Asignación mediante notificación o publicación en periódico local o nacional, como a bien lo considere el ente.     El beneficiario de la presente Carta Asignación debe cumplir con todos los trámites administrativos previos y de ley para el otorgamiento del contrato, so pena que el Instituto deje sin efecto la asignación librada a su favor y debidamente notificada, cuando a bien lo considere por incumplimiento de los requisitos. El beneficiario de la presente Carta Asignación debe suscribir  el contrato conforme a las condiciones que predetermine el INMIVI y la Ley de Condiciones Generales de Contratación de Obras.      En caso de negativa del beneficiario a suscribir el contrato que dimana con base a la presente carta asignación, el Instituto dejará sin efecto la asignación y los efectos legales que dimanan de la misma, sin indemnización alguna a favor del beneficiario.
    ING. ROBERTO MOLINA
    PRESIDENTE
    INSTITUTO MERIDEÑO DE INFRAESTRUCTURA Y VIALIDAD (INMIVI)

    Notificado Nombre (s) y Apellidos (s)
    _____________________________________
    Firma:________________________________
    Lugar y Fecha:__________________________
    Teléfono.______________________________

    Av. Cardenal Quintero. CC. El Viaducto, Nivel Mezzanina, Mérida - Venezuela. Telfs.: (0274) 244 2948 - 244 5112

    “;

    $dompdf = new DOMPDF();
    $dompdf->load_html($html);

    $dompdf->render();
    $dompdf->stream(”carta_Asignacion.pdf”, array(”Attachment” => 0));

    ?>

    Thanks for your help.

  9. Felix Says:

    This is the html’s head

    Untitled Document

  10. Felix Says:

    //

    Untitled Document

  11. Felix Says:

    Hi Luca.

    Can you give me an email address where I can send the complete raw html?, because the blog is processing the html code.

  12. Luca Priorelli Says:

    luca at priorelli dot com

  13. David Says:

    Estoy intentando usar el sistema del script type=”text/php” y no parece que funcione. Mas bien parece que ignora lo que pongo alli ya que no me lo hace.

    ¿necesito alguna configuracion especial del apache? tengo php5.2

  14. DeepVoid Says:

    I’m trying to create a header for the A4 page format (vertical orientation) with just an image (a corporate logo), to be added to all the pages in the PDF document, without any success. A little suggestion would be welcome, a snippet, a little hint…

    Official docs aren’t helpful on this matter, imho.

    Thank you all! :-)

  15. DeepVoid Says:

    About official dompdf’s support, the official forum seems to be unmanaged by the author; you can find many spam postings, often related with porn content, among the rightful messages by the actual users.

    Is dompdf a dismissed project? I’m looking for a reliable PDF generator for my commercial projects, I’ll consider different softwares in this case…

  16. Luca Priorelli Says:

    To DeepVoid: Is dompdf a dismissed project? I’d like to know it as well. I asked your same question in the forum, and so did others. Every time the answer is: no, it isn’t. I’d like that those that give such an answer would also explain few other things. It’s a pitty that such a promising software, would be left in the present, uncompleted, state.

    There are other options, but those that I tried were worse than this, at least for my needs. In any case, even in its present state, it is adeguate for the prints that I produce.

    Maybe the unicode support is awkward, some offically supported tags do not work very well when used in given combinations, the CSS support is lacking, but overall I have always been able in some way to reach the intended result.

  17. Luca Priorelli Says:

    To DeepVoid: there is a full example(http://www.digitaljunkies.ca/dompdf/faq.php#image_footers) in the dompdf FAQ. Does not work for you? What is exactly the problem you encountered? In several occasions I found that there is a problem with image rendering. Depending on the image format and the operating system used, images can be visible, invisible or just wrong.

  18. Luca Priorelli Says:

    To David: can you post here an example of your code?

  19. Bhakti Says:

    hi,
    i am suddenly getting below error on my page. what could be the problem? Please help me

    Argument #2 should be an array in /var/www/developmentfolder/includes/dompdf/include/abstract_renderer.cls.php on line 689

Leave a Reply