Tải bản đầy đủ (.pdf) (67 trang)

Tài liệu The Object Oriented Evolution of PHP5 ppt

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.68 MB, 67 trang )

FEBRUARY 2003
www.phparch.com
VOLUME II - ISSUE 2
The Object Oriented The Object Oriented
Evolution of PHP5Evolution of PHP5
A Look At The New OOP Model
Using The Zend Engine 2.0
By Zeev Suraski
Reviewed for you:
IonCube PHP Accelerator 1.3.3
CodeCharge Studio 1.0
Plus:
Tips&Tricks, Book Reviews, Product Reviews
and much more
Creating A CustomizedCreating A Customized
Template-EngineTemplate-Engine
Hacking the Smarty
Template Engine
Data Fingerprinting with Hash Functions in PHP
Time Travel: Breadcrumbs and Session History with PHP
Enterprise Applications:
PHP in a Multitier Environment
PHP in a Multitier Environment
The Magazine For PHP Professionals
php|architect
Technologies Ltd.
Visit www.zend.com
for evaluation version and ROI calculator
Zend Performance Suite
Reliable Performance Management for PHP
Serve More.


With Less.
The designers of PHP offer you the full spectrum of PHP solutionsThe designers of PHP offer you the full spectrum of PHP solutions
IINNDDEEXX
Departments
TABLE OF CONTENTS
February 2003 · PHP Architect · www.phparch.com
3
php|architect
Features
10 Time Travel - Breadcrumbs and
History with PHP
by Peter James
18 The Object Oriented Evolution
of PHP
by Zeev Suraski
27 PHP in an N-Tiered World
by Dave Palmer
32 Creating a Customized
Template-Engine
by Andreas Demmer
38 Building a Turing Test with PHP
and the GD Library
by Marco Tabini
47 Using, Reusing and Extending
Smarty
by Tomica Jovanovic
55 Data Fingerprinting with
Hash Functions in PHP
by Leon Vismer
4 EDITORIAL RANTS

5 NEW STUFF
6 REVIEWS
Zend Encoder V.3.1.0
22 REVIEWS
LogiCreate
61 TIPS & TRICKS
by John Holmes
65 BOOK REVIEWS
67 exit(0);
Hello, Mr. Gates?
EEDDIITTOORRIIAALL RRAANNTTSS
EDITORIAL
February 2003 · PHP Architect · www.phparch.com
4
php|architect
Volume II - Issue 2
February, 2003
Publisher
Marco Tabini
Editors
Arbi Arzoumani
Brian K. Jones
Marco Tabini
Graphics & Layout
Arbi Arzoumani
Administration
Emanuela Corso
Authors
Andreas Demmer, Peter James,
Tomica Jovanovic, Dave Palmer,

Zeev Suraski, Marco Tabini,
Leon Vismer
php|architect (ISSN 1705-1142) is published
twelve times a year by Marco Tabini & Associates,
Inc., P.O. Box. 3342, Markham, ON L3R 6G6,
Canada.
Although all possible care has been placed in
assuring the accuracy of the contents of this mag-
azine, including all associated source code, listings
and figures, the publisher assumes no responsibil-
ities with regards of use of the information con-
tained herein or in all associated material.
Contact Information:
General mailbox:
Editorial:
Subscriptions:
Sales & advertising:
Technical support:
Copyright © 2002-2003 Marco Tabini &
Associates, Inc. — All Rights Reserved
L
ately, I’ve been measuring the
progress of php|a in terms of
“brilliant ideas”. After a careful
analysis of our history up to this
point, I have noticed that
instead of following a smooth
linear progression based on con-
stant innovation, our ascension
from the ashes of the publishing

world seems to have resulted
from short-lived but intense
flashes of genius, which are then
followed by long periods of cere-
bral inactivity. (A related study
also showed that I have way too
much time on my hands, but I
was far too busy to notice or
even care about that).
For example, Arbi came up
with the idea of calling our mag-
azine “php|architect” after I had
been brooding over names like
“The PHP Gazette” and “The
PHP Informer” for days. I can
only be thankful for the com-
pletely random sequence of
synaptic signals that made that
brilliant idea come to life.
Given the spontaneity of our
collective genius, it would most
definitely prove futile to even try
to explain how we arrived at our
most brilliant idea: to ask Brian
Jones, who joined our editorial
staff last month, to become our
new Editor-in-Chief. I can only
say that it was a moment of
unparalleled brilliance. I’m sure
that we burned a good number

of those remaining brain cells
which had not yet been fried by
years of exposure to the radia-
tion that our monitors happily
produce to keep us warm, but it
was worth it.
This is, therefore, my last edi-
torial as the Editor of php|a. I will
still be the Publisher of this mag-
azine and I will do my best to
contribute my thoughts to our
exit(0) column (whose name
was another flash of inspiration,
if I may say so myself), but I will
move on to some of the new ini-
tiatives that we have in store for
you, and Brian will take over the
entire editorial process of php|a.
As my parting words from my
editorial post, let me tell you
about the Editor-in-Chief.
The post of Editor-in-Chief is
instrumental in defining the
course and stature of a maga-
zine, and I can only be happy
that Brian has decided to accept
our request to take this position
with us (not to mention how
happy I am that someone else
will be doing it! But alas, poor

foolish soul that he is, Brian will
only read this once the maga-
zine has already hit the virtual
stands, and by then his fate will
be sealed).
Naturally, the person who can
sport the title of Editor-in-Chief
enjoys a great deal of power—a
power that Brian promptly
abused by asking me to rewrite
this editorial, claiming that “my
thoughts were too fragmented”.
As if. That could ever. Happen.
Let me now tell you about the
Publisher. The post of Publisher
affords great powers as well.
That includes the power to edit
and reject (did I say reject? I
meant “evaluate”) the Editor-in-
Chief’s monthly editorial.
Regardless of whether his
thoughts are fragmented or not.
Ah, the bittersweet taste of
revenge
NNEEWW SSTTUUFFFF
NEW STUFF
ionCube Launches New Encoder
British PHP software company ionCube Ltd.
released version 2.0 of their standalone Encoder
product last month. The new encoder providers

additional features compared to its predecessors,
such as the possibility of creating text headers that
are appended to the encoded files. This could be
useful, for example, for creating copyright and
ownership notices, as well as instructions and
how-to guides at the beginning of each file. The
Encoder sells for $349.00 US.
For more information, you can visit the ionCube
website at :
/>TechMeridian Releases XAVIOUR
CMS
TechMeridian, a new PHP development compa-
ny based in the United States, has released a prod-
uct called XAVIOUR Web Application Platform.
According to TechMeridian, XAVIOUR represents a
combination of the features normally found in
content management and templating systems. It
promotes reusability of the code and provides a
flexible framework that can easily be extended by
writing code directly into the templates, if neces-
sary.
XAVIOUR is entirely based on PHP and
PostgreSQL, thus providing a platform that can
easily be taken to an enterprise-level of stability
and performance. The software product costs
$199.00 US for a single-domain license. More
information can be found on the TechMeridian
website at :
/>OpenOSX Updates OpenWeb With
PHP 4.3.0

MacIntosh open-source software provider
OpenOSX have updated their OpenWeb CD prod-
uct to include the latest version of PHP.
OpenWeb is a CD compilation of open-source
software for the MacIntosh market designed to
provide publishing and development tools to Web
developers and webmasters. Besides technologies
like Apache, PHP and MySQL, it also includes a
shopping card, a content management system
and a graphical management interface.
The new 2.5.1 update is available to registered
users of the OpenWeb product free of charge. A
new full subscription can be purchased for $60 US
from the OpenOSX website at :
/>2003 PHP Conference in Montréal
This just hot off the press—The Québec PHP
Association announced that they will be holding a
PHP conference in Montréal, Canada, on March
20th and 21st. The conference will attract a who’s
who of the PHP community, from PHP creator
Rasmus Lerdorf to Zend-engine co-creator (and
php|a author) Zeev Suraski. The conference will
include sessions in both French and English, and it
is sure to attract visitors from the Americas as well
as from Europe.
The php|a team will be with a booth and to
cover the event.
/>February 2003 · PHP Architect · www.phparch.com
5
php|a

The Magazine For PHP Professionals
php|architect
We Dare You
To Be
A Professional.
Subscribe to php|a Today and
Win a book from Wrox Press
RREEVVIIEEWWSS
REVIEWS
February 2003 · PHP Architect · www.phparch.com
6
T
he simplicity and immediateness of a scripting lan-
guage like PHP is a double-edged sword. On the
one hand, everyone has direct access to the source
code; no need to compile for separate platforms and
distribute separate versions of your application. On the
other everyone has direct access to the source code,
which makes the protection of intellectual property
really difficult.
Let’s face facts, it would be difficult for a software
market to exist without some form of code protection.
After all, PHP consultants and software developers are
selling their knowledge, which, for better or for worse,
is somewhat embedded into the source code they pro-
duce. The demand for code protection has resulted in
several products which have been developed to make it
possible to limit the functionality of a PHP script (or a
series of scripts) so as to facilitate a commercial licens-
ing scheme.

The Zend Encoder, produced by Zend Technologies
(yep, the same folks who wrote the Zend Engine on
which PHP is based) is a rather complete system that
makes it possible to transform a PHP source file into an
“intermediate” representation of itself—that is, a pre-
interpreted set of bytecode instructions that the PHP
interpreter would be able to execute but that are quite
meaningless to a human being. The resulting file is fur-
ther mangled to make reverse-engineering almost
impossible. In addition, it is possible to require that a
Reviewed For You
Zend EEncoder
V.3.1.0
By Marco Tabini
The Cost:
$960.00 - $2,880.00 (US)
(or less through special small business pricing)
Requirements:
-Supported PHP versions: 4.0.5 up through 4.3.0.
-Supported operating systems:
-Linux glibc 2.1 / 2.2 (e.g. RedHat
6.x/7.x/8.x, Debian 4.2, SuSE 6.4, Mandrake
8.1, and others)
-Windows® 98 / NT 4.0 / 2000 / XP.
-Solaris Sparc 2.6 /2.7 /2.8 (Non-GUI ver-
sion).
-Supported Web Servers for deployment:
-Apache 1.3.x, IIS 4 / 5
-Zeus (using FastCGI) or any Web server that
supports CGI

-The Graphical User Interface is supported under
Windows and Linux only.
Product Page:
Zend Encoder
Home Page:
Zend Technologies ()
Company Background:
Zend Technologies provides web developers and
enterprises using PHP, integrated software solutions
for developing, protecting and scaling their PHP
applications providing a foundation that allows
companies to efficiently and effectively develop PHP
based web applications. Zend's founders are the
designers of PHP 3, PHP 4 and Zend Engine 1.0; on
which all PHP sites and applications are run. They
are also currently leading the design and develop-
ment of PHP 5 and the Zend Engine 2.0.
REVIEWS
February 2003 · PHP Architect · www.phparch.com
7
Zend Encoder V.3.1.0
script only run if a special “license file” is present and
provided by the end-user, thus making it possible to
limit the execution of a script to a specific timeframe
(limited trial), or to specific IPs, and so on.
Installation
Zend installation systems are, in my experience,
among the best ones available to the PHP community.
As in most cases, the Encoder is a Java-based applica-
tion that will run on pretty much any platform—the

Zend website allows you to download a version for
Windows, Linux or Solaris.
On Linux, the platform I tested it on, the application
is set up through a very straightforward process that
even connects to the Zend website and downloads the
appropriate license code automatically. A free 14-day
trial of the Encoder is available, its only limitation being
that your encoded files will only work for three days,
regardless of what settings you choose when convert-
ing them.
The User Interface
Once installed, the Encoder launched flawlessly—no
ifs, ands or buts about it. It features a neat graphical
user interface (shown in Figure 1) that makes using the
software for the encoding of large numbers of files easy
and convenient.
As you can see, the interface is based on the concept
of a “project”—this way, you can encode entire direc-
tories of PHP scripts at the click of a mouse. In fact, I
tried to encode the entire php|a website, and the entire
operation took only a few seconds. The original files
were not overwritten (if they were, I’d lose our source
code!), but copied over to a destination folder of our
choosing. The program even skipped over our CVS
folders automatically!
The Encoder supports several options designed to
enrich the value of encoded files. For example, it’s pos-
sible to prepend a clear-text header to the file that
allows you to insert installation or usage comments, or
even plain PHP code that is executed if the server is not

set up properly to accept encoded files. In addition,
Figure 1
REVIEWS
February 2003 · PHP Architect · www.phparch.com
8
Zend Encoder V.3.1.0
the Encoder also applies several opti-
mizations to the code while encod-
ing it (although I did not find much
in the way of improvement to our
scripts’ performance I guess we
just write good code!), and it is pos-
sible to require that each encoded
script only work with other encoded
scripts. This last feature can be very
important if, for example, your
include files contain your custom
license authentication mechanism
and you don’t want them to be
replaced with dummy versions that
circumvent your scheme.
Licensing Capabilities
Perhaps one of the most interest-
ing features of the Encoder is its abil-
ity to encode a project and control
the functionality that an end-user
has access to by issuing a special license file. This can be
very useful if you plan to offer specialized “trial” ver-
sions of your application that the end-user can play
with, build upon as needed and then upgrade to a

“full” version by just installing a single file. Licensing is
only available if support for it is activated when a script
is encoded.
The licensing screen (Figure 2) offers a wide variety of
options, including the ability to limit the execution of
the scripts using constraints such as time or IP or even
a hardware ID that is generated by a small Zend appli-
cation distributed together with the Encoder.
Distributing the Code
Once encrypted, a project can be redistributed by
simply transferring the files to another system.
Depending on the settings, you may also need to dis-
tribute a license file.
In order to execute your script on a target system,
your customers will need to install a copy of the Zend
Optimizer together with their installation of PHP. This is
not normally a big problem, as the Optimizer is a freely
available product whose installation only require a
small change in the php.ini file. However, if the appli-
cation is being hosted by a third party, it might be dif-
ficult to convince them to install this software.
Advanced Capabilities And
Documentation
In addition to the GUI, the Encoder also features the
necessary tools for encoding scripts and generating
license files on-the-fly through a command-line exe-
cutable. This can be helpful if your goal is to hand out
licenses in an automated fashion directly from a web-
site.
There is no online help for the Encoder, but the instal-

lation includes a well-thought-out manual in PDF for-
mat that provides plenty of information on using the
Encoder, both programmatically and from the GUI.
Unfortunately, neither the installation program nor the
GUI application itself offers any hints that the docu-
mentation itself exists, and this may discourage the
less-than-zealous user.
Bottom Line
The Zend Encoder is not a cheap product, although
you can actually get it very inexpensively through the
Zend Small Business Program that we illustrated in last
month’s issue of php|a ($295.00 US will grant you a
license to the Encoder, the Zend Studio IDE and the
Zend Performance Suite). However, it is also a very
well-thought-out product that offers ease-of-use and
consistency—something you don’t always find in the
world of PHP.
If you’re looking for a way to protect your products
and want the maximum flexibility possible, then I rec-
ommend you check this product out. If your business
qualifies for the Small Business Program (visit
/>smallbiz.php for more information). I think you will
find that the entire package offers tremendous value at
a very reasonable price.
php|a
Figure 2

FFEEAATTUURREESS
FEATURES
February 2003 · PHP Architect · www.phparch.com

10
Introduction
The great philosopher and novelist George Santayana
once told us: “Those who cannot remember the past
are condemned to repeat it.”
The past has always been a vital part of the present.
Like a map, it tells us where we’ve been and gives us
important information with which to make decisions
about the future. If you’re asking yourself what all of
this has to do with PHP, let me show you.
Information is critical. If you are reading this maga-
zine, your business probably revolves around informa-
tion, and you probably recognize the value of that
information to the people who want it. The fact is,
regardless of what your business is, every time someone
visits your site you have the opportunity to capture use-
ful information about them. That information can be
used to significantly enhance their experience on your
site, and there are many levels of detail to be had.
For instance, you could request that users register
and log in to your site, which usually has required the
provision of at least some personal information on
behalf of the end user. You could use this to contact
your customers with promotions or newsletters, or tar-
get their demographic (age, gender, location) with
advertising. While the gleaning of this personal data
requires action from the user (ie, voluntary registra-
tion), other types of information can be gathered pas-
sively and silently.
A prime example of the type of data which can be

collected behind the scenes is ‘patterns of use’ informa-
tion. This can provide invaluable insight into how your
site is being used, allowing you to make decisions
about the layout of your site. This could influence link
Time TTravel -
Breadcrumbs aand
History wwith PPHP
By Peter James
With all of the things to consider when designing and laying out your site, you can quickly become lost and over-
whelmed. Usability, accessibility and localization usually require attention before a single line of code is written.
While I can’t possibly hope to cover all of these topics meaningfully in a single article, what I can do is give you some
code to implement one very important (and often overlooked) tool to increase your site’s usability: Breadcrumbs.
Information is critical. If you
are reading this magazine,
your business probably
revolves around information,
and you probably recognize
the value of that information
to the people who want it.
PHP Version: 4.0 and Above
O/S: Any
Additional Software: N/A
REQUIREMENTS
FEATURES
Time Travel - Breadcrumbs and History with PHP
placement, advertisement placement and numerous
other factors. As an aside, one popular tool that can aid
in the discovery and inspection of this data is
phpOpenTracker.
Another silently collected class of data, which will be

our primary focus in this article, is the history of the cur-
rent session. This is the most easily handled type of
information. We can get it as they navigate, use it
while we have them on the site, and then discard it
when their session ends. Unlike many other types of
desirable user data, it doesn’t require a database or the
associated design; it is very transient. Interestingly
enough, if stored across sessions, the history provides
patterns of use data, which we mention briefly above.
Among many other things, this information can be
used to provide enhanced navigation options, called
‘breadcrumbs’, which is the subject of this article.
First, I’ll first explain what breadcrumbs are, and then
I’ll examine in detail the ways in which breadcrumbs
can be used, giving you plenty of usable code along the
way.
A note about the coding
style used in my examples
In all of my examples involving sessions, I will use the
$_SESSION[] array, rather than the associated glob-
als. Aside from being what I consider to be a cleaner
approach, this will reduce the chance for the introduc-
tion of errors by, for example, missing a
session_register() call. I also do not assume in
these examples that you will have register_glob-
als enabled in your php.ini file. This will ensure max-
imum compatibility with different systems and PHP
implementations.
Of Bread and Crumbs
‘ and Hansel comforted his little sister and said: “Just

wait, Gretel, until the moon rises, and then we shall see
the crumbs of bread which I have strewn about, they
will show us our way home again.’
- Hansel and Gretel - Brothers Grimm, et al
Earning their name from the above-quoted famous
tale, breadcrumbs are a navigation tool that helps the
user find their context, and quickly navigate back to
anywhere in that context. Breadcrumbs can be used to
expose the structure of the site to the user, allowing
them to learn the location of items.
Usually found near the top of a web page under the
title banner, breadcrumbs can be created using any
server-side or client-side language. An example bread-
crumb is shown in Figure A, and a nice, live example of
breadcrumbs can be found at Google’s web directory
at />Figure A
Usability expert Keith Instone tells us that there are
generally two different types of breadcrumbs: location
and path.
Location breadcrumbs are useful on hierarchical sites,
and represent a straight line from home (or the root) to
your current location. This is similar to a file path in the
Windows Explorer location bar, or the output of the
pwd command in Unix, and is what we saw in
Figure A.
Path breadcrumbs are much less structured, and
show the actual path you took to your current location,
as in Figure B. Hence, if you jump in from a search
engine, you’ll see a breadcrumb with only one crumb.
Clicking a link on that page will take you to another

page on that site, where you will then see two crumbs,
and so forth. This can be used on non-hierarchical sites
to supplement with a visual what’s under the browser’s
back button.
Figure B
Is that clear? Location breadcrumbs are like a ‘You are
here’ marker on a map, and path breadcrumbs are like
a highlighted route on a map. Location breadcrumbs
are more focused on where you are in the scheme of
things, whereas a path breadcrumb is more concerned
about the way you came.
As an aside, it may be that if you used a search engine
and looked for “daisy”, you might come across the
page in Figure A directly. Strangely, you may still see
the full location breadcrumb, even though you didn’t
navigate through those points. This is because pages
on sites that implement location breadcrumbs typically
know their way home. This can work in a couple of dif-
ferent ways, which I’ll discuss a little later.
Because they are the most common form, this article
will focus on the location breadcrumb concept,
although I will relate back to path breadcrumbs when
appropriate. In fact, the second example that we will
cover will actually be a hybrid that looks like a location
breadcrumb, but the processing underneath is closely
related to that of the path breadcrumb method. From
this point on, unless otherwise noted, when I talk about
breadcrumbs I’ll be referring to location breadcrumbs.
More About Breadcrumbs
Breadcrumbs usually will appear like a directory struc-

Store > Tables > Wines > Tables >
Liquers
> Edit
Home > Life > Plants > Flowers > Daisy
February 2003 · PHP Architect · www.phparch.com
11
FEATURES
Time Travel - Breadcrumbs and History with PHP
ture, which is appropriate since they work best when
you have a highly hierarchical site layout. A user can
quickly navigate to any previous level by clicking one of
the links in the breadcrumb. For instance, if a user
clicked on the Plants link in Figure A, she would likely
see a page listing the different types of plants, such as
flowers, trees, and grasses. The breadcrumb found on
that page might look like Figure C.
Figure C
Breadcrumb separators can be anything, including
images, but are commonly one of a number of semi-
intuitive characters, as shown in Figure D.
Figure D
The links, such as Home and Monsters above, are links
that contain just enough informtion to get you back to
that place in your session history. Depending on your
intention, and the layout of the site, this information
can be very different, ranging from a plain script name
through to a full blown URL. (or even a Javascript func-
tion call).
HarveysHTMLHaven.com
Let’s set the stage. Harvey is an aspiring business

leader, and his final project while studying for his MBA
required a business idea that related to IT. Harvey
thought about it (no pun intended), and decided that
as a part of his business he could resell web code and
graphics. All he had to do was browse the web for an
hour or two, and he’d have enough code and images
to start up his business, HarveysHTMLHaven.com.
Harvey ended up using a highly hierarchical physical
structure for his site. Directories named images and
code resided in his site’s home directory. Inside of the
images directory were four more directories named but-
tons, clipart, icons and photos. Inside each of these
were, potentially, gif, jpg and png. The code directory
had a similarly nested structure. For brevity, we’ll focus
only on the images tree.
A user could follow links down any of these paths,
and Harvey was concerned that the user would lose
their bearings and become frustrated. He wanted to
maintain some sort of map back to home at all times.
Breadcrumbs to the rescue! This is the easiest form of
breadcrumb to implement, because it is a more or less
static structure. Sure, Harvey may add images to his
individual library pages, but the category layout is
mostly static. Let’s write some code.
In Figure F, you’ll see a simple class that I created to
show how easy it is to deploy this form of breadcrumb.
Let’s examine this code. I needn’t have used a class
here, but it provides nice encapsulation. The class’s job
is to build breadcrumbs from the script’s URL, and
return the finished product. There are two member

variables: $_separator, which contains the charac-
ter used to delimit the links in the breadcrumb, and
$_label_map, which is a list of labels to use for direc-
tory names. This code works off of the directories in
the script’s URL, and the label map allows us to give
these directory levels descriptive labels, rather than out-
put the raw directory names.
The class also contains a basic constructor, as well as
a couple of gratuitous setter functions. The main func-
tionality, though, comes from get_output(), which
actually produces the breadcrumb. Let’s look at how.
It first gets the script’s path from the $PHP_SELF
server variable. If this class was instantiated from the
script running at
/>an example of what we’d get from this variable is
/foo/bar/index.php. The method then gets the
highest directory in the path, also the current directo-
ry, which in this case would be bar. Then it explodes
the path and puts all of the pieces into the $dirs vari-
able.
It now loops over all of the entries in $dirs. $base
keeps a running concatenation of the directories
already processed and is the basis for all links in the
breadcrumb. As each directory is processed, the loop
searches for an entry in the $label_map and, if one is
found, outputs a breadcrumb using the current $base
value, and the label from the map.
Once all of the directories are processed, the
$crumbs are joined together using $separator, and
Home > Movies

> Animated
Home
| Plays | Comedies
Home : Cooking
: Fish
Home
/ Monsters /
Sully
Home > Life > Plants
February 2003 · PHP Architect · www.phparch.com
12
<?php

// simple example of using SimpleBreadcrumb class
$crumb_label_map = $array(

images

=>

Images

,


buttons

=>

Buttons


,


clipart

=>

Clip Art

,


icons

=>

Icons

,


photos

=>

Photographs

,



jpg

=>

JPEG

,


gif

=>

GIF

,


png

=>

PNG

,


code


=>

Code

,
// etc
);

$sbc = &new SimpleBreadcrumb($crumb_label_map);

print $sbc->get_output();

?>
Figure G
FEATURES
Time Travel - Breadcrumbs and History with PHP
returned to the caller. Figure G contains the code to
use this class for Harvey’s site. Harvey simply includes
this file at the point in his page where he wants the
breadcrumb to appear, and he’s in business.
The code is very simple. A label map is defined, and
the SimpleBreadcrumb class is instantiated using it.
Harvey is happy with the default separator, so he does-
n’t pass any in. Finally, he gets the output, and prints
it. This is a pretty simple class, but it provides very
powerful functionality for a simple directory-oriented
site such as Harvey’s.
Although we know that this is a very simple example,
February 2003 · PHP Architect · www.phparch.com
13

1 <?php
2
3 // a simple breadcrumb class that works off of the directory
4 // names in the current script
5 class SimpleBreadcrumb
6 {
7 var $_separator =

>

;
8 var $_label_map = array();
9
10 function SimpleBreadcrumb($label_map=null, $separator=null)
11 {
12 if (isset($separator))
13 {
14 $this->set_separator($separator);
15 }
16 if (isset($label_map))
17 {
18 $this->set_label_map($label_map);
19 }
20 }
21
22 function set_separator($separator)
23 {
24 $this->_separator = $separator;
25 }
26

27 function set_label_map($label_map)
28 {
29 $this->_label_map = $label_map;
30 }
31
32 function get_output()
33 {
34 // get script path, strip any trailing slashes, and
35 // split into constituents
36 // ex. /images/icons/gif
37 $dir = $_SERVER[

PHP_SELF

];
38 $current = basename(dirname($dir));
39 $dirs = split(

/

, $dir);
40
41 // base is built as we go through the dirs
42 $base =

/

;
43 foreach($dirs as $dir)
44 {

45 $base .=

{$dir}/

;
46 if (isset($this->_crumb_label[$dir]))
47 {
48 if ($dir == $current)
49 {
50 $crumbs[] = $this->_crumb_label[$dir];
51 }
52 else
53 {
54 $crumbs[] =

<a href=

{$base}

>{$this->_crumb_label[$dir]}</a>

;
55 }
56 }
57 }
58
59 return join($this->_separator, $crumbs);
60 }
61 }
62

63 ?>
Figure F
FEATURES
Time Travel - Breadcrumbs and History with PHP
let’s mention a couple of its limitations.
First, it is dependent on a directory structure, which
makes it very fragile. This class simply doesn’t work if
your site is not laid out by directory, since that’s where
the breadcrumbs come from.
Second, it doesn’t actually maintain any history.
Although the URL in a site structured by directory can
generally be interpreted as the history (if your site is
navigated linearly) the breadcrumbs are still built
directly from it without any regard for querystring vari-
ables, or the path actually taken. This severely limits
how flexible this class is.
Let’s leave Harvey to his questionable business ideas,
and move on to a more complex situation involving
(almost) everyone’s favorite relative.
GrannysGiftGaggle.com
Granny Smith had a dream of being an online king-
pin. After some thought, she decided that the best way
to begin her dynasty was to open an e-store, and wait
for the riches to flood in. She even started buying
pants with extra-big pockets, so she’d have room for all
the money she was going to make.
Her store, GrannysGiftGaggle.com is an emporium of
goodies, from health food to hinges. If you can buy it,
you can buy it at Granny’s. She has hundreds of cate-
gories and thousands of sub-categories. Let’s examine

the structure a little further.
All activity on GrannysGiftGaggle.com comes
through specialized points of access, or controller
scripts, and as I mentioned earlier, there is no really
structured physical underlay for Granny’s site. She
mostly relies on the data passed in on the querystring
to get the current state, which determines what to
show.
Since the querystring will determine the current
page, it might be educational for us to follow a simple
set of transactions on Granny’s site, and see how peo-
ple navigate around in Figure H.
Now that we’ve got the view from 50,000 feet on
how Granny’s site works, we can move on to what we
need to make breadcrumbs work.
You may have seen some information in the links
above that might be useful for generating bread-
crumbs. This information will provide what bread-
crumbs require: state.
State and History
State can be defined as a “unique snapshot that is
quantified by values for a set of variables, characterizing
the web site for a period of time, and is different from
other states.” This is rather like your checkbook. Right
now, if it is balanced, you have a certain set of posses-
sions, and a certain amount of money left. Your check-
book, and life, is in a particular state. Writing a check
will transition you to another state (hopefully not a
broke one).
In order to get the information we need for the state,

we must first ask the question: What identifies it? The
answer to that question depends on the way you’ve put
your site together, and may end up being a very com-
plicated question to answer. Harvey used his directory
names to identify state, which was very simple. Granny
doesn’t really have that luxury, so she will need to per-
form a little more magic.
While Granny doesn’t have a physically hierarchical
system, we can see from the above transaction that she
does have a home directory, which appears to contain
a products directory and an estore directory. This allows
us to use Harvey’s system for part of the breadcrumb
generation. The rest of the breadcrumb will need to
be created from the incoming querystrings.
Granny’s breadcrumbs will be a little different, not
only in method, but also in construction. Granny’s
breadcrumbs will aggregate themselves based on the
user’s history, rather than building fresh on each page,
like Harvey’s. The reason for this is that Harvey had all
of the states built into each request (because of the
URL), whereas Granny doesn’t. The subcategory page
request contains no direct information about what
page it came from.
The user’s history is just a stored collection of past
states. As an example, the user’s session history, after
selecting the football category on Granny’s site, would
contain the following states.
1. Home – no variables, no directories
2. Product Categories – no variables,
products directory

3. Football Sub-Categories – category=football
variable , products directory
This is starting to look suspiciously like a breadcrumb!
Let’s see the code to “make it so, Number One”. It’s
listed in Figure I.
It’s ironic that this is the ComplexBreadcrumb class,
when the code is almost simpler than the
SimpleBreadcrumb class that we discussed earlier.
Regardless, I’ll walk through this code. Again, I really
didn’t need to use a class here, but there it is.
The purpose of the class is to store state history in the
Disclaimer: This is obviously not intended to be a
tutorial on how to write a shopping cart applica-
tion, and is only a very rough example, for demon-
stration purposes, of how an application like this
might work.
February 2003 · PHP Architect · www.phparch.com
14
FEATURES
Time Travel - Breadcrumbs and History with PHP
user’s session and allow retrieval of state in breadcrumb
form. It has two member variables, $_separator,
and $_current_state. $_separator again con-
tains the character used to delimit the breadcrumb’s
links, while $_current_state contains the label of
the current state. This label is used as a crude lookup
later.
The class also contains a very basic constructor,
which can optionally initialize the breadcrumb separa-
tor at instantiation. A setter function is also provided

for this purpose. The meat of the class is contained in
the get_output() method. This method first checks to
see if a state has been registered for the current page.
If not, it returns an empty string.
If get_output() did detect a current state, it makes a
non-linked breadcrumb entry for it, and then proceeds
to process the parents of that state. For each parent,
the state variables are URL-encoded and links are pro-
duced.
Once all of the parents have been processed, the
array of $crumbs is reversed because we built it right-
to-left, but want to display it left-to-right. Finally, the
completed breadcrumb string is returned.
Figure J shows a usage example of the
ComplexBreadcrumb class. This file could be either
included or embedded in the code that handles the
case where category is set, as in http://grannys-
giftgaggle.com/products/?category=foot-
ball.
This usage code instantiates our new class, and just to
be different, changes the output separator to a forward
slash. Since this is specific to the category state, it gets
the category from the $_GET array, and sets the state
accordingly. Finally, it gets the output and displays it.
I have no doubt that using a little ingenuity specific to
the situation, it would be possible to generalize this
usage code and use it as a common include file, similar
to Harvey’s.
February 2003 · PHP Architect · www.phparch.com
15

1
/>First the user navigates to the main page, where
they are presented with, among other things, a link to
the products section.
2
/>ucts/
When the user navigates to the products section,
they are presented with a number of product cate-
gories
3
/>ucts/?category=football
Once a category is selected, a list of subcategories
will appear.
4
/>ucts/?subcategory=footballs
After they select a category, a list of products
appears.
5
/>ucts/?product_id=A1234
Once a product is chosen, the user may browse
through any amount of relevant information about it,
including the description, testimonials, specifications
and supporting material.
6
/>e/?cart=add&prod_id=A1234
Once the user is happy with the product, they may
choose to add it to the cart.
7
/>e/?cart=checkout
If no other products are wanted, the next logical

step is to check out.
8
/>e/?cart=checkout&subpage=shipping
The checkout is multi-stage. First they must enter
their shipping address, and pick the delivery method.
9
/>e/?cart=checkout&subpage=billing
Second, they enter their billing information.
10
/>e/?cart=checkout&subpage=confirm
Then they confirm the order.
11
/>e/?cart=checkout&subpage=receipt
And lastly, they get the receipt
Figure H
FEATURES
Time Travel - Breadcrumbs and History with PHP
February 2003 · PHP Architect · www.phparch.com
16
1 <?php
2
3 class ComplexBreadcrumb
4 {
5 var $_separator = ' > ';
6 var $_current_state;
7
8 // constructor
9 function ComplexBreadcrumb($separator=null)
10 {
11 if (isset($separator))

12 $this->set_separator($separator);
13 }
14
15 function set_separator($separator)
16 {
17 $this->separator = $separator;
18 }
19
20 // set a state/crumb
21 // - 'parent' is the parent label (allows chaining)
22 // - 'label' is the state/crumb label you are adding
23 // - 'vars' is an array of name-value pairs (usually from $_GET) that
24 // identify the state/crumb
25 function set_state($label, $parent='home', $vars=array())
26 {
27 $_SESSION['_crumbs'][$label] = array( 'label' => $label,
28 'path' => $_SERVER['PHP_SELF'],
29 'vars' => $vars,
30 'parent' => $parent,
31 );
32 $this->current_state = $label;
33 }
34
35 function get_output()
36 {
37 // no current crumb means no crumb display on the page
38 if (! isset($this->current_state))
39 return '';
40
41 $crumbs = array();

42
43 // don't make a link from the current state
44 $crumbs[] = $this->current_state;
45
46 // get the current state's parent and set the new current
47 $parent = $_SESSION['_crumbs'][$this->current_state]['parent'];
48 $current = $_SESSION['_crumbs'][$parent];
49
50 // do all parents
51 do
52 {
53 foreach ($current['vars'] as $name=>$value)
54 $values[] = urlencode($name) . '=' . urlencode($value);
55
56 $crumbs[] = "<a href='{$current['path']}?" . join('&', $values) . "'>"
57 . "{$current['label']}</a>";
58 // get the current state's parent and set the new current
59 $parent = $_SESSION['_crumbs'][$this->current_state]['parent'];
60 $current = $_SESSION['_crumbs'][$parent];
61 }
62 while ($current['label'] != 'home'))
63
64 // reverse the array (we built it in reverse)
65 krsort($crumbs);
66
67 return 'back to ' . join(" {$this->separator} ", $crumbs);
68 }
69 }
70
71 ?>

Figure I
FEATURES
Time Travel - Breadcrumbs and History with PHP
You might notice that, with some effort, this more
complex version of breadcrumbing would work for
Harvey as well. For his situation, the first method is
more than adequate, and will keep things simple, but
this would certainly do the trick, too.
Limitations
Although these examples will cover help with the
majority of applications, they still don’t address a few
things:
Using images as separators is not supported. This
would be a very simple extension, and would really
only involve the addition of a parameter to the contruc-
tor, an extra setter method, and the extra logic needed
to add an <img> tag, rather than a symbol.
Saving $_POST variable state is also not supported.
This is a very simple modification, requiring only that
you change $_GET to $_REQUEST. Note that storing
and later resubmitting $_POST values is generally con-
sidered a bad idea, though, since they usually come
from submitted forms, and can have nasty side-effects
(like attempting to re-insert entries to your database
tables) if you aren’t careful.
If you are browsing Granny’s site, and you navigate to
two different products in two different categories, you
may find problems with old history. If you use your
browser’s back button to back out of the second prod-
uct all of the way back to the first product and refresh,

the categories link in the breadcrumb may be incorrect.
This is because each state overwrites any state with the
same name. This could be handled by further identify-
ing state using sequences or other methods, but you
will need to determine whether this is really an impor-
tant feature, or just fluff.
In the complex example, jumping in from a search
engine, or otherwise browsing in a non-linear fashion is
not supported. Because the breadcrumbs are built
incrementally, you would have some difficulty building
a dynamic system like this that responded well to that
situation. Two solutions come to mind:
1. default crumbs
2. redirection
‘Default crumbs’ means that if history cannot be
found, default crumbs will be inserted in their place.
‘Redirection’ means that if a page is navigated to that
shouldn’t be, the user would be redirected back into
the linear path. Both of these are reasonable solutions
in some situations. What you do in your situation is up
to you.
Applications that use very complex messaging and
event systems may have difficulty fitting into the mold
that breadcrumbs often require. Remember, if you face
this task, the fundamental question is ‘what defines
your state at any given moment?’. If you can define
your state minimally, then you are a big step closer to
having the information you need.
We introduced the concept of state history here,
which has a number of other uses as well. Some of

these uses include preventing form resubmission, path
breadcrumbs (remember those?), and in-stream
authentication. In-stream authentication refers to a sit-
uation in which you click a link, are asked to authenti-
cate, and then proceed to that link’s location directly,
which is a very nice usability feature.
Wrapping Up
Boy, we’ve come a long way! I hope these examples
have helped to clear the mud. As with just about any-
thing in this world, there are a million ways to imple-
ment breadcrumbs. I can’t possibly attempt to cover
every base, but I hope that I’ve been able to provide
some insight into this topic, and provide some useful
code to work with.
February 2003 · PHP Architect · www.phparch.com
17
php|a
Peter James is a developer and team lead working in Edmonton, Alberta,
Canada. In his spare time he tries to magically juggle his family, free-
lance work, tool development and learning. You can reach Peter at

References
“Those who cannot remember the past are
condemned to repeat it.”
Life of Reason, Reason in Common Sense,
Scribner’s, 1905, page 284
Definition of state
/>ill/Definitions.html
Breadcrumb concepts
/><?php

~
// simple example of using ComplexBreadcrumb class
$cbc = &new ComplexBreadcrumb(

/

);

// get category name
$category = $_GET[

category

];

$cbc->set_state(

{$category} categories

,


product categories

,
array(

category

=>$_GET[


category

])
);

print $cbc->get_output();

?>
Figure J
FFEEAATTUURREESS
FEATURES
February 2003 · PHP Architect · www.phparch.com
18
Where did it all start?
Few people know this, but when PHP as we know it
today was being molded, back in the summer of 1997,
there were no plans for it to have any object-oriented
capabilities. Andi Gutmans and I were working to cre-
ate a powerful, robust and efficient Web language
loosely based on the PHP/FI 2.0 and C syntax. As a
matter of fact, we got pretty far without having any
notion of classes or objects – it was to be a purely struc-
tured language. One of these summer nights however,
on August 27
th
that year, this changed.
At the time classes were introduced to the code base
of what was to become PHP 3.0, they were added as
syntactic sugar for accessing collections. PHP already

had the notion of associative arrays collections, and the
new critters were nothing but a neat new way of
accessing them. However, as time has proven, this new
syntax proved to have a much more far-reaching effect
on PHP than originally intended.
Another thing that most people don’t know is that by
the time PHP 3.0 came out officially in mid-1998 and
was gaining momentum at a staggering rate, Andi
Gutmans and I were already determined to rewrite the
language implementation. Users may have liked PHP
as it existed at the time - in fact we know they liked it.
But as the authors of the engine we knew what was
going on under the hood and we couldn’t live peace-
fully with that. The rewrite, which was later dubbed
the ‘Zend Engine’ (Zend being a combination of Zeev
and Andi), initiated and became one of the core com-
ponents of the 2
nd
revolution that PHP experienced in
just over a year.
This revolution, however, left PHP’s object model
mostly unchanged from version 3 – it was still very sim-
ple. Objects were still very much syntactic sugar for
associative arrays, and didn’t offer users too many addi-
tional features.
Objects in the old days
So, what could one do with objects back in the days
of PHP 3.0 or even with the current version of PHP 4.0?
Not that much, really. Objects were essentially contain-
ers of properties, like associative arrays. The biggest

difference was that objects had to belong to a class.
Classes, as in other languages, contained a collection of
properties and methods (functions), and objects could
be instantiated from them using the new operator.
Single inheritance was supported, allowing users to
The OObject OOriented
Evolution oof PPHP
By Zeev Suraski
One of the key ingredients in the upcoming version 5 of PHP will be the Zend Engine 2.0, with support for a brand
new object-oriented programming model. This article describes the evolution of the object-oriented programming sup-
port in PHP, covering the new features and changes that are scheduled for PHP 5.
FEATURES
The Object Oriented Evolution of PHP
extend (or specialize) the scope of an existing class
without having to write it from scratch or copy it.
Finally, PHP 4.0 also added the ability to call methods
of a specific class, both from within and outside object
contexts.
One of the biggest twists in PHP’s history was the fact
that despite the very limited functionality, and despite
a host of problems and limitations, object oriented pro-
gramming in PHP thrived and became the most popu-
lar paradigm for the growing numbers of off-the-shelf
PHP applications. This trend, which was mostly unex-
pected, caught PHP in a sub-optimal situation. The fact
that objects were not behaving like objects in other OO
languages, and were instead behaving like associating
arrays was beginning to show.
The limitations of the
old Object Model

The most problematic aspects of the PHP 3 / PHP 4
object model was the fact that objects were passed
around by value, and not by reference. What does that
mean?
Let’s say you have a simple, somewhat useless func-
tion, called myFunction():
As you probably know, the call to myFunction()
will leave $myArgument unchanged; Sent to
myFunction() is a copy of $myargument’s value, and
not $myargument itself. This type of argument pass-
ing is called passing arguments by value. Passing argu-
ments by reference is done by most structured lan-
guages and is extremely useful, as it allows you to write
your functions or call other people’s functions without
worrying about side effects they may have on variables
outside their scope.
However, consider the following example:
(The implementation of Woman::setHusband(),
Man::setWife() and areMarried() is left as an
exercise for the reader).
What will areMarried() return? We would hope
that the two newlyweds would manage to stay married
at least until the following line of code, but as you may
have guessed – they wouldn’t. areMarried() will
confirm that they got divorced just as soon as they got
married. Why?
The reason is simple. Because objects in PHP 3.0 and
4.0 are not ‘special’, and behave like any other kind of
variable, when you pass $joanne and $joe to wed(),
you don’t really pass them. Instead, you pass clones or

replicas of them. So, while their clones end up being
married inside wed(), the real $joe and $joanne
remain within a safe distance from the sacrament of
holy matrimony, in their protected outer-scope.
Of course, PHP 3 and 4 did give you an option to
force your variables to be passed by reference, conse-
quently allowing functions to change the arguments
that were passed to them in the outer scope. If we
defined wed()’s prototype like this:
then Joanne and Joe would have had better luck (or
not, depending on your point of view).
However, it gets more complicated than that. For
instance, what if you want to return an object from a
function, by reference? What if you want to make
modifications to $this inside the constructor, without
worrying about what may happen when it gets copied
back from new’s result into the container variable?
Don't know what I'm talking about? Say hallelujah.
While PHP 3 and 4 did address these problems to a
certain extent by providing syntactic hacks to pass
around objects by reference, they never addressed the
core of the problem:
The Answer – Zend Engine 2
When we were finally convinced that objects are
indeed special creatures and deserve their own distinct
behavior, it was only the first step. We had to come up
with a way of doing this without interfering with the
rest of the semantics of PHP, and preferably, without
having to rewrite the whole of PHP itself. Luckily, the
solution came in the form of a big light bulb that

emerged above Andi Gutmans’ head just over a year
Objects and other types of values are not
created equal, therefore, Objects should be
passed around by reference unless stated
otherwise.
function wed(&$bride, &$groom)
function wed($bride, $groom)
{
if ($bride->setHusband($groom)
&& $groom->setWife($bride)) {
return true;
} else {
return false;
}
}
wed($joanne, $joe);
print areMarried($joanne, $joe);


function myFunction($arg)
{
$arg = 5;
}

And you call this function:
$myArgument = 7;
myFunction($myArgument);
print $myArgument;

February 2003 · PHP Architect · www.phparch.com

19
FEATURES
The Object Oriented Evolution of PHP
ago. His idea was to replace objects with object han-
dles. The object handles would essentially be numbers,
indices in a global object table. Much like any other
kind of variables, they will be passed and returned by
value. Thanks to this new level of indirection we will
now be moving around handles to the objects and not
the objects themselves. In effect, this feature means
that PHP will behave as if the objects themselves are
passed by reference.
Let’s go back to Joe and Joanne. How would wed()
behave differently now? First, $joanne and $joe will
no longer be objects, but rather, object handles, let’s
say 4 and 7 respectively. These integer handles point to
slots in some global objects table where the actual
objects sit. When we send them to wed(), the local
variables $bride and $groom will receive the values 4
and 7; setHusband() will change the object refer-
enced by 4; setWife() will change the object refer-
enced by 7; and when wed() returns, $joanne and
$joe will already be living the first day of the rest of
their lives together.
What does that mean
to end-users?
Alright, so the ending to the story is now more idyl-
lic, but what does it mean to PHP developers? It means
quite a number of things. First, it means that your
applications will run faster, as there will be much less

data-copying going around. For instance, when you
send $joe to a function, instead of having to create a
replica, and copy over his name, birth date, parents’
name, list of former addresses, social security number
and whatnot – PHP will only have to pass on one object
handle, one integer. Of course, a direct result of this is
also a significant amount of memory savings – storing
an integer requires much less space than storing a full-
fledged replica of the object.
But perhaps more important, the new object model
makes object oriented programming in PHP much
more powerful and intuitive. No longer will you have
to mess up with cryptic & signs in order to get the job
done. No longer will you have to worry about whether
changes you make to the object inside the constructor
will survive the dreaded new-operator behavior. No
longer will you ever have to stay up until 2:00AM track-
ing elusive bugs! Ok, maybe I’m lying with that last
one, but seriously, the new object model reduces the
object-related stay-up-until-2:00AM type of bugs very
significantly. In turn, it means that the feasibility of
using PHP for large-scale projects becomes much easi-
er to explain.
What else is new?
As one could expect, the Zend Engine 2 packs quite
a few other features to go along with its brand new
object model. Some of the features further enhance
object-oriented capabilities, such as private member
variables and methods, static variables and language-
level aggregation. Most notable is the revolutionized

interaction with external component models, such as
Java, COM/DCOM and .NET through overloading.
In comparison to the Zend Engine 1 in PHP 4.0,
which first introduced this sort of integration, the new
implementation is much quicker, more complete, more
reliable and even easier to maintain and extend. This
means that PHP 5.0 will play very nicely in your exist-
ing Java or .NET based setup, as you will be able to use
your existing components inside PHP transparently, as
if they were regular PHP objects. Unlike PHP 4.0, that
had a special implementation for such overloaded
objects, PHP 5.0 uses the same interface for all objects,
including native PHP objects. This feature ensures that
PHP objects and overloaded objects behave in exactly
the same way.
Finally, the Zend Engine 2 also brings exception han-
dling to PHP. To date, the sad reality is that most devel-
opers write code that does not handle error situations
gracefully. It’s not uncommon to see sites that spit out
cryptic database errors to your browser, instead of dis-
playing a well-phrased ‘An error has occurred’ kind of
message. With PHP, the key reason for this is that han-
dling error situations is a daunting task – you actually
have to check for the return value of each and every
function. Since set_error_handler() was added,
this issue became slightly easier to manage, as it was
possible to centralize error handling – but it still left a
lot to be desired. Adding exception handling to PHP
will allow developers both fine-grained error recovery,
but more important it will facilitate graceful applica-

tion-wide error recovery.
Conclusion
The release of PHP 5.0, powered by the Zend Engine
2.0, will mark a significant step forward in PHP’s evolu-
tion as one of the key Web platforms in the world
today. While keeping its firm commitment to users
who prefer using the functional structured syntax of
PHP, the new version will provide a giant leap ahead for
those who are interested in its object oriented capabil-
ities – especially for companies developing large scale
applications.
February 2003 · PHP Architect · www.phparch.com
20
php|a
Zeev has been working for over five years on the PHP project. Along with
Andi Gutmans, he started the PHP 3 and 4 projects and wrote most of
their infrastructure and core components, thereby helping to forge PHP
as we know it today and attracting many more developers to join the
movement. Zeev is a co-founder and CTO of Zend Technologies Ltd, the
leading provider of development and performance management tools for
PHP-enabled enterprises. Zend’s website is www.zend.com.

RREEVVIIEEWWSS
REVIEWS
February 2003 · PHP Architect · www.phparch.com
22
A
s a developer, I have always been used to building
most of my own websites from scratch, rather
than using something that other people have devel-

oped. When we had to build the php|a site, we did-
n’t even look at any other options—we simply
designed the website the way we wanted it and put it
together. The reason is simple: after so many years of
being in this business, I have a pretty good under-
standing of how things work and can take care of
most things more quickly than I can learn how to use
a new product that would do the same in my place
(plus, let’s face it, one always likes to think that his
own stuff is better than something an automated
script can generate).
Unfortunately, this approach does not always work.
Building things from scratch—even when it comes to
reusing some of your own code from previous proj-
ects—takes time, and time is money. When budget-
ary considerations must take precedence over person-
al pride and the general laziness that all programmers
sport, it’s necessary to look beyond one’s personal war
chest and start from solid building blocks that take
care of most basic (and some advanced) aspects of a
good website.
It’s therefore with quite a bit of interest that I look at
the LogiCreate product that we received from Tap
Internet for review this month. Now, it’s important to
understand that the version Tap sent us is a develop-
ment snapshot; as such, some of the kinks still need to
be worked out, but this really seems to affect only the
installation part of the application, and for the rest I
can’t really say that the product exhibits any major
flaws. I wish our “development snapshots” were quite

as good as this
What Is LogiCreate?
At the most basic level, LogiCreate is a web applica-
LogiCreate
Tap IInternet
LogiCreate is a web application framework, providing a common development base for web systems. By standardizing
development practices, developers can quickly create new web-based systems such as intranets, extranets, and other
database-driven applications.
The Cost:
$1,495.00 - $4,950.00 (US)
Requirements:
Any L.A.M.P. based architecture
Download Page:
LogiCreate
LogiCreate Home Page:

REVIEWS
tion framework. It provides a set
of modules that can be integrat-
ed into a single website, provid-
ing functionality like content
management, an ad placement
system, an FAQ, a search func-
tion, and more. If this sounds
like something that you’ve
already heard, I urge you to read
on—I had exactly the same
impression at the beginning, but
changed my mind as I explored
things in a bit more detail.

As with other similar systems,
an entire LogiCreate application
can be managed through an
easy-to-use web-based interface.
Unlike other similar systems,
LogiCreate takes a security-cen-
tric approach to the entire appli-
cation. Most functions can only
be managed by users who have
the proper permissions, and it’s
possible to push almost all data
that is published through the
website through an approval
process to provide complete
control over it.
What’s more, unlike most con-
tent management systems and
web application frameworks,
LogiCreate seems to have been
built with the understanding that
a developer might want to work with something more
than the templates offered by the framework. As
such, the creation of custom templates and custom
scripts is not only supported, but also encouraged as a
way to provide a more flexible environment for the
programmer.
The Installation Process
As I mentioned above, this is the only area where the
version of LogiCreate that we received still needs a sig-
nificant amount of work. The creation of a new

LogiCreate website takes place through a simple two-
step process in which the user is asked to enter only a
few parameters, like the site’s name and database
information (Figure 1). Here, my use of “Marco’s Site”
as the name of the application caused a bit of a hic-
cup—the single quote was not escaped and ended up
in a constant definition, thus confusing the PHP inter-
preter, which threw an error when I subsequently tried
to open my website. Note that the installation script
also asks for the database driver that should be used to
access the database. Although our version only came
with a driver for MySQL, the entire data access layer is
abstracted, and it’s actually possible to extend it to
support other database systems.
The installation process also includes a post-setup
phase in which the user is required to adjust the per-
missions of the files that have been created. Although
this requires only four simple shell commands, it could
certainly have been automated.
The simplicity of the installation process, even with
its manual portion, is somewhat staggering. As you
can see from Figure 2, LogiCreate is a complex piece
of software that includes a large number of modules.
For anyone who has ever tried to create a new online
store using Microsoft Commerce Server, the two-step
approach adopted by this application framework is
just plain great.
LogiCreate Modules
A total of twelve different modules were packaged
with the version that we received, with functionality

ranging from a “welcome page” to a complete con-
February 2003 · PHP Architect · www.phparch.com
23
Figure 1
REVIEWS
tent management system.
The modules can be adminis-
tered through the Hercules
Control Center (affectionately
referred to as “Herc”), a backend
web-based application that
allows you to control the individ-
ual settings of each aspect of your
website. As I mentioned earlier,
Herc provides a very well-
thought-out user management
system, complete with grouping
and permissions at both the user
and group level. Thus, for exam-
ple, if I want to publish a new
news item and type it into the
system (Figure 3), it will be
“parked” into a special repository
until it can be verified and
approved by someone who has
the correct permissions to do so.
Herc also provides a complete
statistical system that can be used
to create reports on the kind of
traffic that your site receives

(Figure 4). Although this tool
does not provide the level of
sophistication that a more spe-
cialized web analysis package
offers, it’s still very valuable,
because it produces reports in
realtime, rather than on a specific
schedule.
Expandability
How good is an application framework if it can’t be
expanded to meet your actual requirements?
Naturally, it depends: a non-technical person who is
just looking for a quick solution to his problems prob-
ably won’t care that he can’t mess around with the
source code. On the other hand, a developer who is
looking for a framework on which to build his website
will.
LogiCreate is clearly slanted towards the latter
approach. The system’s templates are really just PHP
scripts that make use of the various classes and meth-
ods made available by each of the application’s mod-
ules. This, in my opinion, is the way it should be—
after all, PHP provides an excellent development envi-
ronment, and there simply is no way that any other
artificial “templating system” can match its functional-
ity. The core of LogiCreate, therefore, relies heavily on
code reusability and, as such, it is primarily based on
OOP.
This, however, does not prevent you from imple-
menting your own PHP functionality inside a particu-

lar template. In fact, that’s the whole point of
LogiCreate’s philosophy: the modules, classes and
procedures that it provides are just there to help you
by providing a simple framework on which you can
build your own specialized functionality.
Documentation
This is probably another area in which LogiCreate
needs a bit of help. The user documentation, com-
February 2003 · PHP Architect · www.phparch.com
24
Figure 2
A non-technical person who is
just looking for a quick solu-
tion to his problems probably
won’t care that he can't mess
around with the source code.
REVIEWS
posed primarily of Herc’s user manual, is of excellent
quality and very clear. For some reason, however, it is
distributed separately from the Herc interface itself.
This makes it difficult for a user to get help from the
system, and risks negating the advantage of having an
interface like Herc in the first place. If I were to devel-
op a production system based on LogiCreate, inte-
grating the help in the Herc web pages would certain-
ly be on my to-do list.
The developer’s manual is a bit sparse, but otherwise
functional enough to be quite complete. It includes
information on how to create new templates and how
to modify (or integrate with) the application frame-

work itself. Mercifully, this is not a difficult task to
accomplish by an intermediate-level developer. My
only real gripe about the docs is that they contain very
few examples; my experience is that two lines of code
can easily explain what ten lines of text can’t, so I real-
ly hope that the Tap team will add more examples and
sample code to their documentation.
The Big Picture
From a purely technical perspective, I am pleasantly
surprised by how much LogiCreate manages to
accomplish without being over-complicated or requir-
ing a week of reading in order to get the proverbial
“Hello, World!” message to appear on the screen.
From a business point of view, LogiCreate is not
cheap, but given its characteristics can provide
tremendous value if you consider how long develop-
ing the functionality that it provides would take. The
product is priced at a base of $1,495.00 (US) per serv-
er, plus $500.00 (US) for each additional module that
you decide to use.
Surely, other inexpensive systems provide similar
frameworks, but it’s really difficult to find something
that is quite as simple to understand and master as
LogiCreate. Overall, if you’re building a new applica-
tion and are looking for a framework to take care of
the gritty work for you, I’d recommend you take a
look at this system.
February 2003 · PHP Architect · www.phparch.com
25
Figure 3

php|a

×