FreeTrade:
A PHP-Based E-Commerce Solution
php|architect
Departments Features
7 NEW STUFF
19 FreeTrade, e-commerce for
70 BOOK REVIEWS
PHP Professional Projects
Professional PHP Web Services 49 Exploring XSLT Processing Options
Within PHP
by Stuart Herbert
72 exit(0);
Let Me Throw The First Stone
Visit www.zend.com
for evaluation version and ROI calculator
Technologies Ltd.
EDITORIAL
EDITORIAL RANTS
Awwww Yeah....
php|architect
These were the first words I uttered after accept- Volume II - Issue 3
ing an invitation to take the reins as editor-in-chief March, 2003
for php|architect magazine. About 3 weeks later,
Marco, our fearless publisher, reminded me that I
still had to write the Editors Rants aritcle. This is Publisher
essentially what you see at the beginning of seem- Marco Tabini
ingly every magazine ever published. Letter from
the Editor, From the Editors Desk. Whatever
you want to call it its all the same and as far Editor-in-Chief
as I can tell, its all pretty meaningless. Brian K. Jones
Over the past few weeks Ive read no fewer than brian@phparch.com
30 of these articles, trying to get a clue as to this
articles purpose in life. I read magazines covering
every conceivable topic, formal and informal, Editorial Team
from the politically perfect to the underground, Arbi Arzoumani
grass-roots publications and found that these edi-
editorial precision with technical savvy, I will say the php|architect website for more details.
that this process and this accomplishment both
fall under the heading of non-trivial tasks. The Longer Term
Certainly a very large thank you is in order for
each of the many authors who collaborate with Looking out and attempting to predict our
our editorial staff each month. Working together, future at such an early stage, while fun, is proba-
we have been able to overcome challenges rang- bly also an exercise in futility. All that can be said
ing from differences in opinion to differences in for sure is that there are plans of great size and
time zone, culture, and even language. Their time, great number. More huge ideas are born every
patience, and hard work is very much appreciated. day. Surprisingly, only some of the ideas belong to
Second, php|architect continues to make great us staffers. The rest come from you!
strides in establishing itself as a voice for the PHP So far, most of the changes and adjustments
developer community, as well as an advocate for weve made, and some which were working on,
the deployment, evolution, and progress of the have come directly from our readers. Were all
PHP platform. We havent sought to glorify the constantly monitoring emails, looking in the
state of PHP, nor to shun its more proprietary php|architect forums, and even monitoring the
peers. Instead, we try to maintain a realistic focus PHP mailing lists in search of yet another unful-
on the use of PHP in production environments. filled need that we might be able to lend a hand
side hacking attacks that could result in the execu- (US). More information is
tion of arbitrary PHP code. available from the Zend
For more information, visit website at
http://ca.php.net/release_4_3_1.php http://www.zend.com.
TUTOS
The Ultimate Team Organization Software
REVIEW
By Marco Tabini
Figure 1
Figure 2
By Jayesh Jain
Introduction
- The CLI starts up in quiet mode by default,
With the introduction of version 4.2, PHP started sup- though the -q switch is kept for compatibility so
porting a new SAPI (Server Application Programming that you can use older CGI scripts.
Interface) called CLI (Command Line Interface). This
facility was introduced to help developers create small - The CLI does not change the working directory
shell applications with PHP that have no dependencies to that of the script. (-C switch kept for compati-
on a web server. bility)
In version 4.2.0, the CLI SAPI was experimental, and
had to be explicitly enabled using the enable-cli - Three words: Plain text errors! (no HTML format-
option when running ./configure. However, with ting).
PHP 4.3.0, the CLI SAPI has been deemed stable and is
therefore enabled by default. It can be explicitly dis- In this article, well discuss how to use PHPs CLI fea-
abled by specifying the disable-cli option to ture to exploit the power of PHP from the command
./configure. line. Well assume that you have a fair understanding
Though it was technically always possible to create of PHP and that PHP is installed and working properly
independent shell-style scripts with PHP using a stand- on your computer. Most of the examples in this tutori-
alone CGI interpreter, there are a few things that make al were tested on a Windows platform (w2k, to be pre-
the new CLI SAPI an especially attractive and unique cise), but should work unaltered on a Linux box.
tool:
The term PHP shell script can cause some confusion Lets start with a small script (the most familiar one)
for those who are used to traditional UNIX-style shell which simply prints the words Hello World to the
scripts. The reason for the confusion is that PHP, strict- screen. Using your favorite text editor, create a text file
ly speaking, does not provide a traditional interactive called world.php in your PHP folder and enter the fol-
environment for command execution. Another source lowing text.
of confusion is the fact that the name of the SAPI CLI
is also an acronym used to refer to a UNIX shell, which <?php
by definition is an interactive command execution envi- echo "Hello World\n";
ronment! Lets clarify this right now by simply stating ?>
that the PHP CLI is an interface to a PHP interpreter that
can be accessed via the command line - not an interac-
tive shell. In reality, PHP shell scripts are just PHP Save the file, ensure that you have the PHP CLI exe-
scripts that can be run from a command line or a cron cutable in your path, and run the following command
job (which will be discussed later in the article) in the
> php world.php
same fashion as a shell or PERL script.
A normal shell script consists of two main parts: the
very first line, which indicates the interpreter that Surprised to see the output, Hello World in the com-
mand prompt instead of the web browser? Welcome
PHP 4.3.0 (cgi-fcgi), Copyright (c) Will output Hello World, the same exact message as
1997-2002 The PHP Group our earlier example. This is fine for small bits of code
Zend Engine v1.3.0, Copyright (c) 1998- you only want to execute once. Only as the code gets
2002 Zend Technologies larger will you need the power of a script.
This would indicate that the php.exe file on my You can redirect the output from any script to a file
machine in the php root folder is actually the old CGI. by running:
For the reasons mentioned earlier comparing the CGI
> php world.php > outputfile
and CLI interpreters, and because the title of this article
says CLI in it and not CGI, Ill be refraining from
using the CGI in the examples going forward. I just Linux and UNIX users can also redirect the script out-
wanted to point out a possible point of confusion put to another command by using the | (pipe opera-
here... so on we go! tor). For example:
Getting Interactive
> php world.php | wc -w
PHP has always made it very easy to interact and trade
Will return the word count of the output (in this case, data with a user via the traditional browser interface.
it will output the number 2). Lets have a look at how PHPs stream functions and
Conversely, you can also send output from some associated constants can extend this ease to the com-
application or command to the php interpreter by mand line interface. There are three streams available
using the pipe operator, for example: in PHP CLI. If youre familiar with the corresponding
standard UNIX device names, youll be right at home
> someapp | php here, as these streams emulate the same functionality.
<?
- Shell scripts can take input from, This time, well demonstrate how to use an input
and send output to a user via stream. It will accept an input from the user, wait for
STDIN/STDOUT, a regular text file, the user to press the Enter key and then display the
or even another command. In other entered text.
words, theyre very flexible.
<?
$stdin = fopen('php://stdin', 'r');
- Shell scripts are a quick and dirty echo "Please Enter your Name: ";
way to create your own command- $mystr = fgets($stdin,100);
line tools and applications. echo "Your Name Is :\n";
echo $mystr;
fclose($stdin);
- If you already use PHP for web ?>
development, why learn another
language to write shell scripts? The following example shows you how to output text
to an error stream.
- Shell scripts are commonly used to
automate day-to-day administration
tasks.
Figure 1
<?
$stderr = fopen('php://stderr', 'w');
fwrite($stderr,"There was an Error"); Constant Details
fclose($stderr);
?>
STDIN
To make accessing and moving data around in a shell An already opened stream to stdin. You dont
environment simpler, PHP has added the following have to open it with:
constants. Again, for UNIX users, these names should
look familiar. In UNIX, these typically map to the key- $stdin = fopen('php://stdin', 'r');
board (STDIN) and the screen (STDOUT and STDERR)
by default. STDOUT
An already opened stream to stdout. You dont
Using Arguments in Scripts have to open it with:
Anyone who has experience writing shell or PERL $stdout = fopen('php://stdout', 'w');
scripts would probably consider the PHP CLI complete-
ly useless if the scripts werent able to handle argu- STDERR
ments passed to it from the command line. The CLI An already opened stream to stderr. You dont
handles this with the use of the $argv and $argc vari-
<?
echo "Total argument passed are: $argc\n"; For users of version 4.2, youll need to add these addition-
al lines to the top of your script in order for the above
for( $i = 0 ; $i <= $argc 1 ; $i++) example to work:
{
echo "Argument $i : $argv[$i] \n"; define('STDIN',fopen("php://stdin","r"));
} define('STDOUT',fopen("php://stdout","w")
?> define('STDERR',fopen("php://stderr","w")
Figure 2
Assuming this is stored in a file argument.php you Also, dont forget to add the PHP tags in the script
could test this script by running: file, otherwise PHP will not interpret it properly. If
youre stuck with the CGI version and want to suppress
> php argument.php arg1 arg2 the HTTP headers, use #!/usr/bin/php -q.
Similarly, you can also use any other PHP arguments.
Refer to Figure 2 for
sample output Scheduling PHP Scripts
Important : You can use $argc and $argv in the man- PHP scripts can be scheduled to run automatically with
ner described above only if you have both the regis- the help of cron. Cron is the name of the standard
ter_globals and register_argc_argv settings in execution scheduling mechanism that enables UNIX
php.ini set to on. As of PHP version 4.3, regis- users to execute commands or scripts automatically at
ter_globals is set to off by default. You should do some regular interval. A common use for it is to back-
your best to write your scripts so that they do not require
up all of the file on the server, do some database
register_globals to be on, to avoid possible security issues
cleanup, or send emails to administrators about the
in your incoming form variables. You can still use $argv
state of the system. Try typing man cron or man
and $argc if register_globals is set to off. Just
use the following code: crontab on your Linux system to learn more about
how to get your PHP scripts to run at regular intervals.
$argc = $_SERVER['argc'];
This can be an extremely valuable tool to developers
> ./testscript.php
Refer to Figure 3 You can also register files with extension .php3 or
.php4 in the same fashion mentioned above.
Select the PHP entry in the Registered File Types list
box, click the Advanced button, click new and type More Information
Run in the Action box. In the Application Used to
Perform Actions box, type C:\PHP\PHP.exe %1 There are certain php.ini directives, which are over-
%* (change the PHP path if its different on your ridden by the CLI SAPI because they do not make sense
machine. Note that %* is used to send any command in shell environments:
line arguments). Click OK, OK again and then the
Close button. Your Windows machine is now config- a) html_errors = FALSE
ured to run PHP Scripts. Just double click on any PHP As the output of the PHP CLI does not go to a brows-
file in Windows Explorer to run it. er, there is no need to echo HTML tags hence this direc-
tive defaults to FALSE.
Refer to Figure 4
Figure 3
Figure 4
FreeTrade, e-c
commerce
for developers
FEATURES
By Vladan Zirojevic
A package aimed at the developer, FreeTrade offers a cost-effective yet robust framework for creating your next online
These requirements are not too strict, but some of er. These components can be laid out in the layout file
them do exclude a number of the solutions out there. using HTML tables, div tags, or any other means. Note
After searching, configuring, testing, customizing, and that none of the components of a layout are hardcod-
a good many sleepless nights, I believe that I have ed. They are just included into it with a simple
found a good, although not well-known, solution for a include(). Each component is saved in a separate
developer. file. The code making up each of the navigation, head-
FreeTrade is a fully-featured and highly configurable er and footer components is kept in the navigation
PHP script for creating and maintaing e-commerce Web module directory.
applications. FreeTrade is not a very well-known script, The content component (or screen) is kept in a file in
and there are a few reasons for this. For example, it the screen module directory. A screen may be pure
does not have its own domain name, the demo store is HTML or PHP, but the screen file never performs any
very poorly designed , and FreeTrade uses a different action past showing page content. Listing 1 lists the
(and, at first glance, strange) development model code for an example screen showing a user login page.
called FreeEnergy. This example login screen script would reside in the
login file in the modules/screen directory. Module
FreeEnergy files have no file extension (like .php) because they are
to be included, not executed. I will stay focused on this
FreeEnergy is not a new concept in PHP develop- example and explain a few things.
ment, but it is also not a widely used one. I am sure FreeEnergy has a general module, called utility, which
Listing 1
1 <?php
2
3 /*
4 ** File: login
5 ** Description: form for logging in
6 */
7
8 /*
9 ** Login Form
10 */
11
12 print(StartForm("contents", 'post', 'LOGIN_USER', TRUE, '', '', '', 'loginForm'));
13
14 startTable();
15
16 printEditRow(localize('Name'), "inputLogin", "", 32, 255);
17 printEditRow(localize('Password'), "inputPassword", "", 32, 255, "password");
18 printSubmit(localize('Login'));
19
20 endTable();
21
22 endForm();
23
ACTION form variable, from the script which requested There are a few things which may confuse you if you
the page, names a file in the modules/action direc- are new. Some of them are related to FreeTrade, while
tory to be included. This script contains the action to some are related to e-commerce programming in gen-
take on submission of the form. For index.php, the eral. I will try to clear things up and save you some
action is like a black box. We include the requested time.
action and receive the results (or error message) from it First, let me explain the FreeTrade nomenclature and
in $ActionResults. how an online store basically works. FreeTrade calls
The action usually has several steps, and all of them your online shop a store. A store may have many dif-
must be successfully completed. FreeTrade uses an ferent departments and subdepartments. For exam-
interesting technique to process these steps. Instead of ple, you might have two departments - one called
using nested ifs and ending up with highly nested Books, and another called Music. Each department
and hard-to-read code, it uses a nice feature of PHP4s can contain subdepartments and products. By default,
include() statement. there is a department called Root. All store depart-
In PHP4 a file that has ments are its subdepart-
been included can prema-
turely exit and return a value
FreeTrade is a fully-featured ments. You can place prod-
ucts in the Root department,
with a return() state- and highly configurable PHP too.
ment, like a function (this is A product is called an item
valid for PHP4+ only; PHP3 script for creating and main- in FreeTrade. A store user (a
taining e-commerce Web appli-
acceptable and the shopper confirms the order, able to use a third-party credit card processor, you
FreeTrade will save it into the database. could store the credit card information in the database
for a day or two until you process the order. At that
Extending FreeTrade point, you can mask all but the last 3 or 4 of the credit
card number digits, or you could just delete the credit
FreeTrade is meant for developers. It is very extensi- card information. I will give an example of how to
ble and flexible. The following is a practical example of make this work using MySQL.
how easy it is to extend the FreeTrade system to meet First, open the
your specific needs. modules/database/mysql/invoice file and add
By default, FreeTrade stores credit card information in the function in Listing 2.
the database table invoice_billing for each individual Now make a new file,
order. This is a problem, in my opinion, even when modules/action/CLEAN_INVOICE_CC, containing
using dedicated servers. Redundant data in a database the code from Listing 3.
is generally never good news, if not for reasons of effi- Finally, add a button for credit card cleaning in the
ciency, than for the problems data redundancy can modules/screen/edit_invoice file with the fol-
cause in the area of maintaining data integrity. There lowing:
are a few ways to avoid this problem. The best way is
to use a third-party real-time credit card processor and print(StartForm(
not collect credit card numbers at all. If you are not "edit_invoice",
Listing 3
1 <?php
2 /*
3 ** File: CLEAN_INVOICE_CC
4 ** Description: removes credit card billing record for an invoice
5 */
6
7 include_once(DATABASE_MODULE . "invoice");
8
9 $_REQUEST['invoice_ID'] = (integer)$_REQUEST['invoice_ID'];
10
11 if(!cleanInvoiceCreditCard($_REQUEST['invoice_ID'], $error))
12 {
13 $ActionResults[] = $error;
14 return(FALSE);
15 }
16
17 ?>
processors documentation and change the tion. If you want a well-writen script, with lot of features
modules/action/SUBMIT_ORDER file. and customization possibilities, give it a try.
Wrapping Up
About The Author ?>
There are a few things I would like to see included in
Vladan Zirojevic is a Serbian web developer, educated in Computer
FreeTrades future versions; for instance, better documen-
Science. He worked on more than 30 various PHP projects both as proj-
tation, modules for credit card processing, better search ect leader and part of the team. Some of them www.24sata.com,
functions, better reports, bulk import solution, and an www.poljubac.com, www.trebinje.com, www.mobilnimagazin.com...
image upload function. However, I do find FreeTrade to Currently, he is employed as a Senior Web Developer in SEENETIX,
be a usable product for developers in its current state. Belgrade. He can be reached at: vladan@webmaster.co.yu
FreeTrade is a great Open Source product, but its not
Click HERE To Discuss This Article
for everyone. It is a framework, not a plug-and-play solu- https://www.phparch.com/discuss/viewforum.php?f=7
A few words with Leon Atkinson Pixels (www.smashingpixels.com) who did the graphical
design work.
Leon Atkinson (http://www.leonatkinson.com), author of
FreeTrade have been a big fan of PHP and MySQL. What he
A great example no longer viewable is Restoration
is best known for is the book Core PHP Programming, first
Hardware. This site grew so successful, it outgrew FT. Its the
Live
PHP is an Open Source
PHP! (for three days)
scripting language with serious
technical muscle. No wonder its the
Meet and mingle with the experts during two conference days
phpLens
Published by Natsoft
REVIEW
editing modes. The standard mode refers to editing a full authentication system. This is left to the develop-
records one-per-page. Hot editing refers to a er to implement using their own choice of tools, such
method where multiple records can be modified at the as Smarty.
same time using an interface similar to that of a typical Finally, the phpLens documentation includes a step-
electronic spreadsheet. The data editing engine auto- by-step procedure for securing the folder in which
matically recognizes the data type of each field, includ- phpLens resides, without impeding its functionality.
ing enumerative types (managed through drop-down
lists). Its also possible to specify very complex relation- Documentation and Support
ships between tables.
phpLens comes with an excellent set of user documen-
Security Features tation. By user I actually mean developer, since
phpLens doesnt force its adopter to utilize a particular
phpLens offers both simple and sophisticated security end-user interface.
features. Some of the simple features include the abil- The entire documentation set is available online. It
ity to password-protect the dynamic editing functions, follows a very natural path, from installation all the way
and to automatically filter user input for potential dan- down to the smallest security details. In addition, the
gerous HTML and SQL statements. phpLens website includes a complete reference of all
One of the more sophisticated features is the check- the objects, properties and methods used by the pack-
summing of records to ensure that the data is not trans- age.
Figure 1
Figure 2
Blazing Site
Performance Using
Objects and Sessions
FEATURES
By Peter Moulding
Databases store rows in pages. Pages are chunks of the object is deserialized out of the session. If we can
disk, usually 4KB long. If your session data is 50 bytes minimize the amount of code that needs to be loaded
long, a page stores 80 rows. If your object blows the and compiled in order for an object to be deserialized,
session data out to 2KB, a page stores just 2 rows. we gain efficiency.
Databases are more space efficient than files. To this end, I prefer to split code into a structure
However, from a performance perspective, a page write based on usage. One block is the code used at the
is the same as a file block write, so a database should start, then a block used in the middle and, finally, a
not slow down your sessions. block used at the end. It is a bit like splitting a web page
MySQL is slower than files on some systems and a lit- into header, body and footer, or a file access operation
tle faster than files on other systems, but generally there into open, read and close. This approach is a good first
should be almost no measurable difference between a step towards cutting large blocks of code into small,
50 byte session row and a 2KB session row. manageable chunks, and has the added benefit of
Furthermore, the time difference is linear, which means building memory efficient objects. When thinking
that adding an extra object produces little difference. about storing objects in sessions, memory usage effi-
Although MySQL lets you choose from three different ciency also means session usage efficiency.
table types, the default native table is the best choice as PHP classes offer a class constructor to perform the
it has no transaction processing overhead. initial work to be performed by the class. Unfortunately,
Oracle is different. Oracle has 4KB text fields, so any- the constructor code remains with the class throughout
thing larger has to go into a CLOB (Character Large its life. If our constructor code is huge, we can consid-
I would like to show you a full content management objective_html is the base class for all of our
system, but the code listing would flood this magazine other HTML classes. It provides a common $html vari-
and squeeze out the interesting stuff! The following able and the get_html() method. The class is stored
examples represent a real set of code that reads XML in a file named objective_html.class in the sites
and database sources to build page content, and are include directory and is shown in Listing 1.
minimal examples I use when teaching PHP. The next few classes are derived from the objec-
In actual web sites, the code builds input from many tive_html class and are shown in Listing 2 through
sources, and the initial class constructor grows into 6.
multiple includes, wrapped in miles of logic. Individual The objective_foot class includes all the previ-
inclusions can have thousands of lines of code which ous classes in one big constructor and is shown in
find, read and decode input. For this discussion, all we Listing 7.
need are a few inclusions with a sample line of code in The Result
each.
Lets pretend we have the task of creating a common Listing 8 ties it all together. The image in Figure 1
footer for all the web pages at petermoulding.com and shows the fruits of our labor. This might seem like a lot
we are told to use existing formatting classes. This of work for this small result, but remember that the
footer is a copyright notice centered on a blue back- examples are representative of code delivering a whole
web page constructed from 30 or more sources. Getting Objects into the Session
Now lets see what the code looks like when we apply
the optimizations we talked about earlier. The objec- When you manually start the session in your code
tive_foot_start class, shown in Listing 9, contains with session_start(), placing objects in the ses-
all of the constructor code that can been removed from sion is easy. On your first page, you can use the follow-
the objective_foot class. If any of the code in this ing code to create an objective_foot object in the
class prevents your optimizer from caching the com- session.
piled code, you will lose caching on only one page (the
first one). require_once('objective_foot.class');
Listing 10 shows the objective_foot class with all session_start();
$_SESSION['foot'] = new objective_foot();
the constructor code replaced by one print $_SESSION['foot']->get_html();
require_once(), including the
objective_foot_start class. When this class is
compiled for your second and subsequent pages, the On the first page, the require_once() and the
compilation time is reduced and there is more chance session_start() can go in any order. At the end of
your optimizer can cache this simple class. the first page, PHP will run $_SESSION[foot]
Now, lets see how to put these objects into the ses- through serialize() to produce a string for storage
sion. in the session record.
Life is different on the second and subsequent pages.
The session_start() on the second page will grab further to solve the problem of including unnecessary
the string from the session record and run the string classes on every page.
through unserialize() to recreate the object in the Close your eyes and visualize a complete, perfect
$_SESSION[foot] variable.. Remember that content management system written to do absolutely
objects require code, and code is not stored in serial- everything you want (and everything you will ever
ized objects. The unserialize() function has to read want). The code is optimized to include the bare mini-
the objects class code and add the code back to the mum number of classes on every page. The trouble is
object, which means that you have to be sure to that the bare minimum includes hundreds of classes,
include the class before using session_start(). This with most classes used only on a few pages. In front of
works: your session_start() are 200 lines of
require_once(). This would normally be quite a
require_once('objective_foot.class'); problem with automatically started sessions.
session_start(); Here is a way to prevent including every class on
print $_SESSION['foot']->get_html();
every page which also solves the problem of
session_start() happening before your code gets
but this does not work: a chance to include any classes.
On your first page, write:
session_start();
require_once('objective_foot.class'); require_once('objective_foot.class');
On your second page, write: could populate your session with variables like:
require_once('objective_foot.class'); $_SESSION['foot']['database']
$foot = unserialize($_SESSION['foot']); $_SESSION['foot']['text']
$_SESSION['foot']['xml']
The pages performing calculations can pass the pi When Size is Important
object into calc via calcs constructor.
After reading this article, you are ready to attack your
require_once('calc.class'); code and push all your objects into sessions, but
require_once('pi.class'); remember the 4 or 8KB disk block size I mentioned ear-
$calc = new calc($_SESSION['pi']);
lier. Use that size as an arbitrary limit to curb your
enthusiasm. I sometimes put a 10 MB string into a ses-
This approach fits a site with many discrete values sion to pass the string from one page to another, but I
shared over all pages. The value of this approach do not leave the 10 MB in the session, since that would
increases if each data item requires complex and slow down every page. Here are some guidelines you
unique code to access the data. On a commercial site, can start with to loosely govern the space consumed by
you might use this approach when you have to retrieve objects in sessions so you can keep your sessions light.
a currency conversion rate from one source, and a com- Place the following code in a test page.
modity price from another site. You might want to get
the current rate when a person logs on, but then keep <?php
ADOdb and other PHP software products aim to give You can see that one byte is used for the variable
you a level of abstraction between your code and the name. Clearly you do not want to give your frequently
rest of the world. ADOdbs aim is to free you from writ- session-stored variables long names.
ing code specific to a database. Most abstractions Place the same variable into a class and look at the
struggle with configuration issues. In the database area, result. Listing 11 shows a test class and the object cre-
MySQL and PostgreSQL use standard dates, while ation.
Oracle uses something different. To deal with this, you Below you can see the 46 byte string result from the
are faced with a few options. You could write PHP code sessions file. The class name and the variable name take
to format your dates for a specific database, use up space, so keep both names short.
ADOdbs special date functions, or use a configuration
option to make Oracle use a modern date format. How test|O:10:test_class:1:{s:1:x;s:4:d
can objects stored in the session help? ata;}
The date format string in ADOdb is a prime target for
a small, frequently used data object that you can set You can make your code as elaborate, or weird, as
once and then load into a session. Your database name you like because the code does not take up space in the
and other configuration details could also go in the session. Listing 12 shows a class with an unnecessarily
same object. The advantage increases when individual long bit of code in the middle. The class is followed by
users have separate requirements. As soon as your web the object creation.
site goes international you will get visitors using coun- The code produced the following string in the session
try specific formats for dates, times, currencies and file. Note that none of the literal values or work fields
postal codes. All of these items fit the object-in-session use space in the session.
ideal of small size, frequent use, and specificity to each
user. t|O:1:t:1:{s:1:x;s:4:aaaa;}
Some data items, however, are just distractions. A vis-
itors country code will be useless if your site has no OK, You Can Add Code
country-specific code. In order to use these little data
objects, look for items that are used after the user logs The previous examples feature mainly data in the
on, and items shared among software. If the database objects stored in the session. What can you do if you
name is only ever used by ADOdb, let ADOdb handle have really slow code access, do not have a code opti-
On subsequent pages you must create the class Listing 12: More complex object
before you access the object, so use the following code serialization example
before you access the object.
1 <?php
2
eval($_SESSION['c_class']); 3 session_start();
4
5 class t
Listing 11: Simple object serialization example 6 {
7 var $x;
1 <?php 8 function t()
2 9 {
3 session_start(); 10 $z = '';
4 class test_class 11 for($i = 1; $i <= 4; $i++)
5 { 12 {
6 var $x = 'data'; 13 $z .= 'a';
7 14 }
8 function test_class() 15 $this->x = $z;
9 { 16 }
10 } 17
11 } 18 }
12 19
13 $_SESSION['test'] = new test_class(); 20 $_SESSION['t'] = new t();
14 21
15 ?> 22 ?>
thing is constant: O is greater than R. Opening a file the first files to have their directory cached. You can
costs more than reading a block because the operating place all your classes in the session without even the
system has to find the file, check access privileges and overhead of opening a class collection file.
sometimes log the open. File opens are the curse of Some ISPs have fast session file access but pathetical-
object oriented programming. ly slow access to libraries and databases. You can get
If you did not have file opens you could place every your classes and objects to the front of the access
class in a unique file of the same name. Your objec- queue by placing both in the session record. Of course,
tive_foot class would go in a better approach is to change your ISP. The best
objective_foot.class. PHP could have a php.ini approach is to try this technique first, list your coding
setting that says to include class foot from directory accomplishment on your resume, then change your
/classes/, another to tell PHP you are using the exten- ISP.
sion .class, and another to tell PHP that the new opera-
tor should automatically include the class. The code: Conclusion
Writing an RSS
Aggregator With PHP
FEATURES
By Marco Tabini
Weblogs (or blogs, as they are commonly called) have ble for an end user to aggregate them in any meaning-
rapidly become commonplace on the Internet. Even ful way.
though they started as little more than online journals
and diaries, they have rapidly become everyones news XML To The Rescue!
and editorial outlets. Many people have their own
favorite blogs that they visit on a daily basis looking At the end of 1999, Netscape needed a format to dis-
for interesting news bits, opinions, funny or insightful tribute information about the news channels that
stories, and so on. their browser then supported. They came up with an
Possibly the most significant feature of blogs, howev- XML system based on (and compatible with) the
er, is the concept of a newsfeed. A newsfeed is a data Resource Definition Format (RDF) created and main-
file that contains information about the articles pub- tained by the W3C, and called it RDF Site Summary
lished by a blogs authorsort of a ticker edition of (RSS).
the blogs contents that can be picked up remotely and In 2000, weblog pioneer Userland Software picked
provide an at-a-glance overview of what is available on up RSS and greatly enhanced its features, distancing it
it. from RDF (although maintaining the XML angle) and
Newsfeeds are nothing new, really. News organiza- including some of the functionality from Userlands
tions have been using them in one form or another to own scriptingNews format. Although Netscape eventu-
deliver information to their clients for decadesfirst ally abandoned their RSS efforts, Userlands version of
through telex and now through the Internet. Some RSS, now dubbed Rich Site Summary, has been used
organizations, like the infamous PointCast, even used consistently as a means to syndicate a websites con-
newsfeeds to deliver information to the end users desk- tents.
tops. In all these instances, however, newsfeeds were
REQUIREMENTS
delivered on a one-off basis, using proprietary formats
that varied significantly from provider to provider. As PHP Version: 4.1 and Above
such, their usefulness was somewhat limited by the lack O/S: Any
of a common standard that would have made it possi- Additional Software: XML Parsing Extension
My personal opinion of XML is that its the Pokmon into play. An RSS news aggregator is, simply put, an
of computer science (boy, this is sure to earn me some application capable of polling the information syndicat-
flames)I used to think that someone got out of bed ed by an arbitrary number of RSS sources and consoli-
one day and thought: lets take a simple conceptsay, dating it into a single news stream.
comma delimited filesand turn it into a monster so Aggregators have the power to revolutionize the way
complex that we can build a whole industry around it. we access and absorb news from the world that sur-
For a while, XML was hailed as the Next Big Thing and rounds us. Instead of having to continuously scour the
you could find it everywhere, just like Nintendos three- Web looking for news stories, one only needs to access
frame-a-minute cartoons. When I first found out that his news aggregator and have all the information he
RSS was based on XML, therefore, I cringed at what lay needs at his fingertips.
ahead. For me, adopting a news aggregator has meant
Luckily, I was wrong. RSS is an excellent example of spending less time finding news and more time reading
an application for which XML is a perfect choice, given it. Added to the often openly frank and unfiltered
the wide variety of different computer systems that nature of blogs, aggregating news gives me the oppor-
need to use it. Its greatest advantage is its simplicity; tunity to both receive information from my favorite
the contents of an entire website can be easily digested news sources on a daily basis and compare my opinions
into a single RSS file that contains but a few XML ele- with those of other people who share my ideasor
ments, and the code for generating an RSS script is very whose opinions are antipodean to mine.
simple to write in pretty much any language. Unfortunately, my experience with news aggregators
An RSS feed is essentially a simple XML file that contains the following elements:
A Channel specification, which, in turn can contain several sub -elements, such as:
o A Description of the news source
o A Title of the feed
o A Link to the feed's homepage
An arbitrary number of Items, one for each story that the feed carries. Although there is
no preset limit to the number of Item elements in a feed, the specifications recommend
that no more than fifteen be returned. Each item can contain:
o A Title of the item
o A Description
o A Link to the item's referenced page
The RSS Format ture, extracting the information it contains. The parser
then calls several user-provided functions to deal with
The specifications for the RSS format can be found at the contents of the file. Contrary to what many people
http://web.resource.org/rss/1.0/spec. An seem to think, the goal of the parser is not to load an
RSS news feed is, essentially, a simple XML file that, at XML file into memory. The parsers role is only to break
a minimum, contains the elements shown in Figure 1. down a correctly formatted XML stream into its com-
As you can see, the main container element is Channel ponents, thus simplifying the developers life, who is
(a vague reminder of RSS initial purpose), which con- free to concentrate on interpreting its contents.
tains information about the originator of the news. In A parser is instantiated using the xml_parser_cre-
addition, the feed should also contain an arbitrary ate() function, which takes no parameters and
number of Item elements, each of which provides infor- returns a resource that can later be used to reference
mation for a single news story. Although there isnt a the newly created parser. Once its operations are com-
predefined limit to the number of items that can be plete, a parser can be destroyed by passing its associat-
included in a newsfeed, the specifications recommends ed resource as an argument to xml_parser_free().
that no more than fifteen be sent by an originator. The XML parser engine supports many different
A news aggregator works by reading in the XML file options, which can be set using the
from an arbitrary number of feeds (determined by the xml_parser_set_option() function:
user), interpreting its contents and, finally, output them
to the user in an aggregated format. xml_parser_set_option (
xml_set_element_handler (
These five lines of code will open a connection to the resource parser,
php|a website, read the contents of its main page and string element_start_function,
string element_end_function);
output it to the caller. If youre using PHP 4.3 or high-
er, you can even specify HTTPS as your protocol of
choice! The element_start_function and
element_end_function parameters contain the
Parsing XML names of the functions that the parser should execute
when a new element begins and ends respectively. For
My compulsive allergy to XML makes writing a news example:
aggregator in PHP a very pleasant experience. In fact,
PHP features a complete XML-parsing system that can xml_set_element_handler (
be used to effortlessly interpret the contents of even the $parser,
"StartElement"
most complicated XML data stream. "EndElement"
In PHP, XML information is handled by a parser, )
which reads the raw XML input and analyzes its struc-
This would require that StartElement() and Although I wont use this feature in the code Im pre-
EndElement() had been previously declared as fol- senting as part of this article, I should also point out
lows: that, instead of function names, you can also pass an
associative array to xml_set_element_handler()
StartElement ( as the value of either element_start_function or
resource parser, element_end_function. If you do so, whenever the
string name,
parser encounters a particular element, it will call the
array attributes);
function associated with it in the array. For example, if
EndElement ( you pass this array as the value of
resource parser, element_start_function:
string name);
(
A => a_begin,
In both cases, the [parser] and [name] parameters
IMG => img_begin
hold a reference to the calling parser and the name of )
the element that is starting or ending. As far as
StartElement is concerned, the [attributes] parameter the parser will invoke a_begin() whenever it finds
contains an associative array of any attributes that are the element <A> and img_begin() whenever it finds
part of the element declaration. For example, the fol- the element <IMG>.
lowing: The character data contained inside an element is
for each attribute. This happens because the parser will interested in, you could simply send them to yourself in
break down the data whenever it encounters a special a nicely formatted e-mail. Similarly, you could change
character (such as & to indicate an ampersand) get_feed() so that it outputs plain text and sends the
and execute the data handler callback separately every news feeds to your favorite PDA or text-enabled cell
time. phone.
ural way, you may want to build a little interface and, gate feeds via e-mail, you wont even have to do that).
possibly, save your feed list in a database. As I mentioned above, the RSS has revolutionized the
The second problem, on the other hand, only way we take in our news. With its capabilities, PHP is
becomes evident when you start having a long list of the perfect choice for writing an RSS aggregator and,
news feeds (four or five different one should do the hopefully, you will be able to use the code I presented
trick). Because all the feeds are refreshed every time you here in your next project.
execute the script, the aggregator will easily become
About The Author ?>
too slow to be useful if it has to pull data from too
many external sources. A simple solution here would be Marco is the Publisher of (and a frequent contributor to) php|architect.
When not posting bogus bugs to the PHP website just for the heck of it,
to actually pull the data on a fixed schedule, either he can be found trying to hack his computer into submission. You can
through a cron job or a similar method supported by write to him at marcot@phparch.com.
your operating system. You can then store the feeds
directly in a database and pull them out when needed Click HERE To Discuss This Article
https://www.phparch.com/discuss/viewforum.php?f=9
(in fact, if you modify the script to send you the aggre-
Exploring XSLT
Processing Options
Within PHP
FEATURES
By Stuart Herbert
following lines in your php.ini file: content. The advantage is that the look and feel of the
website can be changed over time without having to
Listing 1 change the code that generates the dynamic content.
;;;;;;;;;;;;;;;;;;;;;; One example website that uses this technique is the
; Dynamic Extensions ; Gentoo Linux website http://www.gentoo.org/.
;;;;;;;;;;;;;;;;;;;;;;
; Here, they use XML to publish the same tutorial con-
; If you wish to have an extension loaded tent to the web as HTML, and to other output formats
; automaticly, use the following syntax: such DocBook (see Gentoo Linux).
;
; extension=modulename.extension
Ive created PHP classes that generate an XML
; description of PHP source code. Listing 2 contains an
; For example, on Windows: actual XML document created by my classes. Im inter-
;
; extension=msql.dll
ested in using XSLT to turn the XML into HTML. Listing
; 3 contains the XSLT file I wish to use on the XML doc-
; ... or under UNIX: ument in Listing 2. You can find these listings in the
;
; extension=msql.so
listings folder that comes with your copy of php|archi-
; tect.
; Note that it should be the name of the
; module only; no directory information
; needs to go here. Specify the location
XSLT Processing From PHP
; of the extension with the extension_dir
$args = array ("/_xml" => $xml, Until then, I still need a way of performing XSLT pro-
"/_xsl" => $xsl); cessing using PHP. If PHPs built-in functionality cant
$output = xslt_process($h, "/_xml", be relied upon to do the job (yet), I need to use exter-
"/_xsl", null, $args); nal XSLT processing engines instead.
3. Call xslt_free() to release the handle to Calling Other XSLT Processor Engines
the XSLT processor. The next thing I did was to download a stand-alone
XSLT processor that I could run manually on the com-
xslt_free($h); mand-line. I chose Instant Saxon, available from
http://saxon.sourceforge.net/, mainly
You can use xslt_process() to process XML and because its written by Michael Kay. I use one of
XSLT held in files on disk, strings in memory, or some Michaels books XSLT Programmers Reference from
combination of the two. http://www.wrox.com/books/1861003129.htm
- as my desktop bible on the XSLT standard.
PHP and Sablotron Listing 5, taken from my docXP source code, shows
PHP 4.3.0 only supports one XSLT processing engine - how to call Saxon in this way.
Sablotron. Created by The Ginger Alliance, Sablotron This approach has one very obvious problem. Having
is written in C, and is freely available for both Windows PHP execute a stand-alone XSLT processor is many
and UNIX operating systems. If you are using PHP on times slower than using Sablotron. Theres the over-
Interface (or JNI). The JVM runs inside our PHP A quick read of the Java Extensions documentation in
process. Once loaded, the same virtual the PHP manual is enough to put most people off tak-
machine is re-used time and time again until ing the Extension out for a spin. This part of the other-
our PHP process ends. We can compile in the wise excellent PHP Manual really stands out for being
Java Extension or load it as a shared object difficult to understand, and for a long list of comments
and if we dont use the Java() keyword at all, by PHP users who just cannot get the Extension to
the Extension does nothing. work.
I think that this is a shame. I found it straight forward
The Java Extension then uses Javas reflection to configure the Java Extension (after reading the PHP
capabilities to examine the Java object were source code!), and Sam did a nice job of making the
trying to create. A PHP object (of type java) is Extension as easy to use as possible. I hope this article
created, and given the same functions as the goes a long way to helping other PHP users take full
Java object. advantage of this powerful and practical Extension
and to make sure of it, Ill show you how to configure
We just call the PHP object, and the Java the Java Extension for Windows, and for Linux.
Extension automatically passes everything
through to the JVM and back again. Its worth Configuring the Java Extension for Windows
noting here that all parameters to functions are To use the Java Extension on Windows, you have to cor-
passed by value. Well return to this point later rectly setup a number of configuration options in your
[Java]
java.library = c:\j2sdk1.4.1_01\jre\bin\client\jvm.dll
java.class.path = "c:\php\extensions\php_java.jar;c:\java\jars\saxon-6.5.1\saxon.jar;c:\java\jars\saxon-
6.5.1\saxon-jdom.jar;c:\devel\php\docXP\java"
to use. In JDK 1.4.1-01, which is what Im using to have one, and that you know where it is.
write this article, the DLL containing the JVM is in the If you do not have a copy, it is created in ext/java
jre/bin/client/jvm.dll file on disk. We have to set the when you compile PHP 4.3.0 using the with-java
java.library option to point to the JVM we wish to use. option.
2. java.class.path To use the Java Extension on Linux, you have to cor-
The Java Virtual Machine needs some help in talking rectly setup a number of configuration options in your
to PHP. The Java Extension, written in C, does a lot php.ini file. Ignore what the PHP manual says. You
of the work. The rest of the work has been written in have to setup three options.
Java, and is compiled into the file php_java.jar. By
default, this is in the extensions directory. We have to Php.ini file setting Purpose
add the full path to the php_java.jar file to the
java.class.path option in the php.ini file. Set this to point to the directory con-
extension_dir taining the libphp_java.so PHP exten-
sion.
Remember also to add any other JAR files that you
need!
Add the following line to load the
Although the PHP Manual does mention other php.ini Java Extension.
extension
options, they are not required on Windows to use PHP
4.3.0 with JDK-1.4.1-01. From reading the PHP source extension=java.so
code, it appears that some options are required for sup-
#
4. java.library.path # Should succeed and print out "1"
Under Linux, the Java Virtual Machine #
$result = $stack->pop();
$ex = java_last_exception_get();
5. java.class.path if (!$ex) print "$result\n";
The Java Virtual Machine needs some help in
#
talking to PHP. The Java Extension, written # Should fail - note the "@" eliminates
in C, does a lot of the work. The rest of the # the warning
work has been written in Java, and is com- #
$result=@$stack->pop();
piled into the file php_java.jar. By default,
$ex=java_last_exception_get();
this is in the extensions directory. We have if ($ex) print $ex->toString();
to add the full path to the php_java.jar file
to the java.class.path option in the php.ini #
# Reset last exception
file. #
java_last_exception_clear();
extension_dir = /etc/php4/lib
extension = java.so
; settings for loading the Java Virtual Machine
[java]
java.class.path = /etc/php4/lib/php_java.jar
java.library = /opt/sun-jdk-1.4.1.01/jre/lib/i386/libjava.so
java.library.path = /etc/php4/lib
and we can start figuring out how to call our favourite Introducing The TRaX API
XSLT processor from within PHP.
Recommended reading:
Using The Java Extension In The
Rest Of The Article The latest documentation for the TRaX API can be found at
http://jcp.org/aboutJava/communityprocess/r
eview/jsr063/.
To use the code listed in the rest of the article, youll
need to download and install an XSLT processor written Make sure you get the latest PDF document. The TRaX API
in Java. For this article, I am using Saxon v6.5.2, avail- documented in the original v1.1 standard is not supported by
able from http://saxon.sourceforge.net/. You XSLT processors such as Saxon. I spent several frustrating
hours finding this out the hard way!
need to add the saxon.jar and saxon-jdom.jar JAR files to
the java.class.path option in your php.ini file. Listing 8.
shows what that looks like on my machine.
At this point, we could just dive in, and write a piece Unlike PHP, Java programs consist entirely of classes
of PHP code to drive our favourite XSLT processor. In arranged in a strict hierarchical order called packages.
fact, this is what I did at first. But what happens when Each class must belong to a package.
we want to change XSLT processors? The PHP code Classes in the TRaX API can be found in the
that we would have written would no longer be valid, javax.xml.transform package :
and would need changing. It would be much better if
Java, and Java wouldnt be Java if things werent just a PATH environment variable):
little more complicated than they first appear.
The TransformerFactory is a great fan of java org.gnqs.docXP.jsr63 <XML input
Christopher Lambert films there can be only one! It file> <output file> <XSL template
is a singleton class. Only one TransformerFactory file>
can exist inside the JVM at any one time. This is
achieved by two things: 2. You can call it from PHP, to process files
already on disk. See Listing 12. for an exam-
1. The constructor for ple.
TransformerFactory is package protect-
ed. Only code belonging to 3. You can call it from PHP, to process XML
javax.xml.transform can create a already stored in a string, and get the result
TransformerFactory object. back in a string. See Listing 13. for an
example.
It goes without saying that none of our code
belongs to the javax.xml.transform
package. Run Listing 10. to see what hap- XSLT allows us to transform
pens when you try to create a
TransformerFactory object from PHP. one XML document into on
By Sam Smith
It all started with a bouncing ball. We were really Flash intro class. This short seminar illustrated the ease
excited to get some money from the Youth Sports and with which nice graphics and animation can be imple-
Recreation Commission, a Detroit non-profit, for a mented. However, the instructors also pointed out
new web site. This pilot project was to see if the web how the new Flash MX scripting language,
could help foster inner-city sports activities, and at the ActionScript, had been enhanced to the point that
same time get the kids interested in using the web some of their customers were developing the entire
interactively. The kids could upload photos, keep application, at least on the client side, with Flash and
track of scores, register for events and have a good ActionScript. Some examples were shown, but I
time playing as well. The application would require mainly left wondering if that was just marketing
access to a database, containing tables for players, enthusiasm.
games and events, and a roster that showed players Anyway, the Flash package arrived and I began get-
and events. ting familiar with its animation capabilities (which are
So, wWe were all set to duplicate an earlier project neat and fun). I was also assessing how well
that used PHP server-side scripting and MySQL only ActionScript (AS) could support general client-side
no client scripting at all. The application worked pret- programming and server communication. I was pret-
ty well, and we knew how to do the project quickly. ty impressed, and also pleased that the learning curve
However, it was going to be BOORRRING. How could was not so great since it had similarities to PHP. One
we do something to get the kids attention? small difference, illustrated in the table below, is that
About that time someone was telling me about the The variables do not have a $ in front, so that to
Macromedias new release of Flash MX, and how eas-
ily good animation can be accomplished with this sys- REQUIREMENTS
tem. Ah-hah! I could see it right away a bouncing PHP Version: 4.0.6 and above (4.1 recommended)
ball going across the screen. Now, that would have to Additional Software: Smarty Template Engine
be better than no movement at all. So off I went to a (http://smarty.php.net)
form a string you use. The table compares the syntax used to implement business-class applications that
used in each to perform equivalent tasks: required forms, input fields, database access and so
forth. An example is the reservation system at the
PHP ActionScript Broadmoor center in Colorado (https://www.entery-
ourinformation.com/broadmoor/onescreen.cfm). It
$obj = "ball"; obj = "ball";
turns out that ActionScript has been made very power-
ful, to the degree that you can programmatically insert
$outString = "the $obj outString = "the visual objects onto the screen display rather than place
bounces"; "+obj+" bounces";
all the objects on the screen in using the menu system
that iswhich is also available. This is referred to as
run-time programming of the visual elements under
This syntax permits PHP to intermix strings and vari-
control of your ActionScript, rather thanas opposed to
ables more readily, but this difference is not much of a
design-time layout of the visual components.
problem (except that you forget the $ when going
There are also adequate provisions in ActionScript to
back and forth!). Another tricky area is ActionScripts
develop forms on the client, do local editing of input
rules for variable scoping, where the PHP rules (IMHO)
fields, and other processing to support interaction with
are much more logical and less prone to error. In AS, if
a PHP program running on the server. The way this
you do NOT declare a variable as local it is known to all
works is that values on the screen are, as you would
functions, whereas in PHP you must specifically declare
expect, represented as ActionScript variables. These
a variable as global - far safer. It was weeks into pro-
work, and in each side of the transmission (browser and Response XML document once it is returned
server) an envelope is wrapped around your data at and loaded. There is no wait right here and
the sending end and stripped away at the otherby the do nothing until this finishes command. This
recipient, with some data stream transformations tak- is not a problem as long as you restrict the
ing place along the way. Rather than complicate the user from further input (creating in effect a
story at this point, please see the sidebar section What pause where nothing happens). This asyn-
happens to your XML on the Network at the end. I chronous operation does allow you to let the
found it just about impossible to debug the system user continue on with other activity, but then
without being able to see (with the help of a network it does getgets complicated since you would
Sniffer type device) what was actually being sent back have to keep track of where the user is upon
and forth. For instance, when the XML string is sent receipt of data and whether anything has
from the browser to the server, it goes out as an HTTP occurred that would impact the processing of
POST transfer, and to get the data retrieved in the the received data (eg. you send in an update
PHP code with minimal change, I found that it was eas- on one person and then move to another per-
iest to directly access the $_POST array and re-con- sons record).
struct the incoming XML string from the contents of Once received, the XML object can be manip-
that array. ulated to extract data. This is, admittedly,
However, the benefit of going through this process of tedious, as there is not a really neat way to
sending and receiving the XML message is that you access elements by name. However, this
best to start with an example, and the example is what A decision must be made regarding what to imple-
we are actually using: the XML document for this appli- ment as a TAG (or element, the TAG being the iden-
cation, which we designated with a TAG to identify the tifier of the element) and what to implement as an
entire XML message,: XEBXML. ATTRIBUTE, as you can implement the solution either
First, any XML document consists, like HTML, of Tags way. The first such distinction is the identification of a
and Attributes: Request from a Response. To group this piece of data
along with other fields common to the TRANSACTION,
<TAG Attribute-Name=Attribute-Value> a XEBHDR tag was used, and within this tag several
Data </TAG> attributes are used to define the transaction: RRTYPE is
the Request/Response Type, containing these values:
The <TAG></TAG> combination can be combined RRTYPE=request or RRTYPE=response. Other
into one bracket: <TAG. />. attributes chosen for the header are APPLN, TRANS,
So iIn our case, we are creating a specific XML struc- and TBLSTEP indicating the application sending the
ture for sending database information and commands, document, a transaction code, and a database Table
with the following outer syntax (all the rest of the Name. Within the header is also another tag, XEBIN-
document is between tags): FO, that contains attributes for the operation being
executed (WHERE SQL clause, etc.).
<XEBXML> .. the XEBHDR and XEBDATA To bring all database information together and per-
elements are here.. </XEBXML> mit flexibility of the format for other, possibly non-tab-
Figure 1:
The database columns use as their tag the Note that the XEBINFO is implemented as a single
actual column name, thus the tag for the tag <XEBINFO />, rather than
Email column is <Email>. <XEBINFO>.</XEBINFO>.
Once we get the XML request ready to send to the
Fields (rows within columns) are identified server, which actually happens in response to a user
with the <FLD> tag. interface button or request, both the send and
response are accomplished with the ActionScript code
Consider the following database table, email_list: in Listing 1.
It is important to note that the delay between the
Name Email request and response is indefinite, during which time
the script keeps on running, so during this period you
John john@acme.com need to ask the user to wait or block any user input dur-
ing the wait period. Or, if you are brave or really good
Jane jane@baker.com let her keep typing (which will work but you need to be
cautious)!
Harry harry@acme.com
Then, once the array is filled, moving the data from the resent data from database tables in a consistent man-
array into the database can be done with standard PHP ner. PHP arrays are very flexible, and Ive found that for
routines (module xebDB_cls.php). In this project, database access an Associative Array of Arrays is most
the MySQL database system is used, but the technique convenient. That is, the major array is an associative
is general and in fact the database procedures are array in which the keys are column names, and the
implemented in a PHP class, which would permit value for each key is another array that containscon-
another database to be used within this class without taining one value for that column for each row. In this
changing the surrounding code. scenario, the table referenced above (email_list) would
Lets first look at how we used the PHP arrays to rep- be stored column-major, row-minor, in an associative
function xebxmlRequest_getTable() {
gxpage.fill_bot(Please wait for Event Data);
//Construct the XebXML request and set for initial read
//XebXml is an object, which contains an XML object and
//other stuff; the setHdr and setData methods take parameters
//and put them into the XEBXML request
//getm is the database operation, eevents is the table name
var myxebXml = new XebXml(gxebAppName);
if (success) {
// trace(Response XML - Success true);
if (gxebxmlResp.status != 0) {
trace(Error: Bad XML status+gxebxmlResp.status);
}
var xebxmlResp = gxebxmlResp.childNodes[0];
// the childNodes array contains the elements
if (xebxmlResp.childNodes[0].attributes.RRTYPE == response &&
xebxmlResp.childNodes[0].childNodes[0].attributes.CODE == ok) {
//trace(Well formed xeb);
//this fills and displays the datagrid
populateDG(0);
// normal case - no error
} else {
// not a well-formed XEBXML message
//etc for error processing
}
} else {
// Error - In this case a bad XML load
}
}
/*
* Function: populateDG() this is the display function
*/
array (one entry per column) of arrays (each element of the application, but within the xebxml umbrella a
which is a field, one entry per table row). number of standard transactions are available that take
Ive found it helpful to encode the array structure in care of most needs. These are:
its name, and use the following convention for an
Associative Array (Aa) of Arrays (A). Using this conven- getm Get Multiple Rows
tion, the table above would be represented as: gets Get single Row
add Add a single Row
arrAaATable[Name]= array{John, Jane, upd Update one or more fields in a Row
Harry}; del Delete a Row
arrAaATable[Email]= array{john@acme.com,
jane@baker.com, harry@acme.com};
These transaction codes are implemented in a data-
base access class (listing xebDB_cls.php), which cur-
rently uses MySQL but could use other databases very
There are a number of tools within PHP for handling
readily.
XML documents. For this project, the built-in functions
The results of the access transactions getm and gets
used were the following:
are stored in the associative array of arrays structure
referenced earlier, arrAaATable. This table contains the
$xml_parser = xml_parser_create();
// creates the xml_parser results of the SQL inquiry. To move this data into the
xebxml Response document, the arrAaA2XML func-
that is passed back and forth, you have complete free- coupled with the use of ActionScripts XML Object, you
dom of implementation on either side of the document are pretty far along the way toin having a full solution.
exchange. Finally, by following the conventions used in this article,
Plus, Flash MX is pretty neat, and the latest embodi- which I call XEBXML, your database exchange can be
ment of Macromedia ActionScript is very powerful. It very easily implemented in a straightforward manner.
lacks debugging tools and does not warn you if you call
non-existent variables or functions, so you have to be About The Author ?>
careful. But it appears to be fast, compact, and capa- Sam Smith is a development manager at DataSmith, Inc., and lives in
ble. Grosse Pointe, Michigan. He received his MS in information science from
In summary, I would say that the marriage of Flash Georgia Tech in 1969, which makes him, in his own words, 'ancient' by
MX and PHP is one that will thrive. Without a lot of internet standards. Sam's other main technology interest is protocol
standards.
overhead or needing a comprehensive development
environment (other than the cost of Flash), you can get
a lot done, whether using XML or not. However, with Click HERE To Discuss This Article
https://www.phparch.com/discuss/viewforum.php?f=11
the availability of even minimal XML support in PHP
Let Me Do My Printing! ever portion of your site you want to cache in the out-
put buffering functions and capture their output. This
Annoyed that some functions just output text and can be used to cache elements such as drop down
dont let you capture it into a variable? Me to. If youre boxes that may take a while to create, or for the entire
using a solution such as virtual() or include() page. To cache a dynamic page to a static one, you
and you really need to get the result of that function could use a method such as that shown in Listing 1.
into a variable, how do you do it? Output buffering. That will take a test.php page and cache its output as
Normally when you hear about output buffering, its test.html.
someone telling a newbie to use it to get rid of their
header() errors about the headers already being
sent. While not very useful in that instance, buffering
If you're using Apache...
can be useful in others. By starting an output buffer
before your
you can also make use of
virtual(), include() or even print_r() func- the virtual() function
tion, you can store the contents of the buffer into a
variable and further process it or display it elsewhere. to call scripts that are not
An example of how this can be used is shown below.
PHP, such as PERL.
<?php
//create static page name from .php page name The problem now is that without an extension on our
$file = substr($_SERVER['PHP_SELF'],0,-3).'html'; filename, Apache doesnt know to call the PHP inter-
//open file pointer and write contents preter to parse our file. Add the lines shown below to
$fp = fopen($file,'w'); your Apache configuration, replacing scriptFilename
fwrite($fp, $contents); with the name of the script youve just created:
fclose($fp);
Reload Apache and voila, you will have easy access to ple times. This is a perfectly valid method that may be
any values you wish to pass to your script, and search suited to your application. However, for a solution
engines will quite happily spider away. If all goes well, thats not going to take up additional memory by cre-
the script in Listing 2 will produce the output shown in ating an array (which could become quite sizable for
Figure 1 if called with a URL such as large result sets), you can simply use the
www.yourdomain.com/scriptFilename/another/php/ar mysql_data_seek() function to reset the result set
chitect/tip. back to the first row and cycle through your result set
again.
Figure 1 PHP offers the pg_result_seek() function for
Array PostgreSQL and the mssql_data_seek() function for
( Microsoft SQL that perform the same functionality as
[0] => another the mysql_data_seek() function. Im sure the APIs
[1] => php to other databases offer these functions as well.
[2] => architect Congratulation to James McGlinn and Cesare
[3] => tip DAmico for their tips being selected for publication.
) They will receive a free months subscription to
PHP|Architect! If you have a tip for other PHP
Professionals that cant be found in your common FAQ,
send it in for the chance to win your own subscription.
Resetting Record Sets
For one thing, the case studies do not follow a rather smaller book than the one-thousand
common thread. While this makes for nice and page monsters that publishers constantly try to
independent sections of the book that one can break bookstore shelves with. Believe it or not,
read without being forced to follow a particular this actually comes as a very welcome change as
order, it also limits its overall effectiveness, as far as I am concernednot because it means
there is a certain degree of overlapping at all lev- fewer pages to read for this review, but because
els. it means that the authors (and the publishers)
In addition, the listings are neither formatted have decided to provide their readers with the
for syntax highlighting (something that is very information they actually need.
useful even in a black and white book), and Even though it is only slightly less than five
there is no line numbering. As a result, the read- hundred pages, PPWS takes full advantage of its
er is often left wandering through pages and narrow topic and goes to a very high level of
pages of PHP code without the ability to prop- detail. The book begins with a description of
erly reference them back-and-forth with the what web services are and why (and when) they
remainder of the text. are useful, followed by an overview of XML and
Finally, the case studies make the assumption its role in the world of data interchange.
that register_globals is ona rather common The remaining seven chapters deal with topics
Let Me Throw
The First Stone
By Marco Tabini
exit(0);
As you have probably read on the pages of this issue of php|a, this month were launching a
new grant program for PHP-related projects. Never a person known for his humility, I personal-