Zend - How To Write to a PDF

The Zend Framework (ZF) provides a class, Zend_Pdf, for creating PDF files. A few years ago I had some experience creating PDFs using the fpdf library. As I recall, it worked quite well. However, since I now had begun developing using the ZF, I decided to try and make use of what it had to offer in the realm of PDF creation when the need for it arose recently.

I can't guarantee what follows will address all the needs of anyone reading this, but it solved a couple of issues I was having. Namely:

1) Wrapping text cleanly (breaking at words and not mid-words)

2) Creating new pages to the PDF, if necessary - since I had no idea how long the text might be.

The first place I looked was the documentation of Zend_Pdf. While it has a lot of really good examples on using Zend_Pdf, it didn't seem to address my particular needs. I then poked around the net to see what others had to say regarding Zend_Pdf and wrapping text. For the most part, what I found were people asking why Zend_Pdf didn't have a wrapping function. My inclination was to agree with that observation. Now, however, I'd have to say I think it makes more sense to handle the wrapping (and any other text manipulation) prior to passing it along to the PDF.

Here's an overview of how I achieved the results I was going after and an outline of what's going on in the example below.

1) Create a Zend_Pdf Object, set up the style, create the first page

2) Create a $text variable (in the example below, I read it in from a text file)

3) Draw $text to the PDF: $page->drawText($text, 40, 760);

At this point, this will just output the text on one line in one page. Not what we need.

4) Wrap $text using the wordwrap() function

   $text = wordwrap($text, 80, "\n", false);
   

where

$text = The string to wrap
80 = How long each line should be after wrapping (column width)
"\n" = How the line is broken (\n is the default)
false = Don't cut strings (as in, break up words to keep the desired width)

5) Tokenize $text and pass it line by line to the Zend_Pdf Object

   $token = strtok($text, "\n");
   

What this does is tokenize $text at each occurrence of "\n" (which we created above)

6) Set a variable to track the vertical position of the output, as new text is added (in this case, $y)

7) Loop through $token:

        while ($token != false) {
                if ($y < 60) {
                        $pdf->pages[] = ($page = $pdf->newPage(Zend_Pdf_Page::SIZE_LETTER));
                        $page->setStyle($style);
                        $y = 740;
                }
                else {
                        $page->drawText($token, 40, $y);
                        $y-=15;
                }
                $token = strtok("\n");
        }
       

Here's what's going on:

The loop continues as long as $token is not false. It first tests to see if $y is less than 60. $y is what is determining where, vertically, on the PDF the text should be placed and so at a certain point a new page should be created. That's what's going on within that conditional statement. A new page is created, it's given a style, and $y is reset to the top of the next page, in this case $y = 740. If $y is not less than 60, the line is drawn to the PDF at a consistent horizontal position (40) and the varying vertical position ($y). $y is then updated to move down the line on the next pass. Once outside the if/else, the string is tokenized again using $token = strtok("\n") - and if there is something to tokenize the process repeats.

8) Generate the PDF:

    $pdf->save('mine.pdf');
   

That's it.

Here's the complete PHP:

<?php
        require_once 'Zend/Loader.php';
       
        Zend_Loader::registerAutoload();

        $color = array();
        $color["blue"] = new Zend_Pdf_Color_Html("#466E99");
        $color["grey"] = new Zend_Pdf_Color_Html("#454545");
       
        $font  = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_HELVETICA_BOLD);
        $size  = 13;
       
        $style = new Zend_Pdf_Style();
        $style->setFont($font, $size);
        $style->setFillColor($color["grey"]);

        $pdf = new Zend_Pdf();
        $pdf->pages[] = ($page = $pdf->newPage(Zend_Pdf_Page::SIZE_LETTER));
       
        $page->setStyle($style);
       
        $file = "zendpdf.txt";
        $fh = fopen($file, 'r');
        $text = fread($fh, filesize($file));

        $page->drawText($text, 40, 760);
       
        $text = wordwrap($text, 80, "\n", false);
        $token = strtok($text, "\n");
       
        $style->setFillColor($color["blue"]);
        $page->setStyle($style);
       
        $y = 740;
        while ($token != false) {
                if ($y < 60) {
                        $pdf->pages[] = ($page = $pdf->newPage(Zend_Pdf_Page::SIZE_LETTER));
                        $page->setStyle($style);
                        $y = 740;
                }
                else {
                        $page->drawText($token, 40, $y);
                        $y-=15;
                }
                $token = strtok("\n");
        }
       
        $pdf->save('mine.pdf');

Thanks

Nice work, Thank You :) I have to test this in my project. I wonder when such functionality will be added to Zend Framework Core.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. Beside the tag style "<foo>" it is also possible to use "[foo]".
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
13 + 7 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.