PHP
  Home arrow PHP arrow Page 2 - Anatomy of an Output Class
Moblin
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Dedicated Servers  
Actuate Whitepapers 
Moblin 
JMSL Numerical Library 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
PHP

Anatomy of an Output Class
By: Daryl Houston
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 1
    2003-07-16

    Table of Contents:
  • Anatomy of an Output Class
  • PDF Basics
  • Writing PDFs
  • Conclusion

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT

    Free Web 2.0 Code Generator! Generate data entry and reporting .NET Web apps in minutes. Quickly create visually stunning, feature-rich apps that are easy to customize and ready to deploy. Download Now!

    Anatomy of an Output Class - PDF Basics


    (Page 2 of 4 )

    Since PDF output was what prompted me to put this class together, let's start with some PDF basics. First off, while I've seen utilities that'll generate PDFs from scratch by writing raw PDF output, I had PDFLIB at my disposal and made good use of PHP's functions that interact with the library. Among these are functions that allow you to open and close a PDF, write text, set the font specifications, calculate string widths, move the cursor around, draw lines, insert page breaks, and add hyperlinks. Again, I'm not going to go into code specifics here; for that, I recommend php.net's handy dandy function reference.

    To create a PDF, you have to give it a page size and then start moving the cursor around and writing and drawing. You open a page, add what text and drawings you wish to add, close the page, and either move on to the next page or close the PDF. Since I pull my data from databases, my initial impulse was to pass my class an array of database row arrays. So while I was looping through my result set, I was performing any data validation and crunching and then pushing the current row onto an array, which I then passed to the output class. Our reports tend to have column headers on each page, and these tend to be hyperlinks that allow you to sort the results by column. It was necessary, then, to detach the column headers from the rest of the data so that they could be added to each page. 

    "Simple," I thought. "I'll just allow the user to set a flag determining whether or not column headers are being printed and, if so, print the first row of the data array on each page." 

    Of course, extra code to force the class to print the links was also necessary. And I wrote the whole class with these conventions in mind. Then I came across a report that had hyperlinks in places besides the column header rows. The whole first column might contain links, for example, or the 19th column. Further, I discovered that some of our reports had bar graphs on the back page that were generated by taking counts of certain fields within the data set. Approaching the data as a set of rows was going to be cumbersome at best given the way PDFs handle the insertion of hyperlinks, and I hadn't even given consideration to graphs at this point. I saw myself starting to write lots of spaghetti code in order to format my data before passing it to the class, and I decided there had to be a better way.

    The Data Wrapper

    Enter the Datum class. Datum is singular for data, and I named the class on the premise that if you have an array of objects that format data, the array might be called "data," but each object would be a datum. (Next, perhaps I'll write a grammar class.) In order to provide abstraction for my row data and my graph data (and after some trial and error with real-life application of the class), I decided that a datum object should hold the following information:

    text (A label for graphs or a value for row data)*
    link (The link, if applicable)
    color (An array of RGB color vals from 0-1, suited more to PDF output than otherwise)
    row (The row number for this object, probably generated by a count)
    col (The col number for this object, probably generated by a count)
    val (The value, most useful for graph data)*
    pdf_width (The PDF width for the given string)
    textarray (If the PDF width is too wide for the given column, an array of the text split into lines that fit the column)

    The Datum class includes a number of get and set methods that allow external code to manipulate these values. It's a small class. While looping through my database results, for each piece of data -- that is, for each column within each row -- I create a Datum object, using row and column counts to set the coordinates for each object. This allows me also to specify links for any given row or column, or any given piece of data. For example, I could do a modulus of the column and row counts and make every fifth column in every third row a hyperlink. Or I could check the text value for each object and make each object that reads "PHP Development" link over to devarticles.com. And since I'm packing all this information into Datum objects, I can pass those off very easily to any other class or set of functions I wish. That said, I did tailor the Datum class to be especially useful with the Output class. I'm not likely to need a PDF width for HTML output; nor am I likely to need to break long values into rows and pass that textarray attribute to the XML Output interface.

    Class Architecture

    Because I knew I'd ultimately be adding support for XML, XLS, and HTML and that some of the functionality of those sorts of output might overlap, I first wrote a base class named Output that contains properties and methods common to the four types of output. It's here that I set font attributes, whether or not to display column headers, and other properties common to more than one output type. The function that passes the Datum object array to the class is also common to all types of output and can be found in the base class.

    Then I split out four other classes that extend the Output class. They are PDF_Output, HTML_Output, XLS_Output, and XML_Output. These are what I instantiate when building a document. Because PDF_Output does things like calculate column widths and row counts, it's by far the most complex of these classes, so I'll devote the bulk of my essay to it. HTML_Output and XML_Output are pretty simple; they both loop through the data array and wrap the values with the appropriate markers to indicate HTML table elements or XML tags. When putting XLS_Output together, I cheated by using an existing class that actually writes the spreadsheet with the proper encoding and just passing my data to that class.

    More PHP Articles
    More By Daryl Houston


     

    PHP ARTICLES

    - Making Usage Statistics in PHP
    - Installing PHP under Windows: Further Config...
    - File Version Management in PHP
    - Statistical View of Data in a Clustered Bar ...
    - Creating a Multi-File Upload Script in PHP
    - Executing Microsoft SQL Server Stored Proced...
    - Code 10x More Efficiently Using Data Access ...
    - A Few Tips for Speeding Up PHP Code
    - The Modular Web Page
    - Quick E-Commerce with PHP and PayPal
    - Regression Testing With JMeter
    - Building an Iterator with PHP
    - PHP Frontend to ImageMagick
    - Using PEAR's mimeDecode Module
    - Incoming Mail and PHP






    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 6 hosted by Hostway