1. Code
  2. PHP

Cómo generar un archivo PDF en PHP

En este artículo analizaremos cómo puedes generar archivos PDF en PHP. Usaremos la biblioteca TCPDF para crear documentos PDF mediante la programación.
Scroll to top
12 min read

Spanish (Español) translation by Ana Paulina Figueroa (you can also view the original English article)

En este artículo analizaremos cómo puedes generar archivos PDF en PHP. Usaremos la biblioteca TCPDF para crear documentos PDF mediante la programación.

Si estás trabajando en un sitio web que permite a los usuarios descargar o imprimir documentos como recibos de pedidos, cuentas o facturas, tienes un par de opciones. Puedes mostrar el documento incorporado en el navegador o proporcionar una descarga. Cuando se trata de descargar documentos, PDF es uno de los mejores formatos y es una excelente opción para preservar el formato del texto.

Entonces, si quieres aprender cómo generar archivos PDF en tu sitio web PHP, ¡estás en el lugar correcto!

Cómo instalar la biblioteca TCPDF

En esta sección veremos cómo instalar la biblioteca TCPDF.

Existen diferentes maneras de instalar la biblioteca TCPDF en tu servidor. La biblioteca TCPDF está disponible en Packagist y en GitHub, por lo que puedes usar Composer o clonarla de GitHub. En nuestro caso, vamos a instalarla con Composer.

Continúa y ejecuta el siguiente comando para instalar la biblioteca TCPDF con Composer.

1
$composer require tecnickcom/tcpdf
2
Using version ^6.3 for tecnickcom/tcpdf
3
./composer.json has been created
4
Loading composer repositories with package information
5
Updating dependencies (including require-dev)
6
Package operations: 1 install, 0 updates, 0 removals
7
  - Installing tecnickcom/tcpdf (6.3.5): Downloading (100%)         
8
Writing lock file
9
Generating autoload files

Una vez que se haya instalado correctamente, debes incluir el archivo autoload.php en tu script de PHP, como se muestra en el siguiente fragmento de código.

1
<?php
2
require "./vendor/autoload.php";
3
...
4
?>

Y, con eso, estás listo para usar todos los métodos de utilidad proporcionados por la biblioteca TCPDF.

Cómo usar la biblioteca TCPDF

En esta sección crearemos un ejemplo real que demuestra cómo generar una factura en PDF. La biblioteca TCPDF proporciona una gran cantidad de plantillas listas para ser usadas que puedes utilizar como referencia para generar documentos PDF. Sin embargo, vamos a generar una factura desde cero.

Como ya mencioné en la sección anterior, la biblioteca TCPDF proporciona muchas plantillas listas para ser usadas que te permiten generar archivos PDF genéricos con encabezados y pies de página. Y eso es realmente útil si estás satisfecho con el formato y con las configuraciones predeterminadas. Pero si quieres personalizar el encabezado y el pie de página junto con el contenido, tendrás que extender la clase TCPDF y sobrescribir los métodos correspondientes.

En nuestro ejemplo vamos a crear dos archivos: customPdfGenerator.php y example.php. En el archivo customPdfGenerator.php crearemos la clase CustomPdfGenerator, la cual extenderá la clase TCPDF principal y sobrescribirá un par de métodos. En el archivo example.php veremos cómo usar la clase CustomPdfGenerator.

La clase CustomPdfGenerator

Sigue adelante y crea el archivo customPdfGenerator.php con el siguiente contenido.

1
<?php
2
class CustomPdfGenerator extends TCPDF 
3
{
4
    public function Header() 
5
    {
6
        $image_file = '/web/logo.png';
7
        $this->Image($image_file, 10, 3, 25, '', 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false);
8
        $this->SetFont('helvetica', 'B', 20);
9
        $this->Cell(0, 15, '', 0, false, 'C', 0, '', 0, false, 'M', 'M');
10
        $this->Ln();
11
        $this->Cell(0, 15, 'Katie A Falk', 0, false, 'R', 0, '', 0, false, 'M', 'M');
12
    }
13
14
    public function Footer() 
15
    {
16
        $this->SetY(-15);
17
        $this->SetFont('helvetica', 'I', 15);
18
        $this->Cell(0, 10, 'Thank you for your business!', 0, false, 'C', 0, '', 0, false, 'T', 'M');
19
    }
20
21
    public function printTable($header, $data)
22
    {
23
        $this->SetFillColor(0, 0, 0);
24
        $this->SetTextColor(255);
25
        $this->SetDrawColor(128, 0, 0);
26
        $this->SetLineWidth(0.3);
27
        $this->SetFont('', 'B', 12);
28
29
        $w = array(110, 17, 25, 30);
30
        $num_headers = count($header);
31
        for($i = 0; $i < $num_headers; ++$i) {
32
            $this->Cell($w[$i], 7, $header[$i], 1, 0, 'C', 1);
33
        }
34
        $this->Ln();
35
36
        // Color and font restoration

37
        $this->SetFillColor(224, 235, 255);
38
        $this->SetTextColor(0);
39
        $this->SetFont('');
40
41
        // table data

42
        $fill = 0;
43
        $total = 0;
44
45
        foreach($data as $row) {
46
            $this->Cell($w[0], 6, $row[0], 'LR', 0, 'L', $fill);
47
            $this->Cell($w[1], 6, $row[1], 'LR', 0, 'R', $fill);
48
            $this->Cell($w[2], 6, number_format($row[2]), 'LR', 0, 'R', $fill);
49
            $this->Cell($w[3], 6, number_format($row[3]), 'LR', 0, 'R', $fill);
50
            $this->Ln();
51
            $fill=!$fill;
52
            $total+=$row[3];
53
        }
54
55
        $this->Cell($w[0], 6, '', 'LR', 0, 'L', $fill);
56
        $this->Cell($w[1], 6, '', 'LR', 0, 'R', $fill);
57
        $this->Cell($w[2], 6, '', 'LR', 0, 'L', $fill);
58
        $this->Cell($w[3], 6, '', 'LR', 0, 'R', $fill);
59
        $this->Ln();
60
61
        $this->Cell($w[0], 6, '', 'LR', 0, 'L', $fill);
62
        $this->Cell($w[1], 6, '', 'LR', 0, 'R', $fill);
63
        $this->Cell($w[2], 6, 'TOTAL:', 'LR', 0, 'L', $fill);
64
        $this->Cell($w[3], 6, $total, 'LR', 0, 'R', $fill);
65
        $this->Ln();
66
67
        $this->Cell(array_sum($w), 0, '', 'T');
68
    }
69
}

El aspecto importante a tener en cuenta es que la clase CustomPdfGenerator extiende a la clase TCPDF, por lo que podemos usar todos los métodos de utilidad proporcionados por la clase TCPDF para dar formato y generar documentos PDF.

El único propósito de crear nuestra propia clase, en lugar de usar directamente la clase TCPDF, es que no queremos usar los componentes integrados del encabezado y el pie de página. Y, por lo tanto, hemos sobrescrito los métodos Header y Footer en nuestra clase.

El método Header

En el encabezado queremos mostrar el logotipo de una empresa junto con el nombre del propietario. Revisemos el método Header para comprender cómo funciona.

1
public function Header() 
2
{
3
    $image_file = '/web/logo.png';
4
    $this->Image($image_file, 10, 3, 25, '', 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false);
5
    $this->SetFont('helvetica', 'B', 20);
6
    $this->Cell(0, 15, '', 0, false, 'C', 0, '', 0, false, 'M', 'M');
7
    $this->Ln();
8
    $this->Cell(0, 15, 'Katie A Falk', 0, false, 'R', 0, '', 0, false, 'M', 'M');
9
}

En primer lugar, hemos usado el método Image para dibujar el logotipo de una compañía del lado izquierdo. Es importante observar que necesitas enviar la ruta absoluta de la imagen del logotipo al método Image. A continuación, hemos usado el método SetFont para establecer la familia de fuentes y el tamaño de fuente del texto que se agregará en el encabezado. Finalmente, hemos usado el método Cell para imprimir el nombre del propietario del lado derecho.

Notarás que hay muchos argumentos que puedes enviar a estos métodos, y te animo a que los explores a detalle, ya que no es posible discutir todos y cada uno de los argumentos en este artículo.

Con la configuración anterior, el encabezado se vería de esta manera:

HeaderHeaderHeader

El método Footer

En el pie de página queremos mostrar un poco de texto estático, por lo que el método Footer es bastante sencillo, como se muestra en el siguiente fragmento de código.

1
public function Footer() 
2
{
3
    $this->SetY(-15);
4
    $this->SetFont('helvetica', 'I', 15);
5
    $this->Cell(0, 10, 'Thank you for your business!', 0, false, 'C', 0, '', 0, false, 'T', 'M');
6
}

La sección del pie de página se vería de esta manera:

FooterFooterFooter

Finalmente tenemos el método printTable, y volveremos a esto más adelante. El método printTable no está relacionado con la clase TCPDF. En lugar de eso, se trata de nuestro método de utilidad personalizado, que usaremos para dibujar la tabla con el fin de mostrar la información de los artículos.

Así que esa es la clase CustomPdfGenerator. En la siguiente sección veremos cómo usarla junto con un puñado de otros métodos ¡para generar una factura completa en PDF!

El archivo example.php

En la sección anterior hemos creado la clase contenedora CustomPdfGenerator, que podemos usar para generar archivos PDF con encabezados y pies de página personalizados. En esta sección demostraremos cómo puedes usarla.

Sigue adelante y crea el archivo example.php con el siguiente contenido.

1
<?php
2
require "./vendor/autoload.php";
3
require "./customPdfGenerator.php";
4
5
$pdf = new CustomPdfGenerator(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
6
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
7
$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
8
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
9
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
10
$pdf->setFontSubsetting(true);
11
$pdf->SetFont('dejavusans', '', 12, '', true);
12
13
// start a new page

14
$pdf->AddPage();
15
16
// date and invoice no

17
$pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0);
18
$pdf->writeHTML("<b>DATE:</b> 01/01/2021");
19
$pdf->writeHTML("<b>INVOICE#</b>12");
20
$pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0);
21
22
// address

23
$pdf->writeHTML("84 Norton Street,");
24
$pdf->writeHTML("NORMANHURST,");
25
$pdf->writeHTML("New South Wales, 2076");
26
$pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0);
27
28
// bill to

29
$pdf->writeHTML("<b>BILL TO:</b>", true, false, false, false, 'R');
30
$pdf->writeHTML("22 South Molle Boulevard,", true, false, false, false, 'R');
31
$pdf->writeHTML("KOOROOMOOL,", true, false, false, false, 'R');
32
$pdf->writeHTML("Queensland, 4854", true, false, false, false, 'R');
33
$pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0);
34
35
// invoice table starts here

36
$header = array('DESCRIPTION', 'UNITS', 'RATE $', 'AMOUNT');
37
$data = array(
38
   array('Item #1','1','100','100'),
39
   array('Item #2','2','200','400')
40
);
41
$pdf->printTable($header, $data);
42
$pdf->Ln();
43
44
// comments

45
$pdf->SetFont('', '', 12);
46
$pdf->writeHTML("<b>OTHER COMMENTS:</b>");
47
$pdf->writeHTML("Method of payment: <i>PAYPAL</i>");
48
$pdf->writeHTML("PayPal ID: <i>katie@paypal.com");
49
$pdf->Write(0, "\n\n\n", '', 0, 'C', true, 0, false, false, 0);
50
$pdf->writeHTML("If you have any questions about this invoice, please contact:", true, false, false, false, 'C');
51
$pdf->writeHTML("Katie A Falk, (07) 4050 2235, katie@sks.com", true, false, false, false, 'C');
52
53
// save pdf file

54
$pdf->Output(__DIR__ . '/invoice#12.pdf', 'F');

Revisemos los fragmentos de código importantes del archivo anterior.

En primer lugar, hemos incluido el archivo autoload.php para asegurarnos de que la clase TCPDF se cargue automáticamente. A continuación hemos incluido el archivo customPdfGenerator.php para cargar nuestra clase personalizada.

Luego hemos creado una instancia de la clase CustomPdfGenerator junto con las configuraciones predeterminadas. También hemos llamado a un par de métodos para realizar la configuración predeterminada antes de comenzar a escribir en el archivo PDF.

1
$pdf = new CustomPdfGenerator(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
2
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
3
$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
4
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
5
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
6
$pdf->setFontSubsetting(true);
7
$pdf->SetFont('dejavusans', '', 12, '', true);

Las constantes que hemos usado en el fragmento de código anterior ya están definidas en el archivo tcpdf_autoconfig.php. Para sobrescribir una de estas constantes, solamente necesitas definirla en tu script y la biblioteca TCPDF usará tus valores. Por ejemplo, el valor predeterminado de la constante PDF_PAGE_ORIENTATION es P (retrato, o portrait en inglés) y, si quieres cambiarlo a L (paisaje, o landscape en inglés), solamente necesitas incluir define ('PDF_PAGE_ORIENTATION', 'L'); en tu script.

A continuación tenemos un fragmento de código importante que llama al método AddPage, que de hecho agrega una página nueva al documento PDF.

1
// start a new page

2
$pdf->AddPage();

Así que ahora hemos agregado una página y podríamos comenzar a escribir en ella.

A continuación hemos usado los métodos Write y writeHTML para imprimir la fecha y el número de factura del lado izquierdo.

1
// date and invoice no

2
$pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0);
3
$pdf->writeHTML("<b>DATE:</b> 01/01/2021");
4
$pdf->writeHTML("<b>INVOICE#</b>12");
5
$pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0);

El método Write imprime texto a partir de la posición actual, y puedes usarlo para imprimir texto sin formato. Por otro lado, el método writeHTML te permite conservar el formato HTML en el texto. Si bien el método writeHTML proporciona un soporte limitado para el formato HTML, este cubre todas las etiquetas HTML que se usan con frecuencia en el desarrollo diario.

De manera similar, imprimimos la dirección y la dirección de facturación con la ayuda del método writeHTML.

1
// address

2
$pdf->writeHTML("84 Norton Street,");
3
$pdf->writeHTML("NORMANHURST,");
4
$pdf->writeHTML("New South Wales, 2076");
5
$pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0);
6
7
// bill to

8
$pdf->writeHTML("<b>BILL TO:</b>", true, false, false, false, 'R');
9
$pdf->writeHTML("22 South Molle Boulevard,", true, false, false, false, 'R');
10
$pdf->writeHTML("KOOROOMOOL,", true, false, false, false, 'R');
11
$pdf->writeHTML("Queensland, 4854", true, false, false, false, 'R');
12
$pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0);

De forma predeterminada, el método writeHTML imprime texto del lado izquierdo. Si quieres imprimir texto alineado a la derecha, puedes enviar R como último argumento del método writeHTML, como se muestra en el fragmento de código anterior. En nuestro caso queremos mostrar la dirección de facturación alineada a la derecha.

Veamos rápidamente lo que hemos creado hasta ahora.

AddressAddressAddress

A continuación tenemos un fragmento de código que hace el trabajo pesado de imprimir la tabla con la información de los artículos.

1
// invoice table starts here

2
$header = array('DESCRIPTION', 'UNITS', 'RATE $', 'AMOUNT');
3
$data = array(
4
   array('Item #1','1','100','100'),
5
   array('Item #2','2','200','400')
6
);
7
$pdf->printTable($header, $data);
8
$pdf->Ln();

¿Recuerdas el método printTable que definimos en la clase customPdfGenerator.php? Ahora es momento de explorarlo a detalle. Traigamos el código del método printTable.

1
public function printTable($header, $data)
2
{
3
    $this->SetFillColor(0, 0, 0);
4
    $this->SetTextColor(255);
5
    $this->SetDrawColor(128, 0, 0);
6
    $this->SetLineWidth(0.3);
7
    $this->SetFont('', 'B', 12);
8
9
    $w = array(110, 17, 25, 30);
10
    $num_headers = count($header);
11
    for($i = 0; $i < $num_headers; ++$i) {
12
        $this->Cell($w[$i], 7, $header[$i], 1, 0, 'C', 1);
13
    }
14
    $this->Ln();
15
16
    // Color and font restoration

17
    $this->SetFillColor(224, 235, 255);
18
    $this->SetTextColor(0);
19
    $this->SetFont('');
20
21
    // table data

22
    $fill = 0;
23
    $total = 0;
24
25
    foreach($data as $row) {
26
        $this->Cell($w[0], 6, $row[0], 'LR', 0, 'L', $fill);
27
        $this->Cell($w[1], 6, $row[1], 'LR', 0, 'R', $fill);
28
        $this->Cell($w[2], 6, number_format($row[2]), 'LR', 0, 'R', $fill);
29
        $this->Cell($w[3], 6, number_format($row[3]), 'LR', 0, 'R', $fill);
30
        $this->Ln();
31
        $fill=!$fill;
32
        $total+=$row[3];
33
    }
34
35
    $this->Cell($w[0], 6, '', 'LR', 0, 'L', $fill);
36
    $this->Cell($w[1], 6, '', 'LR', 0, 'R', $fill);
37
    $this->Cell($w[2], 6, '', 'LR', 0, 'L', $fill);
38
    $this->Cell($w[3], 6, '', 'LR', 0, 'R', $fill);
39
    $this->Ln();
40
41
    $this->Cell($w[0], 6, '', 'LR', 0, 'L', $fill);
42
    $this->Cell($w[1], 6, '', 'LR', 0, 'R', $fill);
43
    $this->Cell($w[2], 6, 'TOTAL:', 'LR', 0, 'L', $fill);
44
    $this->Cell($w[3], 6, $total, 'LR', 0, 'R', $fill);
45
    $this->Ln();
46
47
    $this->Cell(array_sum($w), 0, '', 'T');
48
}

Primero llamamos a un par de métodos para establecer el tamaño de la fuente, el color de relleno, el ancho de línea y el color de texto antes de comenzar a imprimir la fila del encabezado de la tabla de la factura. A continuación recorremos el arreglo $header e imprimimos los títulos del encabezado de la tabla con la ayuda del método Cell.

El método Cell te permite imprimir una celda (un área rectangular) con bordes opcionales, un color de fondo y una cadena de caracteres. También puedes especificar la alineación del texto que se imprime en la celda. Y, por lo tanto, el método Cell es un candidato perfecto para construir una tabla.

Después de imprimir los títulos del encabezado de la tabla, recorremos el arreglo $data y lo imprimimos para terminar toda la tabla. Finalmente, hemos llamado al método Cell un par de veces para imprimir el monto total.

Una vista previa rápida de la tabla debería verse así:

Item Information TableItem Information TableItem Information Table

Ahora regresemos al archivo example.php para examinar las últimas líneas de código.

Al final de la factura vamos a imprimir algunos comentarios e información de contacto, como se muestra en el siguiente fragmento de código.

1
// comments

2
$pdf->SetFont('', '', 12);
3
$pdf->writeHTML("<b>OTHER COMMENTS:</b>");
4
$pdf->writeHTML("Method of payment: <i>PAYPAL</i>");
5
$pdf->writeHTML("PayPal ID: <i>katie@paypal.com");
6
$pdf->Write(0, "\n\n\n", '', 0, 'C', true, 0, false, false, 0);
7
$pdf->writeHTML("If you have any questions about this invoice, please contact:", true, false, false, false, 'C');
8
$pdf->writeHTML("Katie A Falk, (07) 4050 2235, katie@sks.com", true, false, false, false, 'C');

Finalmente, hemos usado el método Output para guardar el archivo PDF en el disco. Si no quieres guardar el archivo PDF en el disco, y en cambio solamente deseas enviarlo al navegador, necesitarás usar I en el segundo argumento del método Output.

Sigue adelante y ejecuta el archivo example.php, y este debería generar el archivo PDF, como se muestra en la siguiente captura de pantalla.

Full PreviewFull PreviewFull Preview

Conclusión

Así es como puedes usar la biblioteca TCPDF para crear documentos PDF en PHP. Creamos un ejemplo real para demostrar algunas de las diferentes APIs proporcionadas por la biblioteca TCPDF.

La documentación oficial de TCPDF proporciona una gran cantidad de plantillas listas para ser usadas que puedes explorar para comprender las APIs integradas, ¡y te animo a que la explores!

Si quieres obtener más información sobre cómo incluir archivos PDF en tu sitio, consulta los enlaces a continuación: