. 74
( 132 .)


work in one of the scripts. We give you a look at display.php. This page is looking
for a product ID value to be passed in. If none is given, it displays some default val-
ues for the main page of the catalog.


// if no product_id value is supplied, display the main page
// of the catalog
$product_id = (int)array_key_value($_REQUEST,™product_id™,0);
$p = new Product(array(˜product_id™=>$product_id));

if (empty($p->product_id))
$p->description = <<<EOT
Here at Bag™O™Stuff, we™ve got so much stuff
we don™t know what to do with it. So buy some
and help us clear out some space.
$p->subproduct_title = “What™ve We Got?”;
$page_title = “Bag™o™Stuff”;

If you do get a product ID, you retrieve it from the database. You are going to be
using breadcrumbs for navigation, so you use the list_products() method to get
the list of parent products above the current one and convert the list of parent
products into a series of anchor tags.

// begin constructing the page title with a link to the main
// of the catalog

// add a link back to the product level to the page title,
Chapter 12: Catalog 435

// followed by the name of this product, and print out the
// top of the page

$titlebits = array(anchor_tag(˜index.php™, “Bag™O™Stuff”));
foreach ($p->list_parents() as $t)
$titlebits[] = anchor_tag(
, $t[˜product™]
$page_title = implode(˜&nbsp;>&nbsp;™, $titlebits);
print start_page($page_title);

Then all you do is hand off the Product object to the print_product() function
and call the usual end_page() function, and the page is ready to go:

// print out information about this product, and any styles and
// substyles it contains

// print out the bottom of the page
print end_page();


Now we want to take a look at the print_product() function and the functions
it uses to display the product.

This function does only a few things. It prints out a description of the product,
including a thumbnail image if one exists. Then it prints out the available styles for
the product and any child products, using the other two main display functions of
the application.

function print_product($p)
$image_tag = $p->thumbnail();
if (!empty($image_tag))
// if an image has been uploaded for the product,
// include the thumbnail version of the image,
// displayed as a link to the full-size version.
436 Part IV: Not So Simple Applications

$image_tag = anchor_tag($p->img->src, $image_tag);
print paragraph(˜<b>™.$p->product.™</b>™);
print paragraph($image_tag, nl2br($p->description));



This function is a lot longer than print_product(), but really, not that much more
is going on here. Mostly what it™s doing is building up an array of the styles that
apply to the product, in such a way that you can turn that array into an HTML table
on the page. If a style is marked as “Not available,” you don™t even mention it. If it™s
only “Out of stock,” you want people to know that you™ll have it eventually, so you
go ahead and display it, with a warning flag. The result looks something like this:

Colors Red, Blue, Green, Yellow, Orange, Black, White, Tie-Dye
Sizes Men™s Peewee, Junior, Medium, Large, Husky (Out of stock)
Women™s Petite, Small, Medium, Large

function print_styles(&$p)
$styles = $p->list_mapped_styles();

$style_table = array();
$row = 0;
$last_depth = 0;
$max_depth = 0;
foreach ($styles as $s)
$style = $s[˜style™];
if ($s[˜status_id™] == Product::NotAvailable)
if ($s[˜status_id™] == Product::OutOfStock)
$style .= ˜ <b style=”color:red”>(Out of Stock)</b>™;
settype($s[˜depth™], ˜int™);
if ($s[˜depth™] < $last_depth) {
for ($cell = 0; $cell < $s[˜depth™]; $cell++)
$style_table[$row][$cell] = ˜™;
$last_depth = $s[˜depth™];
Chapter 12: Catalog 437

$style_table[$row][$last_depth][] = $style;
$max_depth = max($last_depth, $max_depth);
foreach ($style_table as $r => $cells)
$i = 0;
foreach ($cells as $k => $v)
if (is_array($v))
$v = implode(˜, ˜, $v);
if ($k == 0 && $v != ˜™)
$v = “<b>$v</b>”;
$style_table[$r][$k] = $v;
$i = $k;
if ($i < $max_depth)
$style_table[$r][$i] = table_cell(array(
, ˜colspan™=>(($max_depth - $i)+1)
print paragraph(table(array(
˜rows™ => $style_table
, ˜border™ => 0
, ˜cellpadding™ => 3

This function is similar to print_styles(). It displays the list of immediate child
products of the current product, with each product name displayed as a link to
display.php for more detailed information about that product:

function print_children(&$p)
$child_price_count = 0;
$child_rows = array();
$children = $p->list_children();
if (count($children) > 0)
$child_url = ˜display.php?product_id=™;
foreach ($children as $c)
438 Part IV: Not So Simple Applications

if ((int)$c[˜price™] > 0 && $c[˜price™] != $p->price)
$child_price = $c[˜price™];
$child_price = ˜&nbsp;™;
if (!empty($c[˜description™])
&& $c[˜description™] != $p->description
$child_description = nl2br($c[˜description™]);
$child_description = ˜™;
if (!empty($c[˜notes™]))
$child_description .= “ <b
$child_rows[] = table_row(
$child_url.$c[˜product_id™], $c[˜product™]
, $child_price
, $child_description

if (!$child_price_count)
// if no child of this product has its own separate price,
// print out the product™s price now, and set the title of
// the price column to blank. (this will make that column
// essentially invisible.)
if ((int)$p->price > 0)
print paragraph(˜<b>Price:</b> ˜.$p->price);
$price_label = ˜&nbsp;™;
$price_label = ˜<b>Price</b>™;
Chapter 12: Catalog 439

if (count($child_rows) > 0)
// print out products belonging to this product
, table_row(˜<b>Product</b>™
, $price_label
, ˜<b>Details</b>™
print paragraph(

You might have found this chapter to be quite a handful. In addition to adding code
for file uploads, we have used a completely different method for the organization of
the code.
The object-oriented approach used in this chapter might not be your cup of tea.
And if it™s not, you™re in good company. Many people who work with PHP feel that
object-oriented programming makes little sense in a Web-development environ-
ment. But it has its advantages. And the object model in the new version of PHP is
greatly enhanced over that of previous versions, too.
As you can see in this application, once the classes are created you don™t need to
do much to get great functionality within your scripts. Further, in Chapter 14, you
can see how we take the code created here and build on it.
Chapter 13

Problem-Tracking System

— Designing a problem-tracking system

— Protecting yourself from redundant data

— Using the IntegratedTemplate class from the PEAR class libraries

— Creating a site that has both public and private portions


. 74
( 132 .)