How to Create PDF Files With PHP

PDF is the de-facto electronic document standard because of its security and integrity. Making a PDF isn’t limited to high-end desktop software though; they can be created quite easily on the fly from your web application. Add in a sprinkle of free code, and you got one great recipe for PDF-ala-mode! In this tutorial I’ll show you with PHP and FPDF.

Introduction

Okay, so here is what we are going to be doing. We’ll be using PHP and a free PHP library called FPDF to create a simple PDF document consisting of some text and an image. I’ve already included the full FPDF download in the source folder (hint: probably should download that), which consist of the library, full html manual, and some tutorials. For this lession though, I’ve included a cheat sheet (cheetsheet.txt) that contains just the commands we will be using today. So, lets get started!

Why FPDF?

Valid question. PHP does come with a extension called PDF that creates pdf documents. However, a problem can arise when the extension is not enabled and/or cannot be enabled, which is a possibility in some shared hosting environments. That’s where FPDF comes in. FPDF does not require
any extensions for the majority of its operations. The only exception comes when you want to use GIF images (requires the GD extension) and page compression (requires the zlip extension). Of course, it’s free too.

Scavenger Hunt

As with any project, we have to gather a few pieces before we can continue. For this tutorial, we’ll need two: FPDF and an image. I’ve already included both in source folder. To install FPDF, you just need to copy the folder (you really only need fpdf.php and the font directory) to a directory on your web server. Remember: this is a PHP library, so you will need some type of web server with PHP installed to run the code. Then, you just need to copy the image to the directory your code will
exists.

Step 1: Let’s get some class

Let’s create a file called index.php which will contain our code. To start using FPDF, we first have to tell PHP that we need some code in a file called fpdf.php; we just don’t need it though, we must have it or our code won’t work, so let’s use the require statement. This way, if the file isn’t available, the code won’t run.

<?php
// Get required files.
require 'fpdf/fpdf.php';
 
// Set some document variables
$author = "Me McMe";
$x = 50;
$text = <<<EOT
facilisis Praesent ultricies vitae, placerat dapibus, turpis commodo morbi tristique erat et amet egestas. faucibus, lacus Quisque amet, est amet erat. facilisis. Aliquam eget, quam tincidunt ipsum sagittis eros vitae eu Vestibulum cursus dui pharetra. erat metus condimentum felis. pulvinar Vestibulum ac habitant neque rutrum feugiat quam, leo. elit tincidunt id Pellentesque sapien sit condimentum, accumsan vitae, eu egestas eget tortor turpis sit dui. neque wisi. ultricies Nam augue, est. porttitor, et eu fermentum, egestas ac ullamcorper tortor enim ante. netus eros luctus, malesuada amet, magna orci, Aenean in vulputate libero quis, non sit Mauris wisi, volutpat. sed, tempus et eleifend fames Donec sit semper. Aenean mi mi, ornare enim tempor Ut Donec senectus.
EOT;
 
// Create fpdf object
$pdf = new FPDF('P', 'pt', 'Letter');

Next, let’s create some variables for later use. In case you don’t recognize the text variable, it’s a heredoc (Diving into PHP, Day 8). Finally, in order to use the FPDF library, we have to create a FPDF object, which we will call pdf. FPDF follows Object Oriented Design, which means that in order to use FPDF, we need to create an object of it. We also passed a few values to FPDF when we created the object. These values set up some basic formatting (‘P’ – portrait landscaping, ‘pt’ – the page units of measurement are in points, ‘L’ – Letter format; important for printing).

Step 2: Let there be fonts!

Our next step of action is to set up the starting font for the document. FPDF uses font definition files to represent fonts, so in order to use a font, the font definition file must exist in the font directory. Six fonts come included in the font directory – Courier, Helvetica, Arial, Times, Symbol, and ZapfDingbats. If other fonts are required, then you can use the makefile.php file located in the font directory to create the needed font files, but that is beyond today’s tutorial. Note: the font must be declared before adding a page and outputing any data. Failure could result in a corrupt document.

// Set base font to start
$pdf->SetFont('Times', 'B', 24);

The SetFont method takes three parameters. The font name (required), any
formating (B – bold, I – italic, blank – no formating), and the font size. Any
character output to the document will use this font until we change the font
again with SetFont.

Step 3: Got Paper?

Alright, we can start writing some text! Well, almost. First, we need to add a page to the document so we have something to write to, so we use AddPage (it can take some optional formatting parameters, but if left blank it inherits the values from the document). We will then need to position the cursor where we want the text to appear. It may help to think of the cursor as you would see it in a word processor. Where ever that cursor is, that is where text is going. If you want text to appear
in a different position that where the cursor, then you have to reposition the cursor.

// Add a new page to the document
$pdf->addPage();

We reposition the cursor on our document with SetXY, which takes the X
and Y position of the cursor. This is where some difficulty comes in as you
figure out the correct position of elements on your pdf document. Remember too
that these values are in the unit of measuremet we specified when we created
our object. So, we are using points (if using mm, then 50 probably wouldn’t be
enough). If you’ve noticed, I’m also using the variable x we declared earlier.
Since we are creating a simple pdf file, I’ve predefined it so everything will
line up evenly to the left.

// Set the x,y coordinates of the cursor
$pdf->SetXY($x,50);

Step 4: It Speaks!

Finally, we can write! FPDF provides two basic ways to output character data to the document – Write and Cell. We’ll cover Write here.

// Write 'Simple PDF' with a line height of 1 at the current position
$pdf->Write(25,'Simple PDF');

Write takes two parameters – the first being the line hight (once again,
in the unit of measurement specified, so 25 provides 1 point of line hieght for
a 24 point font), and the other being the text to write. If the text to write
goes beyond the left margin (which is 1 cm by defualt), then the text is
automatically wrapped. Also, if it wraps till the end of the page, a page break
is automatically done and the text continued onto the next.

Step 5: Oooh, fancy!

Okay, so we want to write some new text at a new position with a different font, style, but add some formatting. No problem, we just have to add one new command and use Cell instead of Write.

// Reset the font
$pdf->SetFont('Courier','I',10);
// Set the font color
$pdf->SetTextColor(255,0,0);
// Reset the cursor, write again.
$pdf->SetXY($x, 75);
$pdf->Cell(0,11, "By: $author", 'B', 2, 'L', false);

We reset the font with SetFont to a 10 point italic Courier font. We then set the font color with SetTextColor, which takes the RGD color numbering system to specify the color; we want red – 255,0,0. We then reset the cursor with SetXY using the x variable to keep it left aligned and increasing Y to move it down the page. Lastly, we use Cell to output the text. Cell behaves differently than Write does with text that hits the margins – text just keeps going and disappears off the page. So, cell is really only good for text we know will fit inside of the Cell. However, cell does provide some more formatting options than Write does – borders, fill, text alignment, cursor placement after the cell. It also allows us to embed a url in the cell. Be sure to check out the cheat sheet for a full list and description of the parameters; the first three are required: cell width (If set to 0, it extends to the right margin), cell height, and the text to print.

Step 6: A picture is worth many words.

Since we don’t just communicate with words, adding an image to our document is done with the Image statement.

// Place an image on the pdf document
$pdf->Image('graph.jpg', $x, 100, 150, 112.5, 'JPG');

The Image command requires only the image file. If nothing else is given, the image size is automatically figured out as well as the image type, and is placed at the current cursor position. However, I’ve found that if left to itself, the images seamed to be somewhat pixelated and larger than when the image size is manually given. Also, I’ve found that jpg images seam to work better than png images, although both are supported. If you want to use a gif image, then remember to enable the GD extension for your PHP installation. So, here we have told FPDF to get the image graph.jpg and place it at the position of 50, 100 and the image size is 150 points wide by 112.5 points high and it is a jpg image. Since we declared the document measurement to be in points, then I had to convert the image size in pixels (200 by 150) to points.

Step 7: And my last point..

Lets print out our last thing of text, which will demonstrate the wrapping features of the Write statement using our text heredoc variable.

// Reset font, color, and coordinates
$pdf->SetFont('Arial','',12);
$pdf->SetTextColor(0,0,0);
$pdf->SetXY($x, 250);
 
// Write out a long text blurb.
$pdf->write(13, $text);

To summarize, we reset the font, set the color to black, set the cursor to a new position, and then printed the text with a line hieght of 13. Since I passed a blank formatting option in SetFont, the font will print with no formatting. In case you haven’t notice, FPDF remembers font settings. So, if we
declare the font color to be red and print out three lines of text, all three lines will be red; we must manually change the font setting to get different results. This features is useful for the SetFont statement. To change a single attribute of the current font, we can simply pass the new attribute. For
example, to add bold formatting, we could simple use the statement SetFont(‘B’), which would keep the font and size, but add the bolding.

Step 8: Don’t forget to save!

Alright! We’re almost there. Now we just need do something with our document that we’re done with it. To end a pdf document and output it in four different ways, you use the Output statement.

// Close the document and save to the filesystem with the name simple.pdf
$pdf->Output('simple.pdf','F');

Output takes two arguments – the name of the file with the pdf extension, and the output method. To save the pdf to the file system your code resides on, use F. To output to the browser use I, or use D to output to the browser and force a download. S returns the document in string format, useful for use in other functions. We’ll use F.

Conclusion

If you navigate to the directory your index.php document resides, you should see a PDF document called simple.php (I’ve included a finished pdf to compare). Well, to recap we’ve included the necessary file, created an FPDF object, set and formatted fonts, printed text 2 ways, placed and
image, and saved the file to the filesystem. While there has been alot of statements, I hope you’ve seen how easy it is to create pdf documents from a web language like PHP. You are not just limited to simple scripts like this though; you could integrate this with a form to provide custom documents, for example.



31

Comments
  • Very good tutorial, thank’s

  • Steve B says:

    Hey Robert, great article on how to create a PDF with PHP! But my question is why wouldn’t you use DOMPDF to create a PDF with PHP? DOMPDF makes it really easy to create a PDF with PHP because all you need to do is create the view and apply a style sheet to the page and DOMPDF uses the stylesheet to create the PDF.

    The one downside as of right now is there is a security vulnerability with DOMPDF. But hopefully they will update the application soon so this won’t be an issue. I’m using DOMPDF on my companies intranet applications, and I *hope* there won’t be any issues.

    http://www.digitaljunkies.ca/dompdf/

  • yomi says:

    great post! exactly what I needed!

  • GrassyHill says:

    Someday someone will come up with a working way to just hand a styled (X)HTML page off to PDF. Meanwhile, this is a good primer for a workable method. Thanks.

  • machine says:

    take a look at library mpdf – it generates pdf directly from html..

  • ec says:

    There are lots of “&gt” and “&lt” in this article. I would assume those are mistakes – but that can be misleading to those who want to copy the code from the article. (And to those who are attempting to read it, too – especially beignners at PHP.)

  • Brenelz says:

    Nice tut! I can see some uses for this in my projects

  • Willabee says:

    The only problem I had was placing the FPDF folder at the root of my website and not in a folder that was in my PHP include path.

    Other than that, thanks for a very clear tutorial which proves the concept. I will now have to dig into the documentation for some more extensive layouts and styles in order to produce good PDF documentation.

  • Crysfel says:

    very good, i usually use Java to do this job but im going to play with this.

    thx

  • ron says:

    Hi
    the only problem is that it does not support languages like Hebrew.

    any knowledge about other options?

  • Jeff Adams says:

    Ah wow! I needed something like this, but like 3 years ago lol. I wanted people to like buy the images, pick their text and then output a PDF poster.

    Now I know it can be done, I will be spending my spare time working on this and I know I sound like a geek but I don’t care lol.

  • Great, i’ve been trying to do this forever and I think this will really help! How can I add the values of a web form to a pdf?

  • John says:

    Better fix the HTML encoding issue… other than that, nice tut!

  • Heiner says:

    Thanks for bringing this back on my mind – i allways wanted to try that out and just now a did. Just a suggestion:

    other than resetting the cursor all the time, use

    // Set margins (left, top, right)
    $pdf->SetMargins(25,25,10);
    //(btw. for testing these are mm values)

    Afterwards you can just insert linebreaks after each write statement:

    //LineBreak
    $pdf->Ln();

    and you won’t have to worry about the absolute position of the cursor – it will all float nicely down the page.

  • saurabh shah says:

    wow ! nice tutorial…

  • M.A.Yoosuf says:

    wow its pretty cool stuff i like this, thank god jeff is not making this stuff for PRO

  • SX says:

    Missing cheatsheet.txt
    Not in the download.

  • WilliamZH says:

    Thanks for your sharing
    I’m just at the begining of PHP

  • Robert DeBoer says:

    @SteveB – I have not seen DOMPDF; it looks great and I will defenitly check it out. However, one down side I see is that it seems to be designed for complete pages (html skeleton). That is good for offering a PDF version of a page, but if I just need to print out a few specific things not necessarily on the page itself, then I might need to use something like FPDF. ( I haven’t explored DOMPDF in detail, so I might be mistaken).

    @Everyone – sorry about the escape characters. > is > and $lt; is < (I substituted them by accident to make sure not to break the javascript code viewer, but it didn’t substitute them back).

    @Montana Flynn – to add the values of a form to the PDF, just create the PDF document in the PHP file that handles your form data, and simple use the $_POST array as a variable, just like I used the variables of text and author in the example. (I would do some text sanitation before outputting the text from the form though, weird characters might not print correctly).

    @Heiner – margins are a good way of maintaining my left margins – just remember that some writing methods do not set the cursor back at the left margin, so you will still need to reset the cursor

  • Robert DeBoer says:

    I should also mention that there methods to convert XML to PDF using transformations. Ultimately, your method of creation depends on your project requirements.

  • MegaFill says:

    Nice tutorial

  • Alper BALCI says:

    Yes, good tutorial, thank’s.
    Here is some working live example links.
    http://www.evo-turkish.com/Zor-Makaleler_-_file_-_printpdf_-_artid_-_2.html

    Real problem is:
    How can i use UTF-8 code page?
    How can i use different language code page than english?

  • twowheeler says:

    I have also encountered another library called tcpdf, which is a fork of fpdf. The file is considerably larger, but has some interesting features added.
    The self-description of tcpdf is as follows:

    // Description : This is a PHP class for generating PDF documents without

    // requiring external extensions.

    //

    // NOTE:

    // This class was originally derived in 2002 from the Public

    // Domain FPDF class by Olivier Plathey (http://www.fpdf.org),

    // but now is almost entirely rewritten.

    //

    // Main features:

    // * no external libraries are required for the basic functions;

    // * supports all ISO page formats;

    // * supports UTF-8 Unicode and Right-To-Left languages;

    // * supports document encryption;

    // * includes methods to publish some XHTML code;

    // * includes graphic (geometric) and transformation methods;

    // * includes bookmarks;

    // * includes Javascript and forms support;

    // * includes a method to print various barcode formats;

    // * supports TrueTypeUnicode, TrueType, Type1 and CID-0 fonts;

    // * supports custom page formats, margins and units of measure;

    // * includes methods for page header and footer management;

    // * supports automatic page break;

    // * supports automatic page numbering and page groups;

    // * supports automatic line break and text justification;

    // * supports JPEG and PNG images whitout GD library and all images supported by GD: GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM;

    // * supports stroke and clipping mode for text;

    // * supports clipping masks;

    // * supports Grayscale, RGB, CMYK, Spot colors and transparency;

    // * supports links and annotations;

    // * supports page compression (requires zlib extension);

    // * supports PDF user’s rights.

  • Poonam says:

    Thanx for this Tutorial..it really worked

  • Mizsia says:

    good tut…but can we have UTF-8 characters in this method? how?

  • Fritz says:

    I need some REAL help, i have been Googl’ing now 4 days non stop, but cannot find any sample for my problem.

    I have 2 tables, tabel 1 is my account holders, and has 3 fields, accholder_id, acc_holder_card_no & acc_holder_name. Tbl2 is all acounts tabel and has 5 fields: acc_no, acc_holder_id, acc_holder_card_no, card_name, acc_name.

    Tbl1 Field = Tbl 2 Field
    acc_holder_id = acc_holder_id
    acc_holder_card_no = acc_holder_card_no
    acc_holder_name = card_name

    NOW, currently i do a lookup on both tables, where the acc_holder_id is joined on both tables, then return acc_holder_name from tbl1 and all acc_no from tbl2 which equals the acc_holder_id.

    Now i need to print this info on a pvc card, credit card size.

    The first field, acc_holder_name top right corner of the card, and the acc_no on the left bottom corner. Because some account holders have more than one account, i need the acc_no to list not more than 4 rows, if more than 4 rows, create a second column next to first column and list next 4 rows, and so on.

    I managed to get it to show in php, but that’s it, i even managed to set the pdf size and list the one of the acc_no but when there are more than one i only get the last result from the lookup.

    I have xampp v1.7 with:mysql 5.1.30, php 5.2.8 + PEAR running on windows.

  • Silviu Chirita says:

    Thank you very much for this post, it really helped me pass a long hour research for such a solution.

  • medyum says:

    There are lots of “&gt” and “&lt” in this article. I would assume those are mistakes – but that can be misleading to those who want to copy the code from the article. (And to those who are attempting to read it, too – especially beignners at PHP.)