DOMPDF es un conversor de HTML a PDF escrito en PHP. Interpreta HTML y CSS para la generación de documentos en PDF con un soporte bastante adecuado para CSS 2.1, incluso algunos avanzados como bordes redondeados en las cajas. En este post presentaré algunas peculiaridades de esta librería que espero ayuden a sacar partido de la versatilidad del HTML para generar documentos en PDF.

Parece que mucha gente se olvida que HTML permite trabajar en muchos soportes distintos, no solo en display, sino también en impresora. Hoy en día documentación como albaranes de compra en comercio electrónico se generan online para enviar al comprador. Haremos uso de esta característica de HTML para componer HTML ajustado a soporte papel que será el que utilizaremos para generar PDFs.

Donde obtener la librería e instalación

Podeís obtener la versión más actualizada en GitHub y tiene una buena documentación y ejemplos en inglés de uso. Como veis no es especialmente exigente en sus requerimientos:

  • PHP 5.3+ (recomendado)
  • DOM extension
  • GD extension

Siguiendo las instrucciones es sencilla su instalación en cualquier proyecto.

<?php
// Cargamos la librería dompdf que hemos instalado en la carpeta dompdf
require_once ('dompdf/dompdf_config.inc.php');
 
// Introducimos HTML de prueba
$html = '<h1>Hola mundo!</h1>';
 
// Instanciamos un objeto de la clase DOMPDF.
$pdf = new DOMPDF();
 
// Definimos el tamaño y orientación del papel que queremos.
$pdf->set_paper("A4", "portrait");
 
// Cargamos el contenido HTML.
$pdf->load_html(utf8_decode($html));
 
// Renderizamos el documento PDF.
$pdf->render();
 
// Enviamos el fichero PDF al navegador.
$pdf->stream('FicheroEjemplo.pdf');

Peculiaridades a tener en cuenta

Aunque facilita mucho la generación de los documentos es importante tener en cuenta algunos aspectos en lo tocante al HTML y la codificación:

  • Utiliza siempre UTF8. Aunque ya deberías de saberlo y deberías de utilizarlo siempre como charset por defecto en Bases de datos, codificación de ficheros, etc no está de más recordarlo. DOMPDF utiliza por defecto este charset y no le sienta nada bien la mezcla. Te puedes encontrar con que no muestra el volcado de datos que te interesa simplemente porque se encuentra un carácter en una codificación inadecuada.
  • Tamaño del papel y orientación. Por supuesto puedes elegir el tamaño de papel que desees. La clase que incluye los tamaños de papel y sus dimensiones se encuentra en include/cpdf_adapter.cls. Si necesitas utilizar un tamaño de papel personalizado utiliza la siguiente sintaxis con las dimensiones que necesitas:

    $paper_size = array(0,0,360,360);
    $dompdf->set_paper($paper_size);
  • El fichero de configuración. Es el fichero que utilizamos en el include, como verás se encuentra bien documentado, por defecto dompdf_config.inc.php

La generación del HTML

Unos breves consejos a la hora de preparar nuestro HTML para generar el PDF:

Utiliza tablas en la maquetación

Efectivamente. Aquello que no nos cansamos siempre de decir: las tablas se deben de utilizar para mostrar datos tabulares, no para maquetar o diseñar. Olvídate. El soporte que tiene de la propiedad CSS float: es bastante limitada así que para simplificar es mejor utilizar tablas como si estuvieras preparando el HTML de una campaña por email.

Nada de HTML5

Aunque tiene cierto soporte HTML5 tampoco tiene mucho sentido de cara a la generación de ficheros PDF, así que si estás generando el HTML de cero puedes ahorrártelo.

Utilización de imágenes en PNG y JPG

La renderización de imágenes es perfecta, utilizando cada tipo de fichero para lo que es. Puedes utilizar PNG para logotipos aprovechando que puede manejar canal alpha y transparencia; y los JPG para fotografías.

Piensa en papel

Aunque es obvio a veces se nos olvida que el soporte al que va destinado nuestro HTML es papel. Por este motivo (y más sin contamos con una plantilla de documento) debemos de utilizar medidas basadas en mm en todo lo relativo a márgenes de documento, en tablas, etc.

Lo mismo se aplica a los tipos de letra. Recuerda que la unidad a utilizar son los .pt (puntos). Si cuentas con un documento de texto (.doc, .odt, etc) en el que basarte aún mejor, tendrás toda esa información en el acto consultando las propiedades del documento o colocando el ratón sobre los tipos de letra para conocer su propiedades.

Si no cuentas con una plantilla digital consigue una regla de diseño gráfico que mida tanto en mm como en pt.

Márgenes a cero

Por defecto a la hora de preparar el HTML te aconsejo que situes los márgenes a 0 y sea en el body donde definas los márgenes.

html {
margin: 0;
}
body {
font-family: "Times New Roman", serif;
margin: 45mm 8mm 2mm 8mm;
}

Saltos de página manuales

Los saltos de página como cualquier editor DOMPDF los realiza de forma auomática, pero podemos forzar que la aparición de un elemento en HTML provoque el salto de linea. Yo generalmente utilizo el tag <hr> con las siguientes propiedades CSS:

hr {
page-break-after: always;
border: 0;
margin: 0;
padding: 0;
}

Incluir cabeceras y pies de página fijos

DOMPDF hace un uso bastante inteligente de la propiedad position: de CSS. Cualquier elemento situado con fixed se repetirá a lo largo de todas las páginas del documento. Lo cual hace que sea una propiedad muy útil para incluir logos de empresa, direcciones, datos de contacto, etc.

Si por contra utilizamos position: absolute su comportamiento será el habitual, pudiendo situar un elemento en cualquier posición de la página con las propiedades top: y left:. Pero sólo en la página actual.

Incluir números de página

DOMPDF permite ejecutar código PHP embebido. Tienes más información en la documentación oficial, pero uno muy importante es el relativo a la paginación. En cualquier documento poder incluir el número de páginas es fundamental y para ello podemos utilizar el siguiente código que nos incluirá la paginación en el punto que le indiquemos:

<script type="text/php">
if (isset($pdf))
{
$font = Font_Metrics::get_font("Arial", "bold");
$pdf->page_text(765, 550, "Pagina {PAGE_NUM} de {PAGE_COUNT}", $font, 9, array(0, 0, 0));
}
</script>

IMPORTANTE: Recuerda activar en la configuración de DOMPDF DOMPDF_ENABLE_PHP = true o de lo contrario no ejecutará el código y no veremos la paginación.

Empleo de buffers y $_SESSION

Cuando quieras generar algún tipo de documento complejo en HTML comprobarás que ciertos modos de generarlo en PHP no son válidos, sobre todo en aquellos en el que vas generando el HTML dentro de un buffer para volcar luego todo el contenido en una variable en PHP. Por algún motivo no suele funcionar de forma directa. Y por otro lado ir concatenando cadenas y cadenas de HTML al final es bastante aburrido.

Por ese motivo lo que suelo hacer es grabar el contenido HTML por medio de buffers, almacenar la información en una variable de sessión; y en un controlador aparte recuperar el contenido de la variable de sessión con el HTML para que lo genere DOMPDF. Por ejemplo:

<?php
session_start(); 
// Iniciamos el buffer
ob_start();
// Operaciones para generar el HTML que pueden ser llamadas a Bases de Datos, while, etc...
require_once ('plantilla.html');
(...)
// Volcamos el contenido del buffer
$html = ob_get_clean();
 
// Creamos la variable de sesión
$_SESSION['pdf']['content'] = $html;
$_SESSION['pdf']['filename'] = 'Informe.pdf';
$printpdf = true;

Desde aquí procedemos a la carga del controlador que ejecuta el siguiente código si encuentra $printpdf = true; en otro punto de la ejecución.

<?php
session_start();
// DOMPDF según el tipo de documento a imprimir o la cantidad puede ser muy exigente así que aumentamos la memoria disponible
ini_set("memory_limit", "128M");
 
// Cargamos DOMPDF
require_once 'dompdf/dompdf_config.inc.php';
 
// Recuperamos la información de la sesión
$html = $_SESSION['pdf']['content'];
$filename = $_SESSION['pdf']['filename'];
 
// Volcamos las páginas en papel
$dompdf = new DOMPDF();
$dompdf->set_paper('A4', 'landscape');
 
// Se carga el codigo html
$dompdf->load_html($html);
// Lanzamos a render
$dompdf->render();
// Guardamos a PDF
$dompdf->stream($filename);
 
// Borramos la variable de sesión
unset($_SESSION['pdf']);

Eso es todo. Espero que os sea de utilidad.

Fuentes

Página oficial de DOMPDF
Generación de PDF’s con PHP y la librería DOMPDF
De Manuais Informática – IES San Clemente.

Personalizar el tamaño de página en DOMPDF

Comparte si te ha gustado

Autor:
Última actualización:

57 comentarios

    1. Para ello, si quieres imprimir la cabecera en todas las páginas deberías de utilizar las propiedades CSS position: fixed y situar con top: y left: con la medida en mm por ejemplo. Recuerda que ahora debes de pensar en soporte papel. De este modo la replicarás en todas las páginas en la posición que le hayas indicado.

  1. Hola amigo, actualmente tengo #footer .page:after { content: counter(page); font-size: 12px; } y el resultado es Pág 1, Pág 2, segun su numero. Pero l querer implementar este codigo #footer .page:after { content: counter(page) ” de ” counter(pages); font-size: 12px; } quisiera me mostrara pag 1 de 3, pagina 2 de 3. por dar un ejemplo. pero con el codigo q te envie me sale pag 1 de 0, 2 de 0. espero me entiendas y puedas ayudarme. gracias

    1. Espero que te sirva la siguiente solución. Yo la implementé en un desarrollo reciente. Se trata de incluir un código similar al siguiente en la cabecera:

      <script type=”text/php”>
        if (isset($pdf))
          {
            $font = Font_Metrics::get_font(“Arial”, “bold”);
            $pdf->page_text(765, 550, “Pagina {PAGE_NUM} de {PAGE_COUNT}”, $font, 9, array(0, 0, 0));
          }
      </script>

      Eso sí luego tienes que posicionar la paginación mediante el método page_text del objeto DOMPDF.

      Fuente original: http://stackoverflow.com/questions/13159645/dompdf-page-number

  2. Hola amigo

    Mi problema es el siguiente, cuando es mas de una pagina el encabezado tapa o se superpone sobre la información que continua en la siguiente pagina; es decir la pagina 1 termina con : “este es el fin de la pagina uno” y la pagina 2 inicia con “este es el comienzo de la pagina dos”, pero el encabezado tapa esa linea.

    Que podría hacer en ese caso?

    Gracias de antemano.

    1. Eso es porque no le has reservado espacio en los márgenes de la página por CSS. Piensa en el <body> como si fuera el papel en blanco. Tienes que definirle márgenes. Por contra, lo que utilices como encabezamiento con position: fixed flota por encima del contenido, por lo que se “monta” sobre él.

      Esto lo podemos evitar si al “body” le asignamos margenes, teniendo en cuenta la altura del encabezado. Si tengo un encbezado que va a ocupar 20mm de altura, puedo reservarle una altura de 30mm siempre en todas las páginas para que no se solapen. Utilizaremos el siguiente CSS, con todos los márgenes de la página.

      body {
      margin: 30mm 8mm 2mm 8mm;
      }
      
  3. Hola queria consultarle sobre el tema del dompdf con el css. Tengo un problema que el dompdf no me toma los css de las tablas que tengo en el html, me tira el siguiente error: block_frame_reflower.cls.php on line 171 y el css que esta causando el problema es el siguiente: #tabla{
    height:100%;
    /*width: 220px;*/
    margin:auto;
    display: inline-block;
    }
    table,th,td{
    font-family: serif;
    font-size: 0.9em;
    border:1px solid black;
    border-collapse: collapse;
    }
    me podria dar alguna ayuda, estoy trabado con este tema y tengo que transformar mi pag a pdf si o si. Desde ya muchas gracias.

    1. Gracias por tu comentario. La verdad es que con la información que me aportas poco te puedo ayudar.

      Si crees realmente que el problema viene del CSS ve probando a eliminar una a una las lineas del CSS (no comentarlas entre /* */ sino eliminarlas) que estás utilizando hasta que no te arroje el error.

      Si tras eliminar todo el CSS sigue sin funcionar está claro que el problema no es del CSS, sino de código HTML mal formado o de la programación. También te advierto que DOMPDF es especialmente estricto en la formación válida del HTML.

    1. Es importante que te asegures que permites la ejecución de PHP como script dentro del HTML generado con DOMPDF. En el raíz de la clase tienes el fichero dompdf_config.inc.php. Busca ahí la constante def("DOMPDF_ENABLE_PHP", false); y cámbiala por true para que interprete el código PHP e incluya los números de página.

  4. que tal amigo fijate que yo cree una archivo php para que me genere un reporte en pdf lo genera y todo pero al abrirlo me dice que es un archivo no admitido o esta dañado y adobe reader no lo abre ni otro lector de pdf revise el codigo minusiosamente y no logro solucionarlo en word y excel al generar si me funciona re bien pero con pdf no

    1. Cuando un fichero generado con DOMPDF te arroja dicho error es porque no se ha creado correctamente. Te recomiendo que revises el HTML que generas pues probablemente sea incorrecto o arroje algún error en texto. Para ello desactiva la salida y haz un volcado en pantalla del HTML generado para poder depurarlo.

  5. Amigo como recibo los datos traidos de php en dompdf…
    normalmente lo muestro en pantalla con un echo
    echo $this_persona[0][‘nombre’];
    si pongo eso mismo asi
    echo $this->_persona[0][“cedula”];
    no me aparece nada sale vacio….

    1. A ver. Con DOMPDF lo que tienes que generar primero una cadena que sea un documento HTML válido. Es ahí donde tienes que hacer el volcado de datos, en esa cadena. A DOMPDF le pasarás el HTML una vez ya formado previamente con todos los datos. No puedes hacer el echo dentro, por lo menos de una forma fácil, y no es aconsejable.

  6. Estoy realizando una aplicacion que genere un pdf , el problema es que solo me muestra un registro cuando la tabla tiene 3 registro, no he podido hacer que mande los 3 registros, sabras como se le puede hacer?

    1. DOMPDF no te elimina registros de las tablas pues simplemente se limita a renderizar el HTML. Tiene toda la pinta de que el HTML que construyes es defectuoso y por lo tanto no puede generar correctamente el PDF. Te recomiendo que te asegures de que tu HTML no tiene errores y cumple el estandar XHTML.

  7. Buenas tardes amigo tengo un problema y es el siguiente tengo mi archivo .php y dentro de el tengo una variable que almacena todo el codigo html $var=’html code’ todo fino pruebo este código html normal y sale perfecto como quiero pero cuando se lo paso al pdf para que lo genere lo genera de forma defectuosa es decir, un pedazo de mi html contiene lo siguiente q es donde esta dando la imperfección:

    >>
    >>
    Este codigo como dije arriba funciona perfectamente en un archivo html pero cuando lo saco en pdf la imagen sale mal o no abarca el div completo que si por la mitad
    Espero que me puedas ayudar. Saludos

  8. Hola. Tengo un problema con los acentos. Cuando una palabra lo tiene se lo come.
    Por ejemplo : “Cajón” me lo muestra como “Cajn”
    He consultado en foros y manuales y no lo consigo solucionar. Puse como juego de carácteres en el charset de la cabecera UTF-8 para evitar problemas.
    Utilicé en la llamada al html tanto utf8_encode como utf8_decode pero nada.

    Te pongo el código que he utilizado :
    set_paper(‘A4’, ‘portrait’);
    $dompdf->load_html(utf8_decode(“$html”));
    $dompdf->render();
    $dompdf->stream(‘catalogo.pdf’);
    ?>

    Muchas gracias de antemano

    1. Es una buena opción que utilices UTF8. Sin embargo no te recomiendo que uses las funciones de utf8_encode, utf8_decode de no ser estrictamente necesario. Asegúrate primero, y por este orden, de cual es la codificación de:

      • El fichero .php. Ten cuidado no esté en Latin-1, Windows-1252-1, etc. Si utilizas un buen editar busca la opción de “Convertir a UTF-8”.
      • El origen de datos de la información. Si es una BDD asegúrate de que en la conexión utilizas la codificación correcta. Si lees un fichero o un include, lo mismo que en el punto anterior. Asegúrate de la codificación del fichero.
  9. Buenos dias, tengo un problema cuando el codigo es puramente html no tengo problema pero cuando incluyo PHP me da errores
    esta es la linea que ingreso
    <?php
    echo "“.”Al “.” “.$jerarquia2.”  “.”(L.P N:”.$legajo2.” “.”) Dn.”.$apellido2.”“;
    ?> o tambien

    <?php
    print "”
    ?>

    este es el error que tira

    ( ! ) Parse error: syntax error, unexpected T_STRING in dompdf\include\dompdf.cls.php(443) : eval()’d code on line 10

    ya verifique y el php esta en true no se que puede ser. desde ya muchas gracias

  10. Hola estimado Oscar:
    Termine de crear mi documento pdf pero lo que deseo es enviarlo directamente a la impresora sin la previsualizacion que aparece en Adobe, con que instruccion de dompdf lo podria hacer? .
    Gracias por responder.

    1. Pues no puedes enviar desde PHP un trabajo a la impresora directamente. El trabajo de DOMPDF termina en cuanto genera el documento. El trabajo de imprimirlo ya es cuestión del navegador. Además como el PDF se abre en un componente embebido y distinto al navegador no creo que puedas imprimirlo directamente…

  11. Hola estimado, espero me puedas ayudar con este mensaje que me sale, al intentar cargar la pagina que me genera los pdfs en base a un xml: Fatal error: Uncaught exception ‘Dompdf\Exception’ with message ‘Min/max width is undefined for table rows’ in C:\xampp\htdocs\pdf\dompdf\src\FrameReflower\TableRow.php:66 Stack trace: #0 C:\xampp\htdocs\pdf\dompdf\src\FrameDecorator\AbstractFrameDecorator.php(806): Dompdf\FrameReflower\TableRow->get_min_max_width() #1 C:\xampp\htdocs\pdf\dompdf\src\FrameReflower\AbstractFrameReflower.php(205): Dompdf\FrameDecorator\AbstractFrameDecorator->get_min_max_width() #2

    1. Aparentemente tienes un problema con la maquetación de alguna tabla en HTML. Ya sabes que DOM/PDF es muy estricto. Sin embargo como pueden ser muchos factores te recomiendo que busques en Google más casos similares al tuyo. Seguro que en el enclace que te pongo a continuación encuentras alguien que le sucede lo mismo que a tí.

      https://www.google.es/?gfe_rd=cr&ei=30F3WIvNFuXU8gevvrPwBQ#q=Dompdf%5CException+Min%2Fmax+width+is+undefined+for+table+rows

      La mejor manera de aprender es buscando los errores en Google. 😉

  12. hola oscar una pregunta quiero usar el dompdf para convertir una pag html en pdf, si le paso el URL con load_html funciona bien , pero si trato de usar el metodo load_html_file me da error este
    Fatal error: Uncaught exception ‘DOMPDF_Exception’ with message ‘Permission denied on archivo.php The file could not be found under the directory specified by DOMPDF_CHROOT.’ in C:\xampp\htdocs\Pasantias pdf\dompdf-0.6.0\include\dompdf.cls.php:491 Stack trace: #0 ruta/Cdompdf.php(13): DOMPDF->load_html_file(‘archivo.php’) #1 {main} thrown in ruta\…\dompdf-0.6.0\include\dompdf.cls.php on line 491

    1. El error parece muy claro. La ruta que le indicas no es correcta y no encuentra el fichero. ‘Permission denied on archivo.php The file could not be found …’

      C:\xampp\htdocs\Pasantias pdf\dompdf-0.6.0\include\dompdf.cls.php Lo primero que veo es que tienes un espacio en la ruta Pasantias pdf y suele ser mala idea trabajar en web e incluir espacios en las rutas. En programación y web es mejor utilizar guiones (-) o caracteres (_) subrayados para evitar el uso de espacios. Por otro lado intenta evitar siempre rutas absolutas. No se si es tu caso, pero siempre mejor utilizar rutas relativas. Salu2.

  13. Que tal oscar, buena investigacion.
    Me gustaria implementar dompfd en una tabla y vaciar los datos desde una consulta hacia mi base de datos, no me sale al realizarlo.
    Estoy utilizando este codigo.

    Listado de maquinas!!

    noMaquina
    marca
    tipo
    capacidad
    FechaLegada

    set_paper(“A4”, “portrait”);

    # Cargamos el contenido HTML.
    $mipdf ->load_html(utf8_decode(‘http/localhost/CustomPak/dompdf/index.php’));

    # Renderizamos el documento PDF.
    $mipdf ->render();

    # Enviamos el fichero PDF al navegador.
    $mipdf ->output();
    ?>

    1. Es más que probable que no te funcione porque el HTML que le envías no esté bien formado. Asegúrate primero que la URL esté bien. Además tienes errores en la URL. Tienes “http/localhost/CustomPak/dompdf/index.php”. No sólo tienes errores en el protocolo… Asegúrate que el servidor es el correcto, porque intentará leer esa ruta en el propio servidor.

  14. hola Oscar Gascón buena tarde, he estado usando dompdf y me ha resultado fácil, pero ahora tengo un problema, estoy tratando de hacer reportes muy grandes o pesados y me sale este mensaje “Fatal error: Allowed memory size of 67108864 bytes exhausted (tried to allocate 32 bytes) in”, mi pregunta es ¿el tamaño es problema del servidor que uso o puedo configurar algún archivo del dompdf? te agradeceria me pudieras ayudar. muchas gracias y saludos

  15. hola! tengo la siguiente situación:

    en una computadora que uso para desarrollo funciona correctamente el reporte pero al pasarlo a otra computadora se sigue ejecutando el reporte pero lo único que no aparece es el número de página.

    ambas computadoras tienen def(“DOMPDF_ENABLE_PHP”, true);

    me podrías orientar sobre qué puede estar pasando ?

    gracias.

    1. Pues te recomendaría que te aseguraras de que realmente sea así y en el momento que invoques la clase DOMpdf, a continuación en tu código hagas un

      var_dump(DOMPDF_ENABLE_PHP);
      die;

      Y realmente te asegures que realmente se está aplicando dicha configuración. Lo siguiente asegurarse que es la misma versión de PHP, de DOMPdf, etc. Espero que lo encuentres pronto.

  16. Intente hacerlo con HTML2PDF, solo que no funciono me saca paginas en blanco y algunos rectángulos. Voy a tratar de hacerlo con con dompdf, siguiendo este artículo. Soló una cuestión funciona par probarlo primero en un localhost de windows y hay un sitio oficial donde bajar la librería dompdf ?

    Saludos desde México

  17. Buen dia Oscar, me podrias ayudar con esto…
    Estoy haciendo un reporte con dompdf y todo esta bien ya me funciona, pero tengo problemas con los margenes, los datos los traigo de una base de datos y me los muestra en una tabla pero cuando son muchos esa tabla crece y se pasa a una segunda pagina, pero quiero que esa segunda pagina tenga un margen arriba porque la tabla en la segunda pagina me queda muy pegada a la parte superior, gracias…

    1. Lo que tendrás que hacer es calcular manualmente cuantas filas de tabla caben en una página y cerrar la tabla para cada página. Luego por en el HTML introduces algún elemento que indique que es una página nueva y le pones una propiedad CSS que “cree una nueva página”. Recuerda que CSS también admite como soporte “print”. En la nueva página simplemente comienza otra vez la tabla y repites las operación tantas veces como haga falta.

      Si necesitas ayuda con el CSS:

      http://stackoverflow.com/questions/3262318/how-does-page-break-before-css-property-work

  18. Me han servido mucho estos comentarios.

    Tuve un problema que simplemente, el explorador indicaba que la Pagina No Funciona. Muy confuso pues me llevó a verificar la coherencia del HTML, de PHP y de CSS linea por linea y nada que modificara, incluso modificando la estructura me funcionaba hasta que la intuición llegó y me dijo: en DIV tiene demasiada información.

    Opte entonces por cortar el div en dos parte y listo. Espero sirva. Saludos.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.