Creating a basic PDF
Let's start by creating a basic PDF file outside of the main application so you can see what's going on.
It's hard to spend much time on the Internet without running into a PDF document at some point. Created by Adobe Systems, the Portable Document Format (PDF) was designed to be just that: portable. PDF files can be read on any system for which the Adobe Acrobat Reader (or a reasonable facsimile) is available, and for the most part, it will look the same wherever you view it.
Interestingly, while these are not files that you typically edit, they are actually text-based, embedded binary data. For example, consider the snippet in Listing 1 of the actual PDF that you'll generate in this tutorial.
Listing 1. A sneak peek at the actual PDF
%PDF-1.4 ... 1 0 obj <<;/Type /Catalog /Version /1.4 /Pages 2 0 R >> endobj 2 0 obj <</Type /Pages /Kids [3 0 R ] /Count 1 >> endobj 3 0 obj <</Type /Page /LastModified (D:20060526190953-04'00') /Resources <</ProcSet [/PDF /Text ] /XObject <</X1 5 0 R >> /Font <</F1 6 0 R >> >> /MediaBox [0 0 612 792 ] /Contents [4 0 R ] /Parent 2 0 R >> endobj 4 0 obj <</Length 134 >> stream q 1 0 0 1 36 684 cm 72 0 0 72 0 0 cm /X1 Do Q /F1 32 Tf 0.2 g 0.9 0 0 RG 3 w BT 138 708 Td (Chomp! To go) Tj ET 18 774 576 -756 re S endstream endobj 5 0 obj ...
As you can see, the file specifies various objects and their attributes. Fortunately, you do not have to get into the actual details of each of these objects because the
Zend_PDF component of the Zend Framework takes care of it for you. Let's see how it works.
Start by creating a document called createPDF.php. You may find it easiest to create this file in the <ZEND_HOME>/library directory, but the actual location is not important as long as it can find the Zend class files. Add the code in Listing 2.
Listing 2. Create the document
<?php require_once 'Zend/Pdf.php'; $pdf = new Zend_Pdf(); $pdf->save("chomp.pdf"); ?>
Here you include the
Zend_PDF class files and use them to create a new PDF object. Once you have the object, you are simply saving it out to an arbitrary file.
You can execute this file by typing php createPDF.php on the command line. You should see a new file in the directory called chomp.pdf, but if you try to open it, you will get an error because it has no content. Let's take care of that next.
Each page in a PDF document is an object unto itself. You can create a page of any size, using x and y values measured in points (1/72 of an inch), or you can use one of the four predetermined sizes, as you can see in Listing 3.
Listing 3. Adding a page
<?php require_once 'Zend/Pdf.php'; $pdf = new Zend_Pdf(); $page = new Zend_Pdf_Page(Zend_Pdf_Page::SIZE_LETTER); $pageHeight = $page->getHeight(); $pageWidth = $page->getWidth(); echo 'Height = '.$pageHeight.'\n'; echo 'Width = '.$pageWidth.'\n'; $pdf->pages = ($page); $pdf->save("chomp.pdf"); ?>
Start by creating a new page as a standard letter-size page. The other choices are
Zend_Pdf_Page::SIZE_A4_LANDSCAPE. Note that you can have different size pages in a single document.
Once you create the page, you can retrieve its height and width, but it still doesn't actually belong to the document. (An alternate means of creating a page, the
$pdf->newPage() method, does belong to the document, and it reportedly has slightly better performance, but it creates a page that cannot be shared between documents.) To attach it to the document, you add it to the pages attribute, an array of page objects you can also manipulate like any other array.
Start by adding an image to the document. As of this writing, the Zend Framework supports only JPEG images, but that is likely to change.
You start by creating an image object, as shown in Listing 4.
Listing 4. Adding an image
<?php require_once 'Zend/Pdf.php'; $pdf = new Zend_Pdf(); $page = new Zend_Pdf_Page(Zend_Pdf_Page::SIZE_LETTER); $chompImage = new Zend_Pdf_Image_JPEG::imageWithPath( dirname(__FILE__) . '/chomp.jpg'); $pageHeight = $page->getHeight(); $pageWidth = $page->getWidth(); $imageHeight = 72; $imageWidth = 72; $topPos = $pageHeight - 36; $leftPos = 36; $bottomPos = $topPos - $imageHeight; $rightPos = $leftPos + $imageWidth; $page->drawImage($chompImage, $leftPos, $bottomPos, $rightPos, $topPos); $pdf->pages = ($page); $pdf->save("chomp.pdf"); ?>
Note: If you do not have the image extension enabled for PHP, you will get an error when you try to execute this file. To solve this problem, open your php.ini file and uncomment the line that says
Creating the actual image object is self-explanatory. You are simply loading the JPEG from a file. But from there, you have to think about positioning, which might not be entirely obvious.
A PDF document uses the same conventions as a PostScript file. That means everything is measured in "points," rather than pixels. There are 72 points to an inch, so if you want the image to be 1 inch high by 1 inch wide, you set both values to 72.
As far as the actual positioning, the origin for the coordinate system is in the bottom left-hand corner of the page. In other words, the point 0,0 corresponds to the lower left-hand corner, with coordinates going up as you get higher on the page and further to the right.
So, to place an object half an inch from the top of the page, you need to set that coordinate to the total height of the page, minus 36 points, or half an inch. Similarly, the bottom of the image will be at that point, minus the height of the image. Also, because you want it in the left-hand corner, you start with the coordinate of 36, then add the width of the image for the second coordinate.
Once you have all of that information, you can use the
drawImage() method to add it to the actual page. The process of adding text is similar.
Before you can add any text to the page, you need to determine what it's going to look like. You can accomplish that through the use of styles, as shown in Listing 5.
Listing 5. Adding text
... $topPos = $pageHeight - 36; $leftPos = 36; $bottomPos = $topPos - $imageHeight; $rightPos = $leftPos + $imageWidth; $page->drawImage($chompImage, $leftPos, $bottomPos, $rightPos, $topPos); $style = new Zend_Pdf_Style(); $style->setLineColor(new Zend_Pdf_Color_RGB(0.9, 0, 0)); $style->setFillColor(new Zend_Pdf_Color_GrayScale(0.2)); $style->setLineWidth(3); $style->setFont( new Zend_Pdf_Font::fontWithName(Zend_PDF_Font::FONT_HELVETICA_BOLD) ,32); $page->setStyle($style); ->drawText('Chomp! To go', $rightPos + 32, $topPos - 48); $pdf->pages = ($page); $pdf->save("chomp.pdf"); ?>
Start by creating a style object and setting its attributes. The line color, here set as an RGB value (with the red, green, and blue values being set on a scale of zero to one), mostly applies to shapes, as you'll see in a moment. The fill color, here set as a very dark gray, also applies to shapes, but more importantly, in this case, sets the color of your text. The line width determines the width of your lines. Then you set the font and the size, in points. Fourteen standard fonts are included in PDF documents and can be referenced as
Zend_PDF_Font values. They include
Zend_Pdf_Font::FONT_TIMES_BOLDITALIC, the same four varieties for Helvetica and Courier, and the Symbol and Zapf Dingbats fonts.
Once you create the style, you can set it for the page. Finally, you are ready to actually add the text to the page, specifying the text itself and its position. In this case, you want the text to be half an inch to the right of the image, and two-thirds of an inch from the top of the page.
The final touch to your sample page is a border around the outside (see Listing 6).
Listing 6. Adding a shape
... $style->setFont(new Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_HELVETICA_BOLD), 32); $page->setStyle($style); ->drawText('Chomp! To go', $rightPos + 32, $topPos - 48); ->drawRectangle(18, $pageHeight - 18, $pageWidth - 18, 18, Zend_Pdf_Page::SHAPEDRAW_STROKE); $pdf->pages = ($page); $pdf->save("chomp.pdf"); ?>
You already set a color and width of the line that makes up the rectangle, so now you're setting the top-left and bottom-right corners to be a quarter of an inch from the edges of the page, and specifying that you want just the line, as opposed to a filled shape. You have three options:
Zend_Pdf_Page::SHAPEDRAW_FILL. The first includes a line and a fill, so if you had used it here, you would've wound up with a dark gray rectangle with a red border.
Let's look at actually implementing this within the application.