This article details the entire process of building PDF files dynamically using PHP. Experiment with open source tools such as free PDF Library (FPDF) or pdflib-lite, and use PHP code to control PDF content formats.
Sometimes you need to control exactly how the page you want to print is rendered. In this case, HTML is no longer the best choice. PDF files give you complete control over how the page is rendered, and how text, graphics, and images are rendered on the page. Unfortunately, the API used to build PDF files is not part of the standard PHP Toolkit. Now you need to provide a little help.
When you search on the web, looking for PDF support for PHP, the first thing you will find is the commercial Pdflib library and its open source version pdflib-lite. These are good libraries, but the commercial version is quite expensive. The compact version Library of the Pdflib Library is only distributed as the original version, and this limitation problem occurs when you try to install a compact version in a managed environment.
Another option is the free PDF Library (FPDF), which is native PHP, without any need for any compilation, is completely free, so you will not see the watermark as you would in an unlicensed version of Pdflib. This free PDF library is exactly the library I'll use in this article.
We will use the score of the women's dry sliding race to demonstrate the process of dynamically building PDF files. These scores are obtained from the Web and converted to XML. Listing 1 shows a sample XML data file.
Listing 1. XML data
<events>
<event name= "Beast of the East" >
<game score1= "team1=" Toronto Rollergirls "team2=" Montreal La racaille score2= "One" > <game score1= "" team1= "Toronto Death Track-Dolls"
Team2= "Montreal Les contrabanditas" score2= ">
". </game></game></event>
<event name= "Dustbowl Invitational" >
...
</event>
<event name= "The Great Yorkshire Showdown" >
...
</event>
</events>
The root element of XML is a events marker. The data is grouped by event, and each event contains more than one match. Within the events tag, is a series of event tokens in which there are multiple game tags. These game tags contain the names of the two teams participating in the game and their scores in the game.
Listing 2 shows the PHP code used to read the XML.
<?php
function GetResults () {
$xml = new DOMDocument ();
$xml->load (' events.xml ');
$events = Array ();
foreach ($xml->getelementsbytagname (' event ') as $event) {
$games = array ();
foreach ($event->getelementsbytagname (' game ') as $game) {
$games []= Array (' team1 ' => $game->getattribute (' team1 '),
' Score1 ' => $game->getattribute (' Score1 '),
' team2 ' => $game->getattribute (' team2 ') ,
' score2 ' => $game->getattribute (' Score2 ');
}
$events []= Array (' name ' => $event->getattribute (' name '),
' games ' => $games);
}
return $events;
>
This script implements a GetResults function to read the XML file into the DOM document. Then use DOM calls to traverse all event and game tags to build an event array. Each element in the series is a hash table that contains the event name and the array of the race item. Structure is essentially a memory version of the XML structure.
To test the role of this script, an HTML export page is built, the GetResults function is used to read the file, and the data is output in a series of HTML tables. Listing 3 shows the PHP code used for the test.
Listing 3. Results HTML Page
<?php
include_once (' getresults.php ');
$results = GetResults ();
foreach ($results as $event) {
?>
The Getresults.php,xml data file is uploaded to the WEB server via code, and you can view the HTML results, which is similar to Figure 1.
Figure 1. Contest results in HTML format
In this result, the winning team was used in bold to see which teams won the game.
Build PDF
After you get the data, focus on building the PDF file. The first step is to download the FPDF library and install it in the same directory as the existing application file set. In fact, as long as it's in the PHP library path, you can install it anywhere you like. Track where you place the font directory because you need to set ' Fpdf_fontpath ', as shown in Listing 4.
Listing 4. PDF Hello World
<?php
define (' Fpdf_fontpath ', '/library/webserver/documents/derby/font/');
Require (' fpdf.php ');
$pdf = new FPDF ();
$pdf->setfont (' Arial ', ', ');
$pdf->addpage ();
$pdf->cell (40,10, "Hello world!");
$pdf->output ();
? >
This script is actually a "Hello world", but it is in PDF format instead of HTML. The first action that this script performs is to use the Define statement to set the location of the FPDF font directory. Then use the Require statement to introduce the FPDF library. This script creates a FPDF object from the library, sets the font, adds a page, and then uses the Cell method to place some text on the page and output the PDF.
Figure 2 shows the results of all normal situations.
Figure 2. Hello World in PDF format
If you do not see a PDF, you may want to run the script at the command line to see if the fpdf.php file is missing or if there are other problems.
Now that the PDF is present, you should merge it with the dry-slip results file and see what can be generated dynamically. Listing 5 shows the first version of the merge operation.
Listing 5. First version of PDF showing results
<?php
define (' Fpdf_fontpath ', '/library/webserver/documents/derby/font/');
Require (' fpdf.php ');
Require (' getresults.php ');
Class PDF extends FPDF
{
function eventtable ($event)
{
$this->cell (40,10, $event [' name '],15);
$this->ln ();
}
$pdf = new PDF ();
$pdf->setfont (' Arial ', ', ');
foreach (GetResults () as $event) {
$pdf->addpage ();
$pdf->eventtable ($event);
}
$pdf->output ();
? >
Instead of extending the FPDF category from the outside, we use our own PDF subclass to extend the FPDF category. Within these subclasses, we created a new method named Eventtable, which builds a result table for the given event. In this case, we start small and output only the event names. The name is at the bottom of the script, wrapped in a foreach loop, which adds a page for each event, and then calls the Eventtable method.
You can see the output of this script in Figure 3.
Figure 3. The first version of a dynamic PDF
Scroll down the page to show that each event is on its own page. The next step here is to start adding the results to the page.
Building a result table
Building a table-free structure is as easy as building HTML when building a PDF file. The way to build a table is to build a number of cells that are different in width, font, fill color, row color, and so on.
Listing 6 shows the add code that sets the title bar of the table.
Listing 6. Add Result table header
<?php
define (' Fpdf_fontpath ', '/library/webserver/documents/derby/font/');
Require (' fpdf.php ');
Require (' getresults.php ');
Class PDF extends FPDF
{
function eventtable ($event)
{
$this->setfont (', ', ' B ', ') ';
$this->cell (40,10, $event [' name '],15);
$this->ln ();
$this->setxy (a);
$this->setfont (', ' B ', ' ten ');
$this->setfillcolor (128,128,128);
$this->settextcolor (255);
$this->setdrawcolor (92,92,92);
$this->setlinewidth (. 3);
$this->cell (70,7, "Team 1", 1,0, ' C ', true);
$this->cell (20,7, "Score 1", 1,0, ' C ', true);
$this->cell (70,7, "Team 2", 1,0, ' C ', true);
$this->cell (20,7, "Score 2", 1,0, ' C ', true);
$this->ln ();
}
$pdf = new PDF ();
$pdf->setfont (' Arial ', ', ');
foreach (GetResults () as $event) {
$pdf->addpage ();
$pdf->eventtable ($event);
}
$pdf->output ();
? >
The add code here is used to set the font, color, and line width. It then renders several cells that contain four header columns. Then call the Ln method, which is equivalent to the ENTER key, to enable a new row.
When you view this script in a browser, you see something like Figure 4.
Figure 4. The page that contains the header row of the table
In Figure 4, the caption is rendered in white text on a gray background. This format helps distinguish it from the data that is rendered below the title. To render the result of the match, add the following code in Listing 7.
Listing 7. Add a complete result table
<?php define (' Fpdf_fontpath ', '/library/webserver/documents/derby/font/');
Require (' fpdf.php ');
Require (' getresults.php ');
Class PDF extends FPDF {function eventtable ($event) {$this->setfont (', ' B ', ' 24 ');
$this->cell (40,10, $event [' name '],15);
$this->ln ();
$this->setfont (', ' B ', ' 10 ');
$this->setfillcolor (128,128,128);
$this->settextcolor (255);
$this->setdrawcolor (92,92,92);
$this->setlinewidth (. 3);
$this->cell (70,7, "Team 1", 1,0, ' C ', true);
$this->cell (20,7, "Score 1", 1,0, ' C ', true);
$this->cell (70,7, "Team 2", 1,0, ' C ', true);
$this->cell (20,7, "Score 2", 1,0, ' C ', true);
$this->ln ();
$this->setfillcolor (224,235,255);
$this->settextcolor (0);
$this->setfont (");
$fill = false; foreach ($event [' games '] as $game) {$this->setfont ((int) $game [' Score1 ']> (int) $game [' Score2 '])? '
BI ': ');
$this->cell (70,6, $game [' team1 '], ' LR ', 0, ' L ', $fill); $this->cell (20,6, $game [' Score1 '], ' LR ', 0, ' R ', $fill); $this->setfont (' Times ', (int) $game [' Score1 ']< (int) $game [' Score2 '])? '
BI ': ');
$this->cell (70,6, $game [' team2 '], ' LR ', 0, ' L ', $fill);
$this->cell (20,6, $game [' Score2 '], ' LR ', 0, ' R ', $fill);
$this->ln (); $fill =!
$fill;
$this->cell (180,0, ', ' T ');
}} $pdf = new PDF ();
$pdf->setfont (' Arial ', ', ', 10);
foreach (GetResults () as $event) {$pdf->addpage ();
$pdf->eventtable ($event); } $pdf->output ();?>
In addition to the header row, there is a foreach loop in the Eventtable method that will iterate over each race. Figure 5 shows the code for this purpose.
Figure 5. PDF containing the result table
$fill variables can be toggled to change the color of each row in the table. The name and score of the winning team are shown in bold, italic font so that they can be clearly displayed. Also note that the font is changed from the Arial font of the title to The Times font used to display the game content.
To complete the sample code, you need to add some graphics.
Decorate with a graphic
Adding images to a PDF is easy. First you need to crawl an image from the Web. I grabbed the logo of a dry-sliding team and stored it as an image in PNG format. Since then, I've been using the new code in Listing 8.
Listing 8. Add logo image
<?php define (' Fpdf_fontpath ', '/library/webserver/documents/derby/font/');
Require (' fpdf.php ');
Require (' getresults.php ');
Class PDF extends FPDF {function eventtable ($event) {$this->image (' logo.png ', 5,5,33);
$this->setxy (40, 15);
$this->setfont (', ' B ', ' 24 ');
$this->cell (40,10, $event [' name '],15);
$this->ln ();
$this->setxy (10, 45);
$this->setfont (', ' B ', ' 10 ');
$this->setfillcolor (128,128,128);
$this->settextcolor (255);
$this->setdrawcolor (92,92,92);
$this->setlinewidth (. 3);
$this->cell (70,7, "Team 1", 1,0, ' C ', true);
$this->cell (20,7, "Score 1", 1,0, ' C ', true);
$this->cell (70,7, "Team 2", 1,0, ' C ', true);
$this->cell (20,7, "Score 2", 1,0, ' C ', true);
$this->ln ();
$this->setfillcolor (224,235,255);
$this->settextcolor (0);
$this->setfont (");
$fill = false; foreach ($event [' games '] as $game) {$this->setfont ((int) $game [' Score1 ']> (int) $game [' Score2 '])? '
BI ': '); $This->cell (70,6, $game [' team1 '], ' LR ', 0, ' L ', $fill);
$this->cell (20,6, $game [' Score1 '], ' LR ', 0, ' R ', $fill); $this->setfont (' Times ', (int) $game [' Score1 ']< (int) $game [' Score2 '])? '
BI ': ');
$this->cell (70,6, $game [' team2 '], ' LR ', 0, ' L ', $fill);
$this->cell (20,6, $game [' Score2 '], ' LR ', 0, ' R ', $fill);
$this->ln (); $fill =!
$fill;
$this->cell (180,0, ', ' T ');
}} $pdf = new PDF ();
$pdf->setfont (' Arial ', ', ', 10);
foreach (GetResults () as $event) {$pdf->addpage ();
$pdf->eventtable ($event);
} $pdf->output ();?>
The key method in Listing 8 is the image method, which selects a file name for the image, location, and width. All other parameters are optional, so you can specify only the information you want.
Some new calls to SetXY move the text and the table around to the appropriate location to prevent it from overwriting the image.
Figure 6 shows the output of this script.
Figure 6. Completed PDF with logo image
The PDF library also provides other ways to render graphics, add streaming text, add hyperlinks, manage margins and orientations, and you have complete control over your PDF files.
Conclusion
Using the right tools, building PDF files through PHP is very easy. This approach is ideal for printing x tickets or bills, or filling out forms, and any items that require strict control over the layout of the content.