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.. But there is a clear dist
Trang 1FEBRUARY 2003
VOLUME II - ISSUE 2
The Object Oriented
The Object Oriented
Evolution of PHP5
A Look At The New OOP Model
Using The Zend Engine 2.0
Tips&Tricks, Book Reviews, Product Reviews
and much more
Creating A Customized
Template-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
The Magazine For PHP Professionals
php|architect
Trang 2Visit 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 solutions
Trang 3and the GD Library
Trang 4Marco Tabini
Editors
Arbi Arzoumani Brian K Jones Marco Tabini
Graphics & Layout
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: info@phparch.com Editorial: editors@phparch.com Subscriptions: subs@phparch.com Sales & advertising: sales@phparch.com Technical support: support@phparch.com
Copyright © 2002-2003 Marco Tabini & Associates, Inc — All Rights Reserved
Lately, 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 willmove on to some of the new ini-tiatives that we have in store foryou, and Brian will take over theentire editorial process of php|a
As my parting words from myeditorial post, let me tell youabout the Editor-in-Chief
The post of Editor-in-Chief isinstrumental in defining thecourse and stature of a maga-zine, and I can only be happythat Brian has decided to acceptour request to take this positionwith us (not to mention howhappy I am that someone elsewill be doing it! But alas, poorfoolish soul that he is, Brian willonly read this once the maga-zine has already hit the virtualstands, and by then his fate will
be sealed)
Naturally, the person who cansport the title of Editor-in-Chiefenjoys a great deal of power—apower that Brian promptlyabused by asking me to rewritethis editorial, claiming that “mythoughts were too fragmented”
As if That could ever Happen
Let me now tell you about thePublisher The post of Publisheraffords great powers as well
That includes the power to editand reject (did I say reject? Imeant “evaluate”) the Editor-in-Chief’s monthly editorial
Regardless of whether histhoughts are fragmented or not
Ah, the bittersweet taste ofrevenge
Trang 5ionCube 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 :
http://www.ioncube.com/encoder
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 :
http://www.techmeridian.com/xaviour
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 Anew full subscription can be purchased for $60 USfrom the OpenOSX website at :
http://openosx.com/openweb/
2003 PHP Conference in Montréal
This just hot off the press—The Québec PHPAssociation announced that they will be holding aPHP conference in Montréal, Canada, on March20th and 21st The conference will attract a who’swho of the PHP community, from PHP creatorRasmus Lerdorf to Zend-engine co-creator (andphp|a author) Zeev Suraski The conference willinclude sessions in both French and English, and it
is sure to attract visitors from the Americas as well
Trang 6The 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
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)
-The Graphical User Interface is supported under Windows and Linux only
Trang 7Zend 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
InstallationZend 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 InterfaceOnce installed, the Encoder launched flawlessly—noifs, ands or buts about it It features a neat graphicaluser interface (shown in Figure 1) that makes using thesoftware for the encoding of large numbers of files easyand convenient
As you can see, the interface is based on the concept
of a “project”—this way, you can encode entire tories of PHP scripts at the click of a mouse In fact, Itried to encode the entire php|a website, and the entireoperation took only a few seconds The original fileswere not overwritten (if they were, I’d lose our sourcecode!), but copied over to a destination folder of ourchoosing The program even skipped over our CVSfolders automatically!
direc-The Encoder supports several options designed toenrich the value of encoded files For example, it’s pos-sible to prepend a clear-text header to the file thatallows you to insert installation or usage comments, oreven plain PHP code that is executed if the server is notset up properly to accept encoded files In addition,Figure 1
Trang 8REVIEWS 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 CodeOnce 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 site
web-There is no online help for the Encoder, but the lation includes a well-thought-out manual in PDF for-mat that provides plenty of information on using theEncoder, both programmatically and from the GUI.Unfortunately, neither the installation program nor theGUI application itself offers any hints that the docu-mentation itself exists, and this may discourage theless-than-zealous user
instal-Bottom Line
The Zend Encoder is not a cheap product, althoughyou can actually get it very inexpensively through theZend Small Business Program that we illustrated in lastmonth’s issue of php|a ($295.00 US will grant you alicense to the Encoder, the Zend Studio IDE and theZend Performance Suite) However, it is also a verywell-thought-out product that offers ease-of-use andconsistency—something you don’t always find in theworld of PHP
If you’re looking for a way to protect your productsand want the maximum flexibility possible, then I rec-ommend you check this product out If your businessqualifies for the Small Business Program (visit
smallbiz.phpfor more information) I think you willfind that the entire package offers tremendous value at
http://www.zend.com/store/products/zend-a very rehttp://www.zend.com/store/products/zend-asonhttp://www.zend.com/store/products/zend-able price
php|a
Figure 2
Trang 10The 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 sively and silently
pas-A prime example of the type of data which can becollected behind the scenes is ‘patterns of use’ informa-tion This can provide invaluable insight into how yoursite is being used, allowing you to make decisionsabout the layout of your site This could influence link
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
Trang 11FEATURES 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 http://directory.google.com/
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) toyour current location This is similar to a file path in theWindows 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 searchengine, you’ll see a breadcrumb with only one crumb.Clicking a link on that page will take you to anotherpage 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’sback button
As an aside, it may be that if you used a search engineand looked for “daisy”, you might come across thepage in Figure A directly Strangely, you may still seethe full location breadcrumb, even though you didn’tnavigate through those points This is because pages
on sites that implement location breadcrumbs typicallyknow 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 articlewill focus on the location breadcrumb concept,although I will relate back to path breadcrumbs whenappropriate In fact, the second example that we willcover will actually be a hybrid that looks like a locationbreadcrumb, but the processing underneath is closelyrelated to that of the path breadcrumb method Fromthis point on, unless otherwise noted, when I talk aboutbreadcrumbs I’ll be referring to location breadcrumbs.More About BreadcrumbsBreadcrumbs usually will appear like a directory struc-
Store > Tables > Wines > Tables >
Liquers > Edit
Trang 12FEATURES 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 ismostly static Let’s write some code
In Figure F, you’ll see a simple class that I created toshow how easy it is to deploy this form of breadcrumb Let’s examine this code I needn’t have used a classhere, but it provides nice encapsulation The class’s job
is to build breadcrumbs from the script’s URL, andreturn 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 tory names This code works off of the directories inthe script’s URL, and the label map allows us to givethese directory levels descriptive labels, rather than out-put the raw directory names
direc-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(), whichactually 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 thescript running at
http://www.example.com/foo/bar/index.php
an example of what we’d get from this variable is
/foo/bar/index.php The method then gets thehighest 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 directoriesalready processed and is the basis for all links in thebreadcrumb 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 | Plays | Comedies
Home : Cooking : Fish
Home / Monsters / Sully
<?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
Trang 13FEATURES 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 n’t pass any in Finally, he gets the output, and prints
does-it This is a pretty simple class, but it provides verypowerful functionality for a simple directory-orientedsite such as Harvey’s
Although we know that this is a very simple example,
1 <?php
2
3 // a simple breadcrumb class that works off of the directory
4 // names in the current script
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 );
Trang 14FEATURES 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-catecate-gories 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
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, characterizingthe web site for a period of time, and is different fromother states.” This is rather like your checkbook Rightnow, 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 checkwill transition you to another state (hopefully not abroke one)
In order to get the information we need for the state,
we must first ask the question: What identifies it? Theanswer to that question depends on the way you’ve putyour site together, and may end up being a very com-plicated question to answer Harvey used his directorynames to identify state, which was very simple Grannydoesn’t really have that luxury, so she will need to per-form a little more magic
While Granny doesn’t have a physically hierarchicalsystem, we can see from the above transaction that shedoes 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, notonly in method, but also in construction Granny’sbreadcrumbs will aggregate themselves based on theuser’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 whatpage it came from
The user’s history is just a stored collection of past
states As an example, the user’s session history, afterselecting the football category on Granny’s site, wouldcontain 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’slisted 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 reallydidn’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.
Trang 15FEATURES 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, thecompleted breadcrumb string is returned
Figure J shows a usage example of the
ComplexBreadcrumb class This file could be eitherincluded or embedded in the code that handles thecase 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 forwardslash 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 tothe situation, it would be possible to generalize thisusage code and use it as a common include file, similar
2
http://grannysgiftgaggle.com/prod-ucts/
When the user navigates to the products section,they are presented with a number of product cate-gories
Trang 16FEATURES Time Travel - Breadcrumbs and History with PHP
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' ],
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 ];
Trang 17FEATURES 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
LimitationsAlthough 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 prodprod-uct 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 usidentify-ing 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 tohaving the information you need
We introduced the concept of state history here,which has a number of other uses as well Some ofthese uses include preventing form resubmission, pathbreadcrumbs (remember those?), and in-streamauthentication 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 UpBoy, we’ve come a long way! I hope these exampleshave 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 coverevery base, but I hope that I’ve been able to providesome insight into this topic, and provide some usefulcode to work with
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
// get category name
$category = $_GET [ ‘category’ ];
$cbc -> set_state ( “ { $category } categories” , ‘product categories’ , array( ‘category’ => $_GET [ ‘category’ ])
);
print $cbc -> get_output ();
?>
Figure J
Trang 18Where 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 27th 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 wasgoing 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 2nd revolution that PHP experienced injust over a year
This revolution, however, left PHP’s object modelmostly unchanged from version 3 – it was still very sim-ple Objects were still very much syntactic sugar forassociative 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 ofproperties and methods (functions), and objects could
be instantiated from them using the new operator.
Single inheritance was supported, allowing users to
Trang 19FEATURES 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 ModelThe 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 passpass-ing arguments by value Passpass-ing
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 anexercise for the reader)
What will areMarried() return? We would hopethat the two newlyweds would manage to stay married
at least until the following line of code, but as you mayhave guessed – they wouldn’t areMarried() willconfirm that they got divorced just as soon as they gotmarried Why?
The reason is simple Because objects in PHP 3.0 and4.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 orreplicas of them So, while their clones end up beingmarried inside wed() , the real $joe and $joanne
remain within a safe distance from the sacrament ofholy 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 argumentsthat were passed to them in the outer scope If wedefined wed()’s prototype like this:
then Joanne and Joe would have had better luck (ornot, depending on your point of view)
However, it gets more complicated than that Forinstance, what if you want to return an object from afunction, 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 acertain extent by providing syntactic hacks to passaround objects by reference, they never addressed thecore of the problem:
The Answer – Zend Engine 2When we were finally convinced that objects areindeed special creatures and deserve their own distinctbehavior, it was only the first step We had to come upwith a way of doing this without interfering with therest of the semantics of PHP, and preferably, withouthaving to rewrite the whole of PHP itself Luckily, thesolution came in the form of a big light bulb thatemerged 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 )) {
wed ( $joanne , $joe );
print areMarried ( $joanne , $joe );
function myFunction ( $arg )
Trang 20FEATURES 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 lytrack-ing 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 enhanceobject-oriented capabilities, such as private membervariables and methods, static variables and language-level aggregation Most notable is the revolutionizedinteraction with external component models, such asJava, 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 newimplementation is much quicker, more complete, morereliable and even easier to maintain and extend Thismeans that PHP 5.0 will play very nicely in your exist-ing Java or NET based setup, as you will be able to useyour existing components inside PHP transparently, as
if they were regular PHP objects Unlike PHP 4.0, thathad a special implementation for such overloadedobjects, PHP 5.0 uses the same interface for all objects,including native PHP objects This feature ensures thatPHP objects and overloaded objects behave in exactlythe same way
Finally, the Zend Engine 2 also brings exception dling to PHP To date, the sad reality is that most devel-opers write code that does not handle error situationsgracefully It’s not uncommon to see sites that spit outcryptic database errors to your browser, instead of dis-playing a well-phrased ‘An error has occurred’ kind ofmessage With PHP, the key reason for this is that han-dling error situations is a daunting task – you actuallyhave to check for the return value of each and everyfunction Since set_error_handler()was added,this issue became slightly easier to manage, as it waspossible to centralize error handling – but it still left alot to be desired Adding exception handling to PHPwill allow developers both fine-grained error recovery,but more important it will facilitate graceful applica-tion-wide error recovery
han-ConclusionThe release of PHP 5.0, powered by the Zend Engine2.0, will mark a significant step forward in PHP’s evolu-tion as one of the key Web platforms in the worldtoday While keeping its firm commitment to userswho prefer using the functional structured syntax ofPHP, the new version will provide a giant leap ahead forthose who are interested in its object oriented capabil-ities – especially for companies developing large scaleapplications
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
Trang 22As 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 generperson-al laziness that person-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 tounderstand 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 theinstallation part of the application, and for the rest Ican’t really say that the product exhibits any major
flaws I wish our “development snapshots” were quite
Trang 23tion 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 camewith a driver for MySQL, the entire data access layer isabstracted, and it’s actually possible to extend it tosupport other database systems
The installation process also includes a post-setupphase in which the user is required to adjust the per-missions of the files that have been created Althoughthis requires only four simple shell commands, it couldcertainly have been automated
The simplicity of the installation process, even withits manual portion, is somewhat staggering As youcan 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 onlinestore using Microsoft Commerce Server, the two-stepapproach adopted by this application framework isjust plain great
LogiCreate Modules
A total of twelve different modules were packagedwith the version that we received, with functionalityranging from a “welcome page” to a complete con-
Figure 1
Trang 24tent 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
ExpandabilityHow 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 menting your own PHP functionality inside a particu-lar template In fact, that’s the whole point ofLogiCreate’s philosophy: the modules, classes andprocedures that it provides are just there to help you
imple-by providing a simple framework on which you canbuild your own specialized functionality
DocumentationThis is probably another area in which LogiCreateneeds a bit of help The user documentation, com-
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.
Trang 25posed 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 PictureFrom a purely technical perspective, I am pleasantlysurprised by how much LogiCreate manages toaccomplish 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 notcheap, but given its characteristics can providetremendous value if you consider how long develop-ing the functionality that it provides would take Theproduct is priced at a base of $1,495.00 (US) per serv-
er, plus $500.00 (US) for each additional module thatyou decide to use
Surely, other inexpensive systems provide similarframeworks, but it’s really difficult to find somethingthat is quite as simple to understand and master asLogiCreate Overall, if you’re building a new applica-tion and are looking for a framework to take care ofthe gritty work for you, I’d recommend you take alook at this system
Figure 3
php|a
Trang 26Figure 4
Trang 27If I had to take a guess, I would say someone on our
development team asks "so Dave, why can't our
[application server that rhymes with "confusion"]
tem-plates just directly query the database?" at least 5 or 10
times a day (maybe that's just a slight exaggeration) I
then feel compelled to explain the concept once again,
spouting trade-rag-babble about how great n-tiered
architectures are, and the benefits in doing things the
n-tiered way
The developer usually just nods his head humoring
me, then walks away reminiscing of the good old days
when they could just throw everything (including the
kitchen sink) into their code and be done with it But
alas, the logical conclusion is reached all the same that
n-tiered architectures lend themselves perfectly to
applications that must scale and be flexible
If you look at your PHP applications you'll notice a
common pattern This pattern includes things like
con-necting to and querying a database, performing logic
on data, and presenting that data back to the user so
that the user can act (or not act) on what was
present-ed For those of you who have built complex PHP
applications I'm sure that you've noticed that your code
becomes, well complex Maintaining it becomes
rather difficult, if not impossible, especially after taking
a break from it for a few days or even hours You'll also
notice that performance starts to degrade and ideals
like scalability and flexibility start to take a back seat tothe infectious mantra of "just get it working", whichinvades many a development project
If the above scenario strikes a little too close to homefor you, have no fear! The good news is that becausePHP is so accommodating in its openness and its abili-
ty to work happily with other technologies, PHP is quitecomfortable fitting in with an n-tiered architecture Ihope this article will equip you with at least enoughbackground knowledge to get you started with thisinvaluable development/design technique
Before I go on any further, perhaps some explanation
of what I mean by 'n-tiered' would be helpful "Tiers"are like layers Pardon the mixture of metaphors, and Iknow just how tired metaphors are when trying todescribe anything in the application developmentworld, but to think of a program as being comprised of
"layers" is a useful device in clarifying what I'm talkingabout Each "layer" or tier represents a common set offunctionality These layers/tiers in your typical PHPapplication are "coupled", meaning that your presenta-
PHP Version: 4.1.0 or Above O/S: Any
Additional Software: Java SDK 1.4.x AND Java J2EE 1.4.x, JBoss 3.0.4, MySQL
REQUIREMENTS
Trang 28FEATURES PHP in an N-Tiered World
tion layer is tied to your business logic layer which is in
turn tied to your data layer It's not unlike the days
when the client/server model was king Your client is a
"fat client", containing all of the code needed to not
only display a nice UI, but also to access and
manipu-late the data! Everything (including that kitchen sink) is
stuffed into the client, and the server is nothing more
than a data store This client/server model is still alive
and well today in many Web applications Even though
the web clients are a bit thinner (because the browser
takes care of some UI details), you still notice that
everything is still crammed into that client tier
Now, along comes the n-tiered architecture, which
spreads things out and creates more room for
every-thing by encapsulating these tiers into separate and
identifiable entities The "n" in n-tiered is simply the
mathematical notation for "unknown", meaning that
using this type of architecture assumes nothing about
what is required in order to implement the application
you must develop Essentially, you are no longer
con-fined to a stringent implementation model and are free
to scale and grow as the application and requirements
demand With the n-tiered framework, the application
can scale without the pain of having to re-engineer
everything each time growth is necessary
N-tiered applications are typically broken up into
dis-tinct units of work (tiers) and generally fall into these
The Presentation Layer is often referred to as the
"web tier." This tier contains all of the code to display
the user interface In our example, PHP running on
Apache represents our presentation or web tier
The Business Logic Layer is often thought of as the
"middle tier" This tier is where the vast majority of
business logic is implemented I often think of this tier
as being pretty fuzzy in that it may be comprised of
many smaller tiers, as is the case (to a lesser extent) in
this example The primary business logic component,
in our example, is an EJB But there is a clear distinction
between the EJB and the Data Access Object - the class
which is responsible for doing the "heavy lifting"
-which leads us into the next tier
Data access - This tier is often part of the middle tier,
but is clearly separate from the business logic tier in
that its primary responsibility is in establishing
connec-tions to data stores and querying those data stores In
our example, this is done with the Data Access Object,
which is a Java class running in the J2EE space which
sends queries to the MySQL database and returns data
back to the EJB (the main component of our business
logic layer, as noted above)
Finally, there's the Database Layer This tier is theend of the line, or beginning, depending on how youlook at it This tier represents our data storage tier
Each tier has a very specific purpose and depending
on the complexity of your application each of thesegeneral tiers may be broken up into more specific tiers.For example, the Business Logic tier may be comprised
of business rules that utilize messaging for systems gration, or Data Access tiers may be broken up intoseparate sub-tiers to handle legacy data sources andLDAP or other directory services which also supply data
inte-in some form
In this example I am using PHP as the presentationlayer The presentation layer is responsible for facilitat-ing the actions or events that occur in an application.You'll notice in the example that the PHP code does notcontain any database calls, nor does it contain any busi-ness logic The reason is that PHP, in this example, isresponsible for presenting data and enabling interac-tion between the user and the data Nothing more,nothing less
The "middle tier," the tier that contains the businesslogic and data access tiers, will be implemented using
an EJB (Enterprise Java Bean) in JBoss using the "sessionfacade" design pattern Using this particular designpattern in the J2EE space means we can further sepa-rate our middle tier code into clear distinctionsbetween controller (the EJB) and data access (DataAccess Object) J2EE (Java 2 Enterprise Edition) hasbecome (or is becoming) the defacto standard technol-ogy for the middle tier because of Java's wide accept-ance on most platforms and because Java's object ori-ented design makes modeling business processes muchsimpler However, I must digress, as this is not an arti-cle about the fundamentals of EJB, object orienteddesign principles or JBoss The code I have includedshould provide you with a good launching off point forgetting your feet wet in the middle tier
I have chosen to use MySQL to represent the datatier MySQL is a powerful and robust relational data-base which is free to use This ease of accessibility,along with its compact, simple design makes MySQLperfect for our informal example code There are lots
of other reasons to use MySQL in your applications but
I don't want to get political on you, so on with theshow!
Lets get on with the example, which I think clearlydescribes this n-tiered architecture and also clearly illus-trates the advantages of this type of architecture Thesmall application I am using to illustrate this concept is
a very simple user management program that enablesyou to add and edit a user account Keep in mind thatthis is merely an example and is used only to illustratehow PHP lends itself well to n-tiered applications Ieagerly invite you to take this code and run with it, andturn it into something useful
First things first You will need PHP (obviously) and
Trang 29PHP in an N-Tiered World
you will need to configure PHP with Java support for
this to work Next you'll need a copy of JBoss
(http://www.jboss.org) JBoss is an open source
J2EE application server Configuring JBoss can be a bit
confusing for those new to the whole Java application
server environment, but there are some excellent
resources such as the JBoss discussion forums and the
Getting Started PDF that can get you up and running
rather quickly Next, you'll need MySQL
(http://www.mysql.org) MySQL is rather simple
to setup and configure - just make sure everything is
running on your local host for this first example Once
you get more comfortable and have the machines to
do so, I would recommend spreading things out a bit
so you can really see how n-tiered architectures enable
logical scaling
Once you have JBoss and MySQL set up, configured
and running, you'll need to run the SQL scripts
provid-ed in the source code for this article (shown in listing
1) Basically you just need a database with a single
table You can use phpMyAdmin
scripts I used phpMyAdmin to generate them, so you
should have no trouble getting them to work
Next, you'll need to create a data source for JBoss that
maps to your MySQL database server and database I
provided my XML configuration files, which I use in my
own JBoss distribution to help give you a leg-up in
get-ting this running Just open up the
phpa_mysql-service.xml file and make the modifications to the
user name and password settings You'll also need to
change the login-config.xml file Please read the
READMEfile I included It should make getting
config-ured and running much simpler
Yes, I am the first to admit that doing this type of
development does have a bit of a steep learning curve,
but once you have gotten comfortable with the whole
notion of application servers and the configurations
surrounding them, all of this will make perfect sense
and become second nature
As part of the source code package you'll notice a
Java JAR file This JAR file contains the EJB classes you
need to deploy (place into the 'deploy' directory in the
JBoss server) You'll also want this JAR file in PHP's class
path This JAR file contains all of the required class files
of the EJB and the client application your PHP program
will use in order to "talk" to the EJB (running in JBoss)
Before we get too much into the source code, take a
look at figure 1 This is a simplification of the design of
the User Management application we'll be looking at
There are some important concepts illustrated in this
figure, one being that the presentation layer does not
directly call the middle tier (EJB) but uses a client
object to perform the work required to instantiate the
EJB and to pass user input into the middle tier
In this example, I use the Java Collections API (Vectors
and Hash tables) to pass data back and forth because
we use the WDDX API to serialize and unserialize thoseobjects into arrays in PHP Because we are dealing withdisparate application platforms (PHP and Java) we need
to pass complex objects from one platform to the nextand WDDX satisfies the requirements in this area rathernicely
Let's start looking at our PHP code in the presentationtier
The interesting stuff starts on line 24 (index.php is
included in this month’s package) Because we areusing an EJB to serve as our business logic - or "middle"tier, we need to establish three variables so that our EJBclient class can locate our EJB remote reference Wecommunicate with our EJB through a remote methodinvocation protocol, and through this protocol ourbusiness methods are said to be "exposed" throughwhat is referred to as a "remote interface."
$factory represents the naming factory interface
JBoss uses to instantiate the naming service $url
points to where JBoss is running, and also indicateswhich remote method invocation protocol we'll be
using $jndiName is the name of the reference in
JBoss's naming service which points to the actual bean's
"home" interface It is through the "home" interfacethat we create an instance of our remote object Iwould recommend checking out
more about EJB
Once we have our EJB "environment" established, wewant to create a Java object in our PHP script Theobject we are creating is an EJB client object This client
is a simple Java class that establishes the connectionbetween the PHP application and the EJB
We first create the object:
Now that we have an object reference for our EJBclient, we can issue method calls against our
$java_obj The first method call we need to issue is
an init() call The UserClient class contains an
init() method that performs the initial contextlookup of the EJB home reference and creates theremote object reference
Okay, so we've gotten all of the boring tal and initialization stuff over with and out of the way.Now we can have some fun!
environmen-To keep things in a single PHP script, I stuck all of thefunctions of this user management application into a
single index.php file The main functionality is
repre-sented by the following PHP functions:
$java_obj -> init ( $factory , $url , $jndiName );
$java_obj = new Java
( "org.ew.phpa.User.clients.UserClient" );
Trang 30FEATURES PHP in an N-Tiered World
saveChanges
printNewUserForm
printEditUserForm
printEntry
Let's start at the very beginning In the
printEntry() function (which is displayed if you've
just accessed index.php for the first time)
We first start with this:
You'll notice we call a method in our $java_obj
(which if you remember is a reference to our EJB client
`user_id` int(11) NOT NULL auto_increment,
`username` varchar(20) NOT NULL default ‘’,
`password` varchar(100) NOT NULL default ‘’,
`email` varchar(50) NOT NULL default ‘’,
`firstname` varchar(50) NOT NULL default ‘’,
`lastname` varchar(50) NOT NULL default ‘’, PRIMARY KEY (`user_id`)
) TYPE=MyISAM;
Listing 1
Trang 31PHP in an N-Tiered World
class) In our EJB client, we have a method called
getUsers()which takes no parameters and returns a
WDDX string This getUsers() method in our EJB
client maps directly to our remote EJB method called
getUsers()
The WDDX string is then deserialized (using
wddx_deserialize ($wddx)) into a PHP array Now
that we have our data back from our database (via our
middle tier) we are now ready to do something with it!
Here we are looping through the array, printing
indi-vidual <OPTION> tags for a <SELECT> widget Our
array contains two keys; user_id and username,
which represent the primary data elements needed in
order to paint this entry screen
Now that we have our entry screen displaying a list of
users, we also have an add and an edit button If we
click the add button we just get a nice little HTML form
where we can fill in a user name, password, email
address, first name and last name We have a method
called saveChanges() we'll use as our action()
function, which will be responsible for inserting or
updating our database We'll use the hidden form
vari-able user_id as a flag to help us determine what
action we need to take (if user_id is 0, then we are
inserting Otherwise, we are updating)
Taking a look at saveChanges() you'll notice we
need to first prepare our form data by serializing it in a
WDDX packet:
Once our data is serialized into a WDDX packet we
can call our EJB client:
You'll notice our friend $java_obj In our EJB client
class we have a method called saveUser() which
accepts a single string parameter This parameter is our
WDDX string The EJB client converts (deserializes) the
WDDX packet into a Java hash table Our EJB client
then calls our EJB remote method saveUser() and
passes the deserialized Hash table to the EJB
The $status variable is a simple string which is
returned by our EJB, through our EJB client which, forthis example, just says something like "hey, user infor-mation was saved." In a real application it's usually agood idea to pass back a real status object with errorcodes, meaningful messages and things of that nature The last thing we should take a look at is the
printEditUserForm() function You'll notice thisline of code:
With this one line we call the other business method
in our EJB (via our EJB client class) called getUser().This method takes a single parameter - our user ID
getUser()returns a WDDX string which deserializesinto a PHP associative array This array contains all ofour columns in our database with the values based onthe user ID we passed into our method
There, was that so bad? We went through all of theimportant bits of code to illustrate how we separate ourapplication into logical tiers I hope you noticed that inour PHP code we did not rely on database calls or per-form any business logic Our PHP code just carried outthe task of preparing, sending and displaying data.Something I also hope you noticed with this smallexample is how our application code can directly map
to a requirements document In any major applicationdevelopment project, requirements and design docu-ments play a very large role in the actual project Infact I'd go so far as to say that they may be one of themost important components of a project Using an n-tiered architecture, whoever is wearing the projectmanager's hat can make dividing up the tasks amongstthe specialists more clear, and can produce real esti-mates on the effort required to build each component
Of course this small example hardly scrapes the face of what is possible and it only really describes onemethod of implementation for an n-tiered architecture.There are other technologies and protocols availablelike SOAP and XML-RPC that can be used to divide yourapplication into the multiple tiers
sur-So, leave the kitchen sink right where it is - you don'tneed it in your code Keep your presentation code free
of business logic which, in turn, should be kept free ofyour data access code You'll be happier, accomplishmore and be admired by peers!
$userHash = wddx_deserialize (
$java_obj -> getUser ( $uid )
);
$status = $java_obj -> saveUser ( $packet );
$packet = wddx_serialize_vars ( "username" ,
"password" , "firstname" , "lastname" ,
"email" , "user_id" );
for ( $i = 0 ; $i < count ( $user_array ); $i ++)
{
$uid = $user_array [ $i ][ "user_id" ];
$username = $user_array [ $i ][ "username" ];
echo '<option value="' $uid '">'
$username '</option>' ; }
php|a
Dave is a professional geek specializing in java/j2ee, php (naturally), perl development which is just a cover for his real passion for spending large sums of money on home recording and musical equipment and general-
ly making a nuisance of himself it should also be noted that his / karma
is currently "positive" which will surely fall.
Trang 32In general, you could say that the purpose of a
tem-plate engine is to bring certain dynamic content into a
flexible, predefined design framework The template
engine we will implement later on in this article will
replace substitution symbols in preformatted HTML
documents with content delivered by PHP scripts This
may sound a little bit unspectacular, but the engine is
quite smart and has a few other useful features It
doesn’t matter if your content consists of a single word
or a whole list of datasets with several rows each Even
arbitrary interlocked datasets can be used to feed a
template In addition, SSIs (server side includes) will be
processed automatically, even if the web server the
script is running on is not capable of processing SSIs
Clean Up Your Code!
There are several good reasons for using a template
engine Probably the most apparent is that it results in
clean and tidy code While one of the greatest
advan-tages of PHP is the ability to embed the PHP source
right into your HTML documents, this mixture of
pro-gramming and formatting languages is also one of the
greatest disadvantages Eventually, the code becomes
impossible to debug and maintain, and as the tion grows larger it begins to look more and more like
applica-‘spaghetti-code’ In addition, if you work on a teamwhere logic and design teams work separately, coordi-nation efforts become quite troublesome
If you’ve ever created large-scale applications withyour PHP code interspersed amongst your HTML,you’re probably well aware of the tremendous effortinvolved in trying to decipher what you or (evenworse) someone else has written; ‘if’ loops are frag-mented by hundreds of lines of HTML code that’s beenwedged between the ‘if’ and ‘else’ statements; just asdisconcerting, every line of HTML seems to have somesmall PHP snippet hidden within These are the night-mares of every PHP programmer tasked with the main-tenance of such “spaghetti-code”, even if it was youwho implemented it in the first place! Thus, in order tosave your soul from this living hell, the pragmatic PHPprogrammer really should be armed with some way ofcreating cleaner, more maintainable, non-nightmareinducing code
develop-started in creating an engine of your own to meet the unique needs of any project.
PHP Version: 4.0 and Above O/S: Any
Additional Software: N/A REQUIREMENTS
Trang 33Creating a Customized Template-Engine
Using templates can help put an end to this madness
by strictly separating PHP (logic) from HTML (design)
Your code, now free of the extra HTML baggage, will
look more tidy and will be much easier to understand
But wait! There’s more! The separation of logic and
design enables you to easily share work within a team
PHP programmers can focus on their code without
worrying about how to make the output look nice,
while the HTML programmers can design complex
lay-outs without having to understand how the content is
created And there was much rejoicing (yay)
Seems Logical, But How
Does It Work?
Substitution symbols are positioned within the HTML
document to be used as placeholders for the dynamic
content, to be delivered later by PHP In this article, I
will use the term ‘tags’ rather than ‘substitution
sym-bols’, simply because the term tag sounds more
famil-iar to programmers (it’s also shorter) Whatever youdecide to call them, just remember that they will bereplaced with dynamic content by the templateengine
Once you’ve decided to take the plunge into using atemplate-driven development model, several agree-ments between the template designers and the PHPcoders have to be made The most important areas tofocus on are:
- which template tags are needed to integrate the necessary content?
- which HTML elements (e.g dropdown fields or radio buttons), if any, are dependent on PHP code?
- how will form elements later referenced by PHP form processing scripts be named?
Figure 1