. 68
( 132 .)



$result = db_connect()->getRow($query, $bind,
394 Part IV: Not So Simple Applications

if (!$result[˜is_ok™])
// if the query has failed, the user has not been
// granted MySQL select access to the stage
// access table, and thus does not have permission
// to edit this story. print out an error and exit.
print subtitle(
˜You may not edit stories in the ˜
. stage($result[˜stage_id™])
. ˜ stage.™
print end_page();

Another item of particular interest is the extensive text-processing done in this
script. This is an example of the type of processing we might need to do if our users
are working with some sort of text-processing tool (such as an HTML editor or word
processor). Every tool has its own little quirks that we will need to account for. The
only way we are going to find out exactly what type of cleanup we need to do is by
examining the code created by the text editor in our workplace.
For instance, we are not going to want to have the beginning and ending tags of
a complete HTML page in the body text of an article. So if the user has written the
article in a WYSIWYG HTML editor, to make creating links and such easier, we™ll
want to strip out everything before and after the actual <BODY> part of the page,
and to get rid of the <BODY> and </BODY> tags themselves.

$body =
$body = preg_replace(˜/[\r\n]{1,2}/™,”\n”,$body);

Of course, PHP™s strip_tags() function could work for you, if you want to
allow a limited tag set and remove all other tags.
Starting at line 157 of the story.php file ” at the comment line fix up paragraph
tags ” is a nice block of code that will do a couple of neat things. If it appears the
user input the story without using <p> tags, the script will add them where it seems
appropriate, assuming the user indicated paragraphs with newlines (hard returns). If
the user did use <p> tags, the script examines the text, making sure that no funky
spaces or malformed tags are present. We recommend that you look at the code and
comments provided on the CD-ROM to get a good feel for how to do complex text
Chapter 11: Content-Management System 395

In this chapter you saw some of the nifty tricks and techniques that can go into cre-
ating a content-management system. Of course an application such as this can be
far, far more complex. But this is a good start and presents a reasonable way to
organize your code and database tables.
We also made use of MySQL™s grant statements when creating this application.
As we™ve said throughout, the grant scheme that we™ve used here may not be terri-
bly practical. However, it does provide a good example of how you could go about
setting up a system where one login name and password isn™t enough for the entire
Also, make sure to take a look at some of the text-handling code in edit_story.
php. Some of the code provides an excellent example of what you can do with PHP™s
string-handling functions and regular expressions.
Chapter 12


— Working with object-oriented code

— Looking at database schemas

IN THE COURSE OF THIS CHAPTER we are going to show one way of creating an online
catalog. You™ll see how to present and administer an application that presents some
typical retail items.
We, the authors of this book, feel that you are an intelligent person, as well as
someone with great taste in technical literature. We also believe that you picked up
this book because you want to learn as much as you can about applications devel-
opment with PHP and MySQL. That™s why we™re not wasting any time. Each chap-
ter introduces additional challenges, or at least presents something new and
different. This chapter is no exception.
If this chapter were to use the functions presented in the survey application in
Chapter 9, we would have little new material to present here. The application would
need nothing but a simple database schema, a few queries with some joins, and
calls to the HTML functions in the /functions/ folder.
To keep things interesting, we™re going to write this example using an object-
oriented programming style, and use a few of the OOP techniques we covered in
Chapter 7.

Chapter 7 covers the concepts and nomenclature associated with object-
oriented programming. In this chapter, we assume that you have read and
understood that information.

398 Part IV: Not So Simple Applications

Determining the Scope and Goals of
the Application
The goals we have in mind for this application are pretty modest. Imagine for a
moment that you own some sort of retail establishment that has goods you wish to
hawk. Further, assume that you have no interest in actually conducting transac-
tions over the Web. Maybe you are just paranoid about this newfangled method of
processing credit cards. Or perhaps you are running an elaborate tax-fraud scheme
that requires you to deal solely in unmarked twenties.

The code used in this catalog is reused in the creation of shopping-cart
application, where we show how to process credit-card transactions. See
Chapter 14 for the shopping cart.

Whatever the circumstance, all this site needs to do is show your wares in logi-
cal categories and breakdowns. You will hear more about the breakdown of the
information when we discuss the database schema.
The chief purpose of this chapter is to show how to create code that makes the
best use of the object-oriented approach. The classes must make use of inheritance
and encapsulation and should make the task of writing individual scripts a whole
lot easier. It™s also important to think about modularity. As indicated in the preced-
ing note, the code created here is reused in Chapter 14, so we want to write code in
such a way that it becomes easily reusable elsewhere.

Necessary pages
The pages that display the catalog aren™t very extravagant. For navigational pur-
poses a simple page displays a list of general product categories. Figure 12-1 shows
the category list.
From the list of categories, the viewer of the page clicks through to see a listing
of specific types of products available within the general product category. (For
example, the category Shirts contains T-shirts, dress shirts, and polo shirts.) Figure
12-2 shows this rather underwhelming page.
Chapter 12: Catalog 399

Figure 12-1: General category page

Figure 12-2: Product types page
400 Part IV: Not So Simple Applications

As a moment™s glance at my laundry can tell you, lots of different kinds of
T-shirts exist. Descending down into that product type shows a listing of the cata-
log™s selection, as shown in Figure 12-3.

Figure 12-3: Product page

Finally, there is a page that lists an actual item for sale. Notice that a thumbnail
of the item is shown, and that under the item is a listing of the various styles in
which the item is available. In Figure 12-4 the item is one of the T-shirts, which
comes in several sizes and colors.
Like all the applications in this book, this one has a series of administrative
pages. Given what you have seen in the previous paragraphs and figures, it should
be no surprise that the administrative pages create, delete, and alter information on
product groups, individual products, and styles (which can be applied to either
product groups or individual products). Some samples of these pages are shown in
Figures 12-5, 12-6, and 12-7 respectively.
Chapter 12: Catalog 401

Figure 12-4: Items page

Figure 12-5: Administration home page
402 Part IV: Not So Simple Applications

Figure 12-6: Product administration page

What do we need to prevent?
Unlike in the survey and the guestbook, no user interaction exists in this applica-
tion. To the world at large the catalog is read-only. So you don™t need to be quite as
concerned with bored people adding unwanted tags and scripts to the pages.
Instead, what you want to be most concerned about preventing is inaccurate and
duplicated data. You want to store one fact ” that no dress shirts are available in
orange, for instance ” one time, and have it be applied whenever necessary. If you
have to change 50 product entries to remove one style, you™re bound to miss some.
Chapter 12: Catalog 403

Figure 12-7: Style administration page

The Data
From what we™ve said about the application so far, you might think that you need
at least four main tables in the database: a general product category table, a prod-
uct types table, an individual products table, and a styles table. But think about
how you would naturally describe the data. If someone asked what the store sold,
your first answer would be something like “We sell shirts and rocks.” What kinds of
shirts? T-shirts, dress shirts, and polo shirts. What kinds of T-shirts? You get the
idea ” in each answer, we™re talking about our products ” just more specifically
each time.
The same applies to styles. A product might come in lots of flavors. Some of the
flavors are fruit flavors. Some of the fruit flavors are banana, cherry, and orange. If
you tried to make a different table for each level, you™d have big problems when
you needed to add a new level; the whole application would need to be rewritten.
So the database has just three main tables: a products table, a styles table, and a
mapping table to link products and styles together. The following shows the com-
plete schema.
404 Part IV: Not So Simple Applications

| +----------------------------+ |
|| +----------+ | | +--------+
| +--o<| products |-|--+ | +--o|-| images |
| | | | | | |
+----o<| | | | +--------+
| | | |
+--|-| |>0--+ |
| +----------+ |
| |
| +-------------------+ | +-------------+
+-o<| product_style_map | +-o|-| price_types |
| | | |
| |>o----o|-| |
+-o<| | +-------------+
| | | +--------+
| | |>o---|-| status |
| +-------------------+ +--------+
| +----------+
+--|-| styles |-|--+
| | |
| |>0--+

Just ignore price_types for now. It™s a table we use in the shopping-cart
example (which uses this same database) in Chapter 14.

If you remember the discussion-board example in Chapter 10, you have a sense
of how the products and styles tables work. Each product can either be a root-level
product or belong to another product “above” it in the hierarchy. Shirts are a root-
level product, T-shirts belongs to Shirts, Plain belongs to T-shirts, and so on. You
use the same structure in the styles table.
It™s worth spending a few minutes talking about product_style_map ” the table
that glues products and styles together. Our T-shirts come in multiple sizes (and dif-
ferent sizes for men™s and women™s shirts, to boot). They™re also available in several
different colors. In the most simple approach, product_style_map would contain a
row linking every different individual kind of T-shirt to every size and every color
in which it™s available. But remember what we said about wanting to avoid dupli-
cating data. If you know that you™re out of stock in the husky size for all of your
T-shirts, or if you add a new color, you don™t want to have to change dozens of


. 68
( 132 .)