In this article, we’re going to discuss how you can generate PDF files in PHP. We'll use the TCPDF library to create PDF documents programatically.
If you’re working on a website which allows users to download or print documents like order receipts, bills, or invoices you have a couple options. Either you could display the document inline in the browser or you provide a download. When it comes to downloading documents, PDF is one of the best formats and is excellent at preserving text formatting.
So if you want to learn how to generate PDF files on your PHP website, you’re at the right place!
How to Install the TCPDF Library
In this section, we’ll see how to install the TCPDF library.
There are different ways to install the TCPDF library on your server. The TCPDF library is available at Packagist and GitHub, so you could use either Composer or clone it from GitHub. In our case, we’re going to install it with Composer.
Go ahead and run the following command to install the TCPDF library with Composer.
$composer require tecnickcom/tcpdf Using version ^6.3 for tecnickcom/tcpdf ./composer.json has been created Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Installing tecnickcom/tcpdf (6.3.5): Downloading (100%) Writing lock file Generating autoload files
Once it’s installed successfully, you need to include the autoload.php file in your PHP script as shown in the following snippet.
<?php require "./vendor/autoload.php"; ... ?>
And with that, you’re ready to use all the utility methods provided by the TCPDF library.
How to Use the TCPDF Library
In this section, we’ll build a real-world example, which demonstrates how to generate a PDF invoice. The TCPDF library provides a lot of ready-made templates that you could use as a reference to generate PDF documents. Although in our case, we’re going to generate an invoice from scratch.
As I’ve already mentioned in the previous section, the TCPDF library provides a lot of ready-made templates that allows you to generate generic PDF files with header and footer. And that’s really useful if you’re happy with the default formatting and settings. But, if you want to customize the header and footer along with the content, you would have to extend the TCPDF
class and override the corresponding methods.
In our example, we’ll create two files: customPdfGenerator.php and example.php. In the customPdfGenerator.php file, we’ll create the CustomPdfGenerator
class, which would extend the core TCPDF
class and override a couple of methods. In the example.php file, we’ll see how to use the CustomPdfGenerator
class.
The CustomPdfGenerator
Class
Go ahead and create the customPdfGenerator.php with the following contents.
<?php class CustomPdfGenerator extends TCPDF { public function Header() { $image_file = '/web/logo.png'; $this->Image($image_file, 10, 3, 25, '', 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false); $this->SetFont('helvetica', 'B', 20); $this->Cell(0, 15, '', 0, false, 'C', 0, '', 0, false, 'M', 'M'); $this->Ln(); $this->Cell(0, 15, 'Katie A Falk', 0, false, 'R', 0, '', 0, false, 'M', 'M'); } public function Footer() { $this->SetY(-15); $this->SetFont('helvetica', 'I', 15); $this->Cell(0, 10, 'Thank you for your business!', 0, false, 'C', 0, '', 0, false, 'T', 'M'); } public function printTable($header, $data) { $this->SetFillColor(0, 0, 0); $this->SetTextColor(255); $this->SetDrawColor(128, 0, 0); $this->SetLineWidth(0.3); $this->SetFont('', 'B', 12); $w = array(110, 17, 25, 30); $num_headers = count($header); for($i = 0; $i < $num_headers; ++$i) { $this->Cell($w[$i], 7, $header[$i], 1, 0, 'C', 1); } $this->Ln(); // Color and font restoration $this->SetFillColor(224, 235, 255); $this->SetTextColor(0); $this->SetFont(''); // table data $fill = 0; $total = 0; foreach($data as $row) { $this->Cell($w[0], 6, $row[0], 'LR', 0, 'L', $fill); $this->Cell($w[1], 6, $row[1], 'LR', 0, 'R', $fill); $this->Cell($w[2], 6, number_format($row[2]), 'LR', 0, 'R', $fill); $this->Cell($w[3], 6, number_format($row[3]), 'LR', 0, 'R', $fill); $this->Ln(); $fill=!$fill; $total+=$row[3]; } $this->Cell($w[0], 6, '', 'LR', 0, 'L', $fill); $this->Cell($w[1], 6, '', 'LR', 0, 'R', $fill); $this->Cell($w[2], 6, '', 'LR', 0, 'L', $fill); $this->Cell($w[3], 6, '', 'LR', 0, 'R', $fill); $this->Ln(); $this->Cell($w[0], 6, '', 'LR', 0, 'L', $fill); $this->Cell($w[1], 6, '', 'LR', 0, 'R', $fill); $this->Cell($w[2], 6, 'TOTAL:', 'LR', 0, 'L', $fill); $this->Cell($w[3], 6, $total, 'LR', 0, 'R', $fill); $this->Ln(); $this->Cell(array_sum($w), 0, '', 'T'); } }
The important thing to note is that the CustomPdfGenerator
class extends the TCPDF
class, so we can use all the utility methods provided by the TCPDF
class to format and generate PDF documents.
The sole purpose of creating our own class instead of directly using the TCPDF
class is that we don’t want to use built-in header and footer components. And thus, we’ve overridden the header
and footer
methods in our class.
The Header
Method
In the header, we want to display a company logo along with the owner name. Let's go through the header method to understand how it works.
public function Header() { $image_file = '/web/logo.png'; $this->Image($image_file, 10, 3, 25, '', 'PNG', '', 'T', false, 300, '', false, false, 0, false, false, false); $this->SetFont('helvetica', 'B', 20); $this->Cell(0, 15, '', 0, false, 'C', 0, '', 0, false, 'M', 'M'); $this->Ln(); $this->Cell(0, 15, 'Katie A Falk', 0, false, 'R', 0, '', 0, false, 'M', 'M'); }
Firstly, we've used the Image method to draw a company logo on the left side. It’s important that you need to pass an absolute path of the logo image to the Image
method. Next, we’ve used the SetFont method to set font-family and font-size of the text, which will be added in the header. Finally, we’ve used the Cell
method to print the owner name on the right hand side.
You'll notice that there are a lot of arguments that you could pass in these methods, and I would encourage you to explore it in detail since it’s not possible to discuss each and every argument in this article.
With the above setup, the header would look like this:
The Footer Method
In the footer, we want to display a static text, so the Footer
method is pretty straightforward as shown the following snippet.
public function Footer() { $this->SetY(-15); $this->SetFont('helvetica', 'I', 15); $this->Cell(0, 10, 'Thank you for your business!', 0, false, 'C', 0, '', 0, false, 'T', 'M'); }
The footer section would look like this:
Finally, there’s the printTable
method, and we’ll get back to this later. The printTable
method is not related to the TCPDF
class. Instead, it’s our custom utility method, which we’ll use to draw the table to display the item information.
So that’s the CustomPdfGenerator
class. In the next section, we’ll see how to use it along with the other handful of methods to generate a complete PDF invoice!
The example.php File
In the previous section, we’ve created the CustomPdfGenerator
wrapper class, which we can use to generate PDF files with the custom header and footer. In this section, we’ll demonstrate how you can use it.
Go ahead and create the example.php with the following contents.
<?php require "./vendor/autoload.php"; require "./customPdfGenerator.php"; $pdf = new CustomPdfGenerator(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED); $pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT); $pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM); $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); $pdf->setFontSubsetting(true); $pdf->SetFont('dejavusans', '', 12, '', true); // start a new page $pdf->AddPage(); // date and invoice no $pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0); $pdf->writeHTML("<b>DATE:</b> 01/01/2021"); $pdf->writeHTML("<b>INVOICE#</b>12"); $pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0); // address $pdf->writeHTML("84 Norton Street,"); $pdf->writeHTML("NORMANHURST,"); $pdf->writeHTML("New South Wales, 2076"); $pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0); // bill to $pdf->writeHTML("<b>BILL TO:</b>", true, false, false, false, 'R'); $pdf->writeHTML("22 South Molle Boulevard,", true, false, false, false, 'R'); $pdf->writeHTML("KOOROOMOOL,", true, false, false, false, 'R'); $pdf->writeHTML("Queensland, 4854", true, false, false, false, 'R'); $pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0); // invoice table starts here $header = array('DESCRIPTION', 'UNITS', 'RATE $', 'AMOUNT'); $data = array( array('Item #1','1','100','100'), array('Item #2','2','200','400') ); $pdf->printTable($header, $data); $pdf->Ln(); // comments $pdf->SetFont('', '', 12); $pdf->writeHTML("<b>OTHER COMMENTS:</b>"); $pdf->writeHTML("Method of payment: <i>PAYPAL</i>"); $pdf->writeHTML("PayPal ID: <i>katie@paypal.com"); $pdf->Write(0, "\n\n\n", '', 0, 'C', true, 0, false, false, 0); $pdf->writeHTML("If you have any questions about this invoice, please contact:", true, false, false, false, 'C'); $pdf->writeHTML("Katie A Falk, (07) 4050 2235, katie@sks.com", true, false, false, false, 'C'); // save pdf file $pdf->Output(__DIR__ . '/invoice#12.pdf', 'F');
Let’s go through the important snippets in the above file.
Firstly, we’ve included the autoload.php file to make sure that the TCPDF
class is autoloaded. Next, we’ve included the customPdfGenerator.php file to load our custom class.
Next, we’ve instantiated the CustomPdfGenerator
class along with the default settings. We’ve also called a couple of methods to do default setup before we actually start writing into the PDF file.
$pdf = new CustomPdfGenerator(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED); $pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT); $pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM); $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); $pdf->setFontSubsetting(true); $pdf->SetFont('dejavusans', '', 12, '', true);
The constants that we’ve used in the above snippet are already defined in the tcpdf_autoconfig.php file. To override one of these constants, you just need to define it in your script, and the TCPDF library will use your values. For example, the default value of the PDF_PAGE_ORIENTATION
constant is P
(portrait), and if you want to change it to L
(landscape), you just need to include define ('PDF_PAGE_ORIENTATION', 'L');
in your script.
Next, there’s an important snippet which calls the AddPage
method, which actually adds a new page in the PDF document.
// start a new page $pdf->AddPage();
So we’ve added a page now, we could start writing into this page.
Next, we’ve used the Write
and writeHTML
methods to print the date and invoice number on the left side.
// date and invoice no $pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0); $pdf->writeHTML("<b>DATE:</b> 01/01/2021"); $pdf->writeHTML("<b>INVOICE#</b>12"); $pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0);
The Write
method prints text from the current position, and you can use it to print plain text. On the other hand, the writeHTML
method allows you to preserve HTML formatting in the text. Although the writeHTML
method provides limited HTML formatting support, it covers all the HTML tags that are used frequently in day-to-day development.
Similarly, we’ve printed the address and bill-to address with the help of the writeHTML
method.
// address $pdf->writeHTML("84 Norton Street,"); $pdf->writeHTML("NORMANHURST,"); $pdf->writeHTML("New South Wales, 2076"); $pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0); // bill to $pdf->writeHTML("<b>BILL TO:</b>", true, false, false, false, 'R'); $pdf->writeHTML("22 South Molle Boulevard,", true, false, false, false, 'R'); $pdf->writeHTML("KOOROOMOOL,", true, false, false, false, 'R'); $pdf->writeHTML("Queensland, 4854", true, false, false, false, 'R'); $pdf->Write(0, "\n", '', 0, 'C', true, 0, false, false, 0);
By default, the writeHTML
method prints text on the left side. If you want to print right-aligned text, you can pass R
as the last argument of the writeHTML
method as shown in the above snippet. In our case, we want to display the bill-to address aligned right.
Let’s quickly look at what we’ve built so far.
Next, we’ve a snippet which does the heavy lifting of printing the item information table.
// invoice table starts here $header = array('DESCRIPTION', 'UNITS', 'RATE $', 'AMOUNT'); $data = array( array('Item #1','1','100','100'), array('Item #2','2','200','400') ); $pdf->printTable($header, $data); $pdf->Ln();
Remember the printTable
method which we defined in the customPdfGenerator.php class? Now it’s time to explore it in detail. Let’s pull in the code of the printTable
method.
public function printTable($header, $data) { $this->SetFillColor(0, 0, 0); $this->SetTextColor(255); $this->SetDrawColor(128, 0, 0); $this->SetLineWidth(0.3); $this->SetFont('', 'B', 12); $w = array(110, 17, 25, 30); $num_headers = count($header); for($i = 0; $i < $num_headers; ++$i) { $this->Cell($w[$i], 7, $header[$i], 1, 0, 'C', 1); } $this->Ln(); // Color and font restoration $this->SetFillColor(224, 235, 255); $this->SetTextColor(0); $this->SetFont(''); // table data $fill = 0; $total = 0; foreach($data as $row) { $this->Cell($w[0], 6, $row[0], 'LR', 0, 'L', $fill); $this->Cell($w[1], 6, $row[1], 'LR', 0, 'R', $fill); $this->Cell($w[2], 6, number_format($row[2]), 'LR', 0, 'R', $fill); $this->Cell($w[3], 6, number_format($row[3]), 'LR', 0, 'R', $fill); $this->Ln(); $fill=!$fill; $total+=$row[3]; } $this->Cell($w[0], 6, '', 'LR', 0, 'L', $fill); $this->Cell($w[1], 6, '', 'LR', 0, 'R', $fill); $this->Cell($w[2], 6, '', 'LR', 0, 'L', $fill); $this->Cell($w[3], 6, '', 'LR', 0, 'R', $fill); $this->Ln(); $this->Cell($w[0], 6, '', 'LR', 0, 'L', $fill); $this->Cell($w[1], 6, '', 'LR', 0, 'R', $fill); $this->Cell($w[2], 6, 'TOTAL:', 'LR', 0, 'L', $fill); $this->Cell($w[3], 6, $total, 'LR', 0, 'R', $fill); $this->Ln(); $this->Cell(array_sum($w), 0, '', 'T'); }
First, we called a couple of methods to set the font size, fill color, line width and text color before we actually start printing the header row of the invoice table. Next, we loop through the $header
array and print table header titles with the help of the Cell
method.
The Cell
method allows you to print a cell (rectangular area) with optional borders, background color and character string. You could also specify alignment of the text which is printed in the cell. And thus, the Cell
method is a perfect candidate to build a table.
After we print table header titles, we loop through the $data
array and print it to complete the whole table. Finally, we’ve called the Cell
method a couple of times to print the total amount.
A quick preview of the table should look like this:
Now, let’s get back to the example.php file to go through the last few lines of code.
At the end of the invoice, we’ll print a few comments and contact information as shown in the following snippet.
// comments $pdf->SetFont('', '', 12); $pdf->writeHTML("<b>OTHER COMMENTS:</b>"); $pdf->writeHTML("Method of payment: <i>PAYPAL</i>"); $pdf->writeHTML("PayPal ID: <i>katie@paypal.com"); $pdf->Write(0, "\n\n\n", '', 0, 'C', true, 0, false, false, 0); $pdf->writeHTML("If you have any questions about this invoice, please contact:", true, false, false, false, 'C'); $pdf->writeHTML("Katie A Falk, (07) 4050 2235, katie@sks.com", true, false, false, false, 'C');
Finally, we’ve used the Output
method to save the PDF file to the disk. If you don’t want to save the PDF file on the disk, and instead want to just send it to the browser, you would need to use I
in the second argument of the Output
method.
Go ahead and run the example.php
file, and it should generate the PDF file as shown in the following screenshot.
Conclusion
So that’s how you can use the TCPDF library to create PDF documents in PHP. We created a real-world example to demonstrate different APIs provided by the TCPDF library.
The TCPDF official documentation provides a lot of ready-made templates that you could explore to understand the built-in APIs, and I would encourage you to explore it!
If you want to learn more about including PDFs in your site, check out the links below:
No comments:
Post a Comment