Recipe 6.11. Generating Downloadable Files Dynamically


Problem

You want to offer a frequently updated or customized document, such as a coupon or application, that visitors to your site can download and print out.

Solution

Set up a PHP script that dynamically generates a file using code libraries that allow you to build and output custom PDFs, PNGs, JPEGs, and other types of files using built-in functions.

The functions associated with PDFlib library, created by Thomas Merz, have been available to PHP since Version 3. Image-generating functions that are part of Thomas Boutell's GD Graphics Library have been a common PHP installation option since Version 4.3.

The PDFlib and GD functions must be enabled with PHP when it is installed on your web server. If you're unsure about the availability of either function library, check with your system administrator or web hosting provider.


If you want to create PDFs on the fly, but don't have access to PDFlib, you can use a third-party PHP class that replicates most of the functionality of PDFlib; refer to the "See Also" section in this Recipe for more information.

Discussion

For this Recipe, I'll use the example of creating a coupon (see Figure 6-9) with an expiration date one week from the date the visitor downloads it. Coupons are a great way for a brick and mortar establishment to get regular visitors to its web site. Setting up a script that keeps the coupon up to date, and offers some flexibility about the terms of the offer, will relieve you or your client from the tedium of generating and uploading a new coupon every week.

Regardless of the graphics library you use, the steps for creating a dynamically generated coupon are the same:

  1. Define any variables to be plugged into the contents of the file.

  2. Create the canvas.

  3. Add any borders, graphics, or text to be displayed in the file.

  4. Output the file to the browser.

For our coupon, I will define two variables$discount for the percentage discount and $duration for the length of time in weeks that it will be validand then use PHP's built-in time() and date( ) functions to create a third variable$expiryfor the human-readable expiration date:

Figure 6-9. A downloadable coupon can be generated on the fly with a PHP script


 $discount = "50"; $duration = 1; //weeks $expiry = time(); $expiry = $expiry+($duration*604800); $expiry = date("F j, Y",$expiry); 

The PHP function time() creates a timestamp in seconds. By adding 604800 to the timestamp value (the number of seconds in one week), the scripts will then format the expiration date variable ($expiry) in "Month Day, Year" format for one week from the current date.

You could also leave these variables out of the script itself and instead pass them from a form on a web page.


Using PDFlib

For the PDFlib script, I also have defined the variables $file for the megaphone logo (which will be uploaded to the same directory as the script) and $fontdir for the path to the font I want to use in the coupon:

 <? $discount = "50"; $duration = 1; //weeks $expiry = time(); $expiry = $expiry+($duration*604800); $expiry = date("F j, Y",$expiry); $file = 'logo.jpg'; $fontdir = $DOCUMENT_ROOT."/path/to/your/fonts"; 

The canvas will be a letter-size sheet of paper, measured in pixels; this coupon is 612 wide and 792 tall:

 $pdf = pdf_new(); pdf_open_file($pdf); pdf_set_info($pdf, "Author","Web Site Cookbook"); pdf_begin_page($pdf, 612, 792); 

The coordinate system for PDFlib begins at the lower left corner of the document, which takes some getting used to. I find it useful to sketch my PDFs on a blank sheet of paper, and then note the X and Y positions of elements with a ruler. One inch equals 72 pixels.


With these next three lines, I specify a border width, as well as the origin and dimensions for its placement on the document. Then the pdf_stroke ( ) function draws the coupon, as shown in Figure 6-10:

 pdf_setlinewidth($pdf, 2); pdf_rect($pdf, 72, 504, 346, 216); pdf_stroke($pdf); 

The first pair of values passed to the pdf_rect function (72, 504) define the rectangle's starting point; the second pair of values (346, 216) are the X and Y values for its width and height.

Next, the script will take the filename (stored in $file) and create an object to be placed in the document with the pdf_place_image( ) function. The three numeric parameters in the function are the X-and Y-axis start points, and the amount to scale the image (1 equals 100 percent):

 $graphic = pdf_open_image_file($pdf, "jpeg", $file); pdf_place_image($pdf, $graphic, 90, 540, 1); 

These next two lines load the font. I copied the TrueType file for Verdana (VERDANA.TTF) from my Windows PC, uploaded it to the same directory as the script, and point to it using the $fontdir variable defined at the top of the script:

 pdf_set_parameter($pdf, "FontOutline", "Verdana=$fontdir/VERDANA.TTF"); $font = pdf_findfont($pdf, "Verdana", "host", 1); 

Using the pdf_setfont( ) and pdf_show_xy() functions together, the script specifies font sizes (20, 30, and 9) for the three text blocks to be displayed on the coupon. The numeric parameters in pdf_show_xy() specify the X- and Y-axis start points for the text:

 pdf_setfont($pdf, $font, 20); pdf_show_xy($pdf, "C O U P O N", 252, 648); pdf_setfont($pdf, $font, 30); pdf_show_xy($pdf, $discount."% off", 252, 612); pdf_setfont($pdf, $font, 9); pdf_show_xy($pdf, "Not valid with other offers. Void where prohibited.", 90, 522); pdf_show_xy($pdf, "Expires: ".$expiry, 90, 511); 

Figure 6-10. On a letter-size canvas, the pdf_rect function draws a rectangle starting at the lower-left corner


Finally, the script closes the documents and sends the data to the browser. Depending on the user's browser settings, the file might be displayed directly in the browser window or downloaded to the user's hard drive:

 pdf_end_page($pdf); pdf_close($pdf); $data = pdf_get_buffer($pdf); header('Content-type: application/pdf'); header('Content-disposition: inline; filename=coupon.pdf'); header('Content-length: ' . strlen($data)); echo $data; ?> 

Using GD Graphics Library

With the set of functions available in the GD Graphics Library, you can create PNGs, JPEGs, GIFs, and other image files on the fly.

For our coupon example, I'll use this script to create a PNG that will display directly in the user's browser:

 <? $discount = "50"; $duration = 1; //weeks $expiry = time(); $expiry = $expiry+($duration*604800); $expiry = date("F j, Y",$expiry); $width = 346; $height = 216; $im = ImageCreate($width, $height); $white = ImageColorAllocate ($im, 255, 255, 255); $black = ImageColorAllocate ($im, 0, 0, 0); 

First, define a canvas 3 inches tall and approximately 4.75 inches wide; also define the colors $white and $black to be used later in the script:

 ImageFill($im, 0, 0, $black); ImageFilledRectangle($im, 2, 2, 343, 212, $white); 

Two lines create a black border. First, the script fills the canvas with black, then the ImageFilledRectangle( ) function fills with $white a rectangle two pixels shy of the full canvas size on each side.

To add the text, the script uses the ImageTTFText( ) function and the TrueType Verdana font file (also used in the PDFlib script). Unlike the PDFlib script, the GD image functions draw on the canvas from the upper-right corner. The numeric parameters sent to the function are the size, angle, and X- and Y-axis starting points for the text:

 ImageTTFText ($im, 20, 0, 172, 60, $black, "VERDANA.TTF", "C O U P O N"); ImageTTFText ($im, 30, 0, 164, 100, $black, "VERDANA.TTF", "50% OFF"); ImageTTFText ($im, 10, 0, 20, 184, $black, "VERDANA.TTF", "Not valid with other offers. Void where prohibited."); ImageTTFText ($im, 10, 0, 20, 196, $black, "VERDANA.TTF", "Expires: ".$expiry); 

Two lines place the logo, too. With the file itself stored in the variable $graphic, the ImageCopy( ) function requires three pairs of numeric parameters: the placement coordinates (8,8) on the destination file ($im), the starting coordinates (0,0) in the source file ($graphic), and the size of the image to be placed (144,144):

 $graphic = ImageCreatefromPNG("logo.png"); ImageCopy($im,$graphic,8,8,0,0,144,144); 

Finally, the script outputs the image to the browser and removes the file from PHP's memory:

 header ("Content-type: image/png"); header("Content-disposition: inline; filename=coupon.png"); ImagePng ($im); ImageDestroy($im); ?> 

Using R&OS PDF class

This PHP class provides a powerful alternative for creating dynamic PDFs if the PDFlib functions are not available:

 <? $discount = "50"; $duration = 1; //weeks $expiry = time(); $expiry = $expiry+($duration*604800); $expiry = date("F j, Y",$expiry); include ('class.ezpdf.php'); 

The required code and fonts for this PHP class can be downloaded from the author's web site listed in the "See Also" section in this Recipe.

The code that does all the heavy lifting is in the file class.ezpdf.php. For this example, I have uploaded it to the same directory as the script that will generate the coupon.

These next two lines create a letter-size PDF canvas and set 1-inch margins:

 $pdf =& new Cezpdf('LETTER','portrait'); $pdf->ezSetMargins(72,72,72,72); 

For the border, I specify the style, and then use the $pdf->line command to draw the four sides. The four numeric parameters define the X-and Y-axis start and end points for each line in this order: X1, Y1, X2, Y2. The 0,0 point in this coordinate system is at the lower-left corner of the canvas:

 $pdf->setLineStyle(1,'','',array(3)); $pdf->line(72,531,72,720); $pdf->line(418,531,418,720); $pdf->line(72,720,418,720); $pdf->line(72,531,418,531); 

A single line places the logo at the X,Y coordinates of 18,144.

 $pdf->ezImage($DOCUMENT_ROOT.'/path/to/logo.jpg',18,144,none,left); 

As with the other two scripts, placing text requires selecting the font, setting placement coordinates, and writing the copy onto the canvas. Unlike its counterparts, the R&OS PDF class comes with a few fonts, sparing you the trouble of tracking down your own:

 $pdf->selectFont('fonts/Helvetica.afm'); $pdf->ezSetY(684); $pdf->ezText("C O U P O N",     18,array('justification'=>'center','aleft'=>'252','aright'=>'400')); $pdf->ezSetY(648); $pdf->ezText($discount."% off",42, array('justification'=>'left','aleft'=>'252','aright'=>'400')); $pdf->ezSetY(567); $pdf->ezText("Not valid with other offers. Void where prohibited.\n".     "Expires: ".$expiry,10,     array('justification'=>'left','aleft'=>'90','aright'=>'400')); 

Finally, send the completed file to the browser:

 $pdf->ezStream(array('Content-Disposition'=>'coupon.pdf')); ?> 

All three options described in this Recipe are well documented and can be extremely powerful tools after you become familiar with the library's more advanced techniques. The GD image library can be used to create complex graphical representations of many types of data or perform manipulations on image files already stored on your server (see Recipe 5.6). With a script that generates a dynamic PDF, you can create up-to-date downloadable product sheets from database content, or printable and faxable forms for situations where applicants must sign or have their application notarized before sending them to you.

See Also

The PHP manual pages for the two function libraries are at http://www.php.net/manual/en/ref.pdf.php and http://www.php.net/manual/en/ref.image.php. The R&OS PDF class can be downloaded from http://www.ros.co.nz/pdf.



Web Site Cookbook.
Web Site Cookbook: Solutions & Examples for Building and Administering Your Web Site (Cookbooks (OReilly))
ISBN: 0596101090
EAN: 2147483647
Year: N/A
Pages: 144
Authors: Doug Addison

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net