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

Tài liệu THE PHP EMPIRE doc

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


Features
8

An Introduction to Drupal
A modular framework for content management
by TITUS BARIK
16

PHP Web Services:
An Introduction to SOAP
Implementing web services with the NuSOAP Library
by ALESSANDRO SFONDRINI
23

Logging and Monitoring with
log4php

A simple way to implement
logging in your applications
by KNUT URDALEN
32

Advanced SQLite Development

A database solution to simplify your code and
help you create high-performance applications
by PETER LAVIN
SPECIAL REPORT
44


Where on the Web is PHP?

PHP Version Tracker Report
by DAMIEN SEGUY
TM
Columns
4 EDITORIAL
6 php|news
50 TEST PATTERN

Stocking Fillers

Year-end book reviews
by MARKUS BAKER
55 SECURITY CORNER
Context

by CHRIS SHIFLETT
60 PRODUCT REVIEW
Zend Studio 5.0
by PETER MacINTYRE
68 exit(0);
Ode to My Keyboard
by MARCO TABINI
If you want to bring a php-related topic to the attention of the professional php community, whether it
is personal research, company software, or anything else, why not write an article for php|architect?
If you would like to contribute, contact us and one of our editors will be happy to help you hone
your idea and turn it into a beautiful article for our magazine. Visit www.phparch.com/writeforus.php
or contact our editorial team at and get started!
Download this month’s code at:



/>CONTENTS
WRITE FOR US!

Volume 4 - Issue 12
Publisher
Marco Tabini
Editor-in-Chief
Sean Coates
Editorial Team
Arbi Arzoumani
Peter MacIntyre
Eddie Peloke

Graphics & Layout
Aleksandar Ilievski

Managing Editor
Emanuela Corso
News Editor
Leslie Hill

Authors
Marcus Baker, Titus Barik, Peter Lavin,
Peter B. MacIntyre, Robert Mark,
Damien Seguy, Alessandro Sfondrini,
Chris Shiflett, Knut Urdalen

php|architect (ISSN 1709-7169) is published

twelve times a year by Marco Tabini & Associates,
Inc., P.O. Box 54526, 1771 Avenue Road, Toronto,
ON M5M 4N5, Canada.
Although all possible care has been placed in
assuring the accuracy of the contents of this
magazine, including all associated source code,
listings and figures, the publisher assumes
no responsibilities with regards of use of the
information contained herein or in all associated
material.
php|architect, php|a, the php|architect logo, Marco
Tabini & Associates, Inc. and the Mta Logo are
trademarks of Marco Tabini & Associates, Inc.
Contact Information:
General mailbox:
Editorial:
Subscriptions:
Sales & advertising:
Technical support:
Printed in Canada
Copyright
©
2003-2005
Marco Tabini & Associates, Inc.
All Rights Reserved
I
f you follow PHP releases, closely, you’ll have noticed that PHP 5.1.0
was released on Thursday November 24, 2005. This release was billed as
paramount in PHP’s history, touted by many core developers as “the first
solid PHP 5 release.”

This supposed banner release was quickly overshadowed on the developers’
mailing list as problematic: a change that was made late in the release candidacy
cycle (a new internal Date class) will break hundreds, if not thousands (or perhaps
hundreds of thousands?) of deployed PHP applications. It was generally accepted
knowledge that new functionality can’t break existing code, but this “knowledge”
proved simply incorrect.
In this case, PEAR has an existing (and well-deployed) Date class of its own. As
you know, PHP doesn’t currently have namespacing, so you obviously cannot have a
Date class in PHP and then declare a second one for PEAR.
Much discussion ensued, including a strong push towards an accepted namespace
standard for PHP (perhaps we’ll see it in the 5.x series, and all signs point to
namespaces in PHP 6 at the latest). The really interesting discussion for me, though
was something along the lines of “why should core care about PEAR?”
Yet another political discussion. It seems that the technical problems are
(relatively) easy to solve, and the real problem is on the social side. So, should PHP
core care about PEAR? Tough call. On one hand core should be given first-rights
to any sort of class, function, variable or constant name. The other side (again) is
social: when most users download and install a package from PEAR, they do so from
pear.php.net. As far as those users are concerned, they’re downloading both PHP
and PEAR from php.net, so they should work together.
Unfortunately, there’s no easy and permanent solution to this problem. However,
Ilia, the 5.1 release manager—and past author for php|architect—wisely reacted
quickly, and on November 28, 2005, PHP 5.1.1 was released, temporarily solving
this problem, by removing the new internal Date class. One growing pain averted,
if only temporarily.
PHP’s integration and many offerings from php.net gives it somewhat of an
“empire” status. This metaphor is further extended when see how PHP has conquered
much of the web in its short lifetime. Tips & Tricks takes a break this month to make
way for a special feature called “Where in the World is PHP?” In this piece, Damien
Seguy shares his company’s findings on how PHP has infiltrated nearly every market,

territory, and size of web application.
This boom is no accident. As you saw last month, PHP is making great strides
in the enterprise, and is shedding its “quick & dirty” reputation. Long live the
dynamically typed variable!
THE
PHP
EMPIRE
EDITORIAL
4 • php|architect • Volume 4 Issue 12

PHP 5.5.1
“The PHP Development Team would like to
announce the immediate release of PHP 5.1.1.
This is a regression correction release aimed at
addressing several issues introduced by PHP
5.1.0, the core changes as follows:
• Native date class is withdrawn
to prevent namespace conflict
with PEAR’s date package.
• Fixed fatal parse error when the last
line of the script is a PHP comment.
• eval() hangs when the code being
evaluated ends with a comment.
• Usage of \{$var} in PHP 5.1.0
resulted in the output of {$var}
instead of the $var variable’s
value enclosed in {}.
• Fixed inconsistency in the format
of PHP_AUTH_DIGEST between
Apache 1 and 2 sapis.\

• Improved safe_mode/open_basedir
checks inside the cURL extension.
Get your hands on the latest release at
php.net!
PHPBase Alpha
Phpbase.org announces their alpha release.
What is it? According to phpbase.org,
“PhpBase is a set of Open Source PHP classes
and functions aimed to help developers
submitting their data to Google Base.
The main purpose for a tool like this is
the need to keep data submissions accurate
and avoid common errors that might occur
when submitting to standard schemes
recommended by Google.
The code still in development, and will be
added to a subversion repository once we get
the project approved at berlios.de.”
Get all the latest info from phpbase.org.
ZEND Studio 5
Zend.com announces their latest release of
the Zend Studio, version 5.
“The product is a full Life Cycle development
solution that allows developers to easily and
more effectively create, test, and deploy their
PHP applications across the enterprise. Zend
Studio 5, the most widely used Integrated
Development Environment for PHP, has
been enhanced with new features to assist
in the development, debugging, testing, and

deployment of PHP applications, including
easy integration with other enterprise
applications.
Available in three editions; Standard,
Professional, and Enterprise, Zend Studio 5
includes support for PHP 5 as well as an easy
switching mechanism allowing users to move
between PHP 4 and PHP 5 for full application
development, and also seamlessly integrates
with Zend Platform 2 to provide a complete
development and deployment solution for
business-critical, PHP-based applications.”
Visit Zend.com to grab the latest release
and check out all the latest features.
OBM-Open Business
Management 1.0.2
OBM is proud to announce the latest release
of their Business Management application
version 1.0.2.
Need a free management application for
your business? Check out OBM. According
to OBM’s site:
“BM is an Intranet application which goal is to
help manage a company or an organization.
6 • php|architect • Volume 4 Issue 12
news
php|architect Releases New Design Patterns Book
We’re proud to announce the release of php|architect’s Guide to PHP Design Patterns, the
latest release in our Nanobook series.
You have probably heard a lot about Design Patterns —a technique that helps you

design rock-solid solutions to practical problems that programmers everywhere encounter
in their day-to-day work. Even though there has been a lot of buzz, however, no-one has
yet come up with a comprehensive resource on design patterns for PHP developers—until
today.
Author Jason E. Sweat’s book php|architect’s Guide to PHP Design Patterns is the first,
comprehensive guide to design patterns designed specifically for the PHP developer. This
book includes coverage of 16 design patterns with a specific eye to their applications in PHP
when building complex web applications, both in PHP 4 and PHP 5 (where appropriate,
sample code for both versions of the language is provided).
For more information, />Looking for a new PHP Extension?
Check out the latest from PECL.
hash 1.0
Native implementations of common message
digest algorithms using a generic factory
method.
ps 1.3.3
ps is an extension similar to the pdf extension
but for creating PostScript files. Its api is
modelled after the pdf extension.
Fileinfo 1.0.2
This extension allows retrieval of information
regarding vast majority of files. This
information may include dimensions, quality,
length etc.
Additionally, it can also be used to retrieve
the mime type for a particular file and, for text
files, the proper language encoding.
sdo 0.7.0
Service Data Objects (SDOs) enable PHP
applications to work with data from different

sources (like a database query, an XML file, or
a spreadsheet) using a single interface.
Check out the hottest new releases from PEAR.
PHP_Compat 1.5.0RC1
PHP_Compat provides missing functionality
for older versions of PHP.
Note: PHP_Compat can be used without
installing PEAR.
1) Download the package by clicking
the “Download” link.
2) Find the file you need. Each function
is in its own file, e.g. array_walk_
recursive.php.
3) Place this file somewhere in your
include_path.
4) Include it, e.g. <?php require_once
‘array_walk_recursive.php’;?>
The function is now ready to be used.
HTML_AJAX 0.3.1
Provides PHP and JavaScript libraries for
performing AJAX (Communication from
JavaScript to your browser without reloading
the page)
Log 1.9.3
The Log framework provides an abstracted
logging system. It supports logging to console,
file, syslog, SQL, Sqlite, mail, and mcal
targets. It also provides a subject - observer
mechanism.
File_SearchReplace 1.1.0

Provides various functions to perform search/
replace on files. Preg/Ereg regex supported
along with faster but more basic str_replace
routine.
Cache_Lite 1.6.0
This package is a little cache system optimized
for file containers. It is fast and safe (because it
uses file locking and/or anti-corruption tests).
Net_DNS 1.0.0rc3
A resolver library used to communicate with
a name server to perform DNS queries,
zone transfers, dynamic DNS updates, etc.
Creates an object hierarchy from a DNS
server response, which allows you to view all
of the information given by the DNS server.
It bypasses the system resolver library and
communicates directly with the server.
HTML_QuickForm_
advmultiselect 1.1.0
The HTML_QuickForm_advmultiselect
package adds an element to the HTML_
QuickForm package that is two select boxes
next to each other emulating a multi-select.
Net_IPv4 1.3.0
Class used for calculating IPv4 (AF_INET
family) address information such as network
as network address, broadcast address, and IP
address validity.
As OBM improve, it is approaching what are
called CRM (with sales force , help desk, time

tracking sections) but can be used simply as a
contact database or as a shared calendar.
OBM represents a framework above which
many modules are written.”
Interested? Get more info from
/>PHPDocumentor 1.3.0 RC4
Phpdoc.org announces the latest release of
phpdocumentor 1.3.0 RC4.
What’s new?
• Full PHP 5 support, phpDocumentor
both runs in and parses Zend
Engine 2 language constructs.
Note that you must be running
phpDocumentor in PHP 5 in
order to parse PHP 5 code
• XML:DocBook/peardoc2:
default converter now beautifies
the source using PEAR’s
XML_Beautifier if available
• inline {@example} tag - this works
just like {@source} except that it
displays the contents of another file.
• customizable README/
INSTALL/CHANGELOG files
• phpDocumentor tries to run
.ini files out of the current
directory first, to allow you to
put them anywhere you want
• multi-national characters are
now allowed in package/

subpackage names
• images in tutorials
• un-modified output
• html/xml source highlighting
This release also contains many bug fixes.
Get the latest info and start documenting at
phpdoc.org.
Volume 4 Issue 12 • php|architect •7
an introduction
I
n their every day development, most web
consulting companies encounter many of the
same components when designing pages for non-
profit organizations and activist groups. These
requirements include forums, a donation system,
membership management, newsletters, and articles,
just to name a few. Many of these organizations also
have small to mid-size e-commerce needs, to effectively
sell and distribute promotional materials, or to handle
signups for paid events.
Developers often tackle this task by rolling their own
systems in an attempt to make their sites as customizable
as possible, while still providing core components to
build on for each individual client. In theory, it sounds
like a good idea. In practice, the limitations of their
underlying frameworks ultimately result in nothing more
than a mash of hacks that only loosely integrate the
unique elements required for their clients.
In the worst case, web development shops end up
coding the entire thing from scratch, each and every

FEATURE
LINKS:
Drupal Handbook:
/>Drupal Modules:
/>PHP Template:
/>Democratica Theme, by Chris Messina, part of the
CivicSpace distribution of Drupal:
/>TO DISCUSS THIS ARTICLE VISIT:
/>8 • php|architect • Volume 4 Issue 12
Organizations these days are demanding
content management applications,
from company homepages to large,
community websites. Let Drupal help
you build these sites quickly and
efficiently by building on a common,
modular framework.
PHP: 4.4
O/S: Debian
OTHER SOFTWARE: Drupal 4.6.3
by TITU S BARIK
9 • php|architect • Volume 4 Issue 12
An Introduction to Drupal
time. Somehow, rolling your own system
never quite works out the way it needs
to. Even if you have two well-written
components, it is often the case that
it’s not the components themselves that
are the problem, but the integration
points that add burdensome complexity.
Integrating disjoint components, say

Forum A with Shopping Cart B, has until
now, been a difficult problem to solve.
This article introduces Drupal, a
modular, open source content management
platform that attempts to address these
difficult challenges. Drupal provides
a flexible, extensible framework—an
alternative to roll-your-own content
management solutions. It can be refit for
a variety of different content systems,
including community portal sites, personal
weblogs, and resource directories, simply
by adding and removing sophisticated
modules.
Drupal offers you a working, tested
framework for building components, and
handles the insignificant but tedious
details of module management, user
management, and integration, so you
can focus on developing the core of your
project. More importantly, Drupal has
a very large user base, and modules to
handle most common functionality are
already available. When these modules
don’t exist, the hooks system allows
the developer to create custom modules
to interact with the Drupal core, while
leveraging the existing Drupal building
blocks.
It’s not at all surprising, then, that

the focus of this article is not on complex
development or PHP code, at least not
directly. In fact, it’s quite the opposite. In
this article, we’ll develop a mock political
organization’s web site, Democratica,
without writing a single line of code.
Along the way, I’ll demostrate the various
built-in and contributed modules that allow you to get a site up
running quickly and effortlessly.
Installation
This section discusses the installation and configuration details of
Drupal, including the pre-requisite software requirements. Our test
installation consists of Drupal 4.6.3, PHP 4, and Apache 2, running on
Linux with a MySQL 4.1 database server.
Though Drupal supports both MySQL and PostgrseSQL, be advised
that most available third-party modules are coded specifically for
MySQL. This effectively forces you to use the former, regardless of
what the Drupal core modules support.
Drupal allows you to host multiple sites on a single Drupal instance.
These sites can be found under the sites folder. For simplicity, I’ll only
utilitize a single site setup in this article.
After creating and assigning the appropriate permissions to your
database, load the tables:
mysql -u nobody -p drupal < database/database.mysql
Next, enter the sites/default folder and modify
settings.php
; namely,
modify the
db_url
, and

base_url
.
Drupal works best on dedicated hosting systems. Since Drupal
FIGURE 1
The first screen you’ll encounter after installing Drupal.
10 • php|architect • Volume 4 Issue 12
An Introduction to Drupal
memory requirements increase proportionally with the
number of active modules, the default PHP memory limit
of 8 MB provided by most shared hosting providers is
typically not enough. To be safe, set this value to
32M

or
64M
in
php.ini
. If the memory requirements are not
successfully met, Drupal will behave strangely, displaying
broken administrative menus and erratic page rendering.
Next, add the following to your
crontab
:
0 * * * * wget -O - -q http://democratica/cron.php
This allows for scheduled events to trigger properly
within Drupal. Such events include search indexing, mass
mailing, and scheduled publishing.
That’s all there is to the installation. Navigate to
your Drupal site using your web browser, and you’ll be
presented with a base page, as shown in Figure 1.

Finding Your Way
Around
It’s time to create your first
account. User #1 is provided
with full administrative access.
All subsequent users are given
authorized user access. Additional
groups can be generated though
the Drupal system as well, providing
fine granularity amongst different
group types. In Democratica, for
example, we may want special
access for employees, and different
access priveleges for members and
guests,
After logging in, select the
administer menu. You’ll be presented
with Drupal’s recent system events,
a web-based logging system for
monitoring the activity on your web
site. A typical administration page
is shown in Figure 2. For now, enter
the settings menu, and change the
FIGURE 2
Administration section of Drupal
FIGURE 3
The Drupal donation block.
FIGURE 4
Administration section of Drupal
default name of the site to Democratica. You should

also set your time zone. Feel free to modify any other
settings, as well.
Perhaps the two most useful menus under administer
are blocks and modules. The modules menu allows you
to extend the core functionality of Drupal. Within this
menu, you’ll activate and install module components
to tailor the functionality that your site requires. For
example, you could enable search, forums, events, and so
forth. The blocks menu enables and disables boxes that
can be positioned on the left and right side bars of your
web site. The available blocks vary, depending on which
modules are currently active. Under modules, notice that
the page and story modules are checked by default.
Now, jump up to the create content menu. You’ll notice
that there are two available content types: page and
11 • php|architect • Volume 4 Issue 12
An Introduction to Drupal
story, the same as the modules we previously witnessed.
Enabling content modules will add additional content
types to this menu. After initial setup, most interaction
with the Drupal site will occur through this menu.
Finally, let’s examine the content menu, again under
administer. This menu allows us to configure the properties
of content nodes, which at first, can be a bit perplexing.
Unlike a dedicated content system such as WordPress for
blogging, or osCommerce for e-commerce, Drupal aims to
be flexible, to suit any type of web platform. In order to
provide such flexiblility, the fundamental type of almost
all content is that of a simple node. Custom behavior
is then implemented by simulating the base node type,

and subsequently adding or removing properties to that
node type. The content menu allows us to set additional
properties, modify nodes, and add custom nodes to
facilitate our development process.
Democratica Theme
In Drupal, themes are rendered through the use of
template engines. Unfortunately, Drupal by default only
provides
xtemplate
, and the Democratica theme that
we’re interested in requires
PHPTemplate
. Luckily, this
takes very little effort. Simply download the
PHPTemplate

engine from the Drupal web site, and extract it to the
themes/engines
folder. Next, download and extract the
Democratica theme, and place it in your themes folder.
Login to your web site as
administrator
and access
the themes menu. The Democratica theme is now
automatically available. Set it to
default
, and save your
configuration. Your new theme is now applied.
Theming is a powerful component of the Drupal
framework that will greatly streamline development.

Namely, it enables you to parallelize your backend
business logic and your presentation code. Your graphic
designers, for example, can independently develop
multiple, pluggable layouts, while your logic developers
can write custom modules and other core functionality.
Modules
The remainder of this article will focus on modules. The
process of installing some modules is more involved than
others, though none of the modules are exceptionally
difficult to integrate. The typical installation procedure
for a module is as follows:
First, load the database schema. This is usually one or
more iterations of the following command:
mysql -u user -p database < schema.sql
Next, copy the module to the modules directory. Then
activate the module in the administer modules menu.
Then, set configuration parameters for the module
under the administer settings menu, and configure access
control permissions on the module through the access
control menu.
Finally, if the module has a presentation layer, enable
the block in the block menu, specifying its location and
ordering.
Some modules have dependencies on other modules.
Many modules, for example, depend on Flexinode, a
module that allows non-programmers to create new
node types from within the content types menu, without
having to custom load database node schemas for each
new node type.
Before continuing, install and activate the Flexinode

module. A content type menu will appear under content,
and a flexinode menu item will appear under settings.
Unlike a dedicated content system
such as WordPress for blogging,
or osCommerce for e-commerce,
Drupal aims to be flexible,
to suit any type of web platform.
12 • php|architect • Volume 4 Issue 12
An Introduction to Drupal
Donations
Our first module will be a simple one. Most political
organizations have a need for donations, and our site
is no different. The Donations module allows us to
accomplish just this goal, with seamless
integration to the
Donorge.org
donation
service. Under settings, modify the
text as desired. Since this isn’t a live
site, the donation ID doesn’t actually
matter.
Nothing appears to have actually
happened, but that’s because we
haven’t told Drupal to place the
content block on the web site. Let’s
do that now. Click on the blocks
menu, enable Donations, and place it
on the right sidebar. A third column
on the Democratica theme will now
be enabled, with your new donation

module, as shown in Figure 3.
Without having to modify a
single line of code, we’ve managed
to add donation functionality to our
Democratica site. Reusable components
such as the donations module are what
make developing under the Drupal
framework so efficient.
Newsletter
After interviewing several non-profit
organizations, the most demanded
feature next to donations is that of
newsletters. Newsletters, when used
effectively, are a vital method of
directly addressing your members,
notifying them of important news and
issues. Our political organization, in
particular, wants to let our subscribers
know about the latest campaign news.
Drupal provides such functionality
through the simplenews module. Install it now. Like
the donation module, it will appear as though nothing
has changed. Click the new newsletters menu item
under administration; this will create a default Drupal
newsletters. Under the newsletters
tab, click edit type for Drupal, and
change the name to “Democratica
Newsletter.” The Newsletters
interface allows you to create
multiple newsletters, track the

progress of newsletters, and track
subscribers, as shown in Figure 4.
Under blocks, activate the newly
created newsletter, placing it on
the right sidebar.
Next, create a newsletter
from the create content menu.
Creating a newsletter item is
simple enough that it doesn’t
require any further explanation
here. Assuming your PHP
configuration and mail server are
setup correctly, all subscribers
will receive an e-mailed copy
of the newsletters you’ve just
posted.
Survey
Our political organization wants
to collect data that may help in
predicting the outcome of the
next election. To do this, they
would like to create a survey,
asking various questions on the
web site. At first glance, such
a task seems like a great deal
of work. We’d have to design
a backend database to store
a variety of survey questions,
FIGURE 5
Election survey.

FIGURE 6
Election survey, administrator perspective
Drupal provides an excellent,
out of the box, event handling system.
13 • php|architect • Volume 4 Issue 12
An Introduction to Drupal
modules. In addition, activate
the cod module and the tangible
module, for tangible products.
Under create content, a product
item will now appear. Here,
you can set the product title,
description, price, and the type
of product. For Democratica, the
fulfillment house handles all
inventory, and we thus disable
inventory management.
Under the block menu, enable
the Shopping Cart module.
Under the create content
menu, create your product. Once
completed, it will appear in the
top-level products menu. From
here, you can add it to your cart
and checkout. The e-commerce
module can and probably will
need to be customized through
PHP to suit your particular
needs. However, the provided
shopping cart already provides

much of the required base
functionality.
Events
Democratica can’t be successful
in rallying support if it can’t
successfully organize events.
Drupal provides an excellent,
out of the box, event handling
system.
The event module relies on
the Flexinode module, which was
installed earlier in this article. A
close cousin of the event module
is the location module, which
allows for additional location
information.
The location module will add the final touch to
our event system. Currently, the location module fully
supports United States zip codes. The module provides
routines for conducting postal code proximity searches,
linking to Google maps, and other functions for collecting
locations. Follow the directions for installing this module,
carefully. This module is unique in that it requires you to
load three mysql data files: a location schema, a zipcode
schema, and US zip code data. Then, just as we’ve done
for all other modules, activate it through the module
menu.
implement forms on the front-end,
and provide facilities to allow the
organization to collect and download

the data in a user-friendly format. In
addition, we would have to provide
some sort of dynamic form creation
system to allow users to create their
own surveys.
Unsurprisingly, Drupal makes this
task simple and reusable through the
survey module. The survey module
depends on the forms module, which
provides an API for adding user-
customizable form elements within
modules. First, install the form
module and activate it. Then, install
and activate the survey module.
Under the create content menu, the
survey item will appear, in addition to
the standard story and page items.
Let’s now create a survey called
“Election Survey.” After entering
the general information, you’ll find
yourself in a survey menu, from where
you’ll go to the form tab.
Add a radio field. We’d like to
know which political party you belong
to. Under selection options, enter
“Republican; Democrat; Libertarian”.
The semi-colon is used to delimit
the multiple options for the given
field type. Add any additional desired
fields. A non-administrator user will be

presented with the survey, as shown
in Figure 5. As an administrator, your
window will appear more like that in
Figure 6. When a user completes a
survey, his or her results can be found
under the responses tab.
E-Commerce
Throughout the political campaign, our organization
wants to sell tangible items through its fulfillment house.
These items include bumper stickers, signs, buttons, and
so on.
The e-commerce package includes several modules.
Some of the modules are located in Figure 7.
E-commerce preferences can set under the settings
menu. Among other options, items include things like
whether customers must create an account to order,
shipping methods, and payment methods.
For our purposes, activate all of the required
FIGURE 8
Content type administration for an Event flexinode
FIGURE 9
Content Types submenu for Content administration
14 • php|architect • Volume 4 Issue 12
An Introduction to Drupal
After enabling both modules, access the block menu
and enable List of upcoming events. An empty upcoming
events listing will appear, depending on your sidebar
selection.
Unlike most of our previous modules, an event is not
a node type in itself. Specifically, event properties can be

added to any node type. So, for example, you can create
your own Generic Event node type using Flexinodes, or
you can create a Birthday node type for birthdays, and so
on, to describe different categories of events.
Let’s create a Generic Event node now. Click on content
type in the content menu under administration, and click
the add content type tab. Call our content type name
“event,” and give it a short blurb in the description.
You’ll now be placed in the list tab, where you can add
additional fields to your custom node. Title is already
included, so let’s add a text area for the event description.
After following these steps, your screen should resemble
Figure 8.
Though we’ve created a generic
event node, we have yet to bind
the event module properties to
it. To do so, click on the content
menu, then the configure tab.
From here, click the content type
subtype, where you’ll find the
configure option for the event.
Yes, it’s deeply buried under a lot
of menus, so look at Figure 9 for
assistance.
Under configure, scroll down
to “show in event calendar.” Set
this to all views to enable event
times for the generic event node
that you’ve just created. Under
the blocks menu, enable “List of

upcoming events.” In addition,
select “Enable for location,” a
feature contributed by the location
module. Set “Allow” for street, city,
state, postal, and country.
You’re on the final stretch. It’s
time to actually add an event. Under
create content, you’ll now find an
event item. Fill in the details for
your event. In our example, we’re
celebrating the Democratica Launch
Party, shown in Figure 10. Notice
also, that the event has been
added to the upcoming events list
in the sidebar.
FIGURE 10
Democratica Launch Party event.
FIGURE 11
Democratica Launch Party invite.
RSVP
The Democratica organization is pleased with the events
system. However, only special guests are invited to the
Democratica Launch Party, based on, say, the number of
charitable contributions, and our currents events system
has no way to track this.
This is where the RSVP module comes in. RSVP lets
users invite people to attend an event. It sends an
invitation email to a list of people, and can the track
which users have looked at the invitation and their
responses. Invitees can view and reply without having

user accounts.
After enabling the RSVP option, a Create RSVP link
will become active on all events. From here, you can
invite selected guests to your event. An invite preview is
shown in Figure 11.
Other Modules
Our last module is as big one. CiviCRM is a web-based,
open source, internationalized,
constituent relationship
management (CRM) application,
designed specifically to meet the
needs of advocacy, non-profit and
non-governmental organizations.
In short, it keeps track of people.
CiviCRM is large enough to be
a product on its own. It is also
the most complicated of modules
to install, and its installation
instructions would comprise an
entire article by itself. The CiviCRM
module is also a dependency for
the other modules which require
contact management, and it is
also an optional requirement for
the event finder module, which
allows the user to search for events
based on event type, geographic
location, and proximity to major
metropolitan area.
Thankfully, the OpenNGO web

site provides excellent installation
instructions for the CiviCRM module.
Here, I’ll omit the installation steps
and show you the brief demo of the
CiviCRM and Event Finder modules.
CiviCRM primarily enables
the Find Contacts feature, shown
in Figure 12. It also allows you
to manage groups, relationship
types between contacts, and
15 • php|architect • Volume 4 Issue 12
An Introduction to Drupal
TITUS BARIK
is a content application developer with an interest in
open source Enterprise solutions. He has deployed both open source
and proprietary content management systems successfully in corporate
and non-profit environments. His personal weblog is available at barik.
net, and he welcomes your comments and suggestions.
FIGURE 12
CiviCRM contact search page.
FIGURE 13
The end result. Not bad at all for the small investment we’ve made.
location information.
For those who don’t
have in-house contact
management tools,
CiviCRM may be a good
option.
Event Finder takes
the functionality of the

existing events module
and adds the ability to
actively search for local
events by category,
event type, and zip
code. It also enables
online registration for
events, where one can
specify the maximum
number of registrants.
Conclusion
The final result is shown
in Figure 13. In the
course of about an hour
or two, you’ve created
a dynamic site that
provides a shopping
cart, donation system,
newsletters, event
management, and
surveys. You’ve also
taken advantage of
the underlying Drupal
framework, including
its user management
and permissions
systems. Even if you’re
required to customize
each and every one of
these components for

your specific project,
the time saved in
comparison to writing
a custom solution from scratch is simply tremendous.
Drupal is a large and powerful framework, and you’ll
no doubt run into a few obstacles here and there, along
the way. When you do, the Drupal Handbook is available
online for your use. The Drupal web site also provides
forums to address questions and issues that aren’t
covered by the Handbook.
Sites that have successfully implemented Drupal
include Spread Firefox, Kernel Trap, Linux Journal, and
The Onion. I hope that you’ll be next. 
16 • php|architect • Volume 4 Issue 12
PHP Web Services: An Introduction to SOAP
FEATURE
W
hen we write a PHP application, it may
rely on a remote program that performs
certain operations what we can’t, or don’t
want to do locally.
For instance, we may need to fetch
some up-to-date data about, the weather in Los Angeles.
Since it is unlikely that our application will have access
to this data through a local database, we must somehow
communicate with the web site of the local meteorological
station in L.A.
We have a similar problem if we want to make our
user perform a web search without leaving the pages
of our site—our PHP application must send a query to

(e.g.) the Google Application Program Interface, and
retrieve the response.
Perhaps you want to implement an online shop, with
a payment system based on PayPal; you’d have to set up
secure communications between your site and the PayPal
servers.
Finally, you may have a local database of user names,
mails and contacts and want to make some of this
information available to a certain number of authorized
users.
All of the examples above require the use of some
sort of communication with a remote application: what
we are looking for are Web Services.
A web service is a software system designed to support
interoperable machine-to-machine interaction over a
by ALES SANDRO S F O NDRINI
TO DISCUSS THIS ARTICLE VISIT:
/>Web Services are widely used to build applications designed to share
information or to communicate with remote programs. In this article
we will take a look at their basic structures and purposes.
PHP: 4.3.0+
Other Software: NuSOAP Library, MySQL database
PHP WEB SERVICES:
an Introduction to
SOAP
CODE DIRECTORY: phpwebservices
LINKS:
www.w3.org/TR/soap
www.w3.org/TR/wsdl
dietrich.ganx4.com/nusoap

17 • php|architect • Volume 4 Issue 12
PHP Web Services: An Introduction to SOAP
FIGURE 1
1 <!-- FIRST PART: SOAP REQUEST -->
2 <SOAP-ENV:Envelope xmlns:SOAP-ENV=
3 “
4 SOAP-ENV:encodingStyle=
5 “
6
7 <SOAP-ENV:Body>
8 <m:GetPrice xmlns:m=”Some-URI”>
9 <Code>Moz-K527</Code>
10 <Name>W.A.Mozart, Don Giovanni</Name>
11 </m:GetPrice>
12 </SOAP-ENV:Body>
13
14 </SOAP-ENV:Envelope>
15
16
17 <!-- SECOND PART: SOAP RESPONSE -->
18 <SOAP-ENV:Envelope xmlns:SOAP-ENV=
19 “
20 SOAP-ENV:encodingStyle=
21 “
22
23 <SOAP-ENV:Body>
24 <m:GetPriceResponse xmlns:m=”Some-URI”>
25 <Price>29.90</Price>
26 </m:GetPriceResponse>
27 </SOAP-ENV:Body>

28
29 </SOAP-ENV:Envelope>
LISTING 1
network. So, when we talk about WS, we are implicitly
referring to many parts:
• A client application, which can be written
in any language (e.g. C, Java, Python, and
of course PHP) and run on any Operating
System
• A remote application, with which we want to
communicate
• A remote interface, often described by WSDL
(Web Service Description Language)
• A protocol, normally based on TCP/IP—the
most used are HTTP and HTTPS
• A document to be sent or received, which is
usually encoded using particular XML subsets
like SOAP (Simple Object Access Protocol) or
XML-RPC (Remote Procedure Call)
In Figure 1 you can see an example of an application
which connects to a remote Application Program Interface
to fetch data from its database: while the communication
between the program and the user (at least, his browser)
is encoded in HTML, the traffic between the two machines
is transported via SOAP.
This article is a short introduction to web services.
Our purpose is to explore what we can do with them
and how they work. We will have a closer look at SOAP-
based web services over HTTP, as they are the most
common, and are pretty easy to use. We will also take a

look at a sample application which consists of a client
& server system, and performs a simple operation (in
our case, retrieves data from a remote MySQL database).
Out sample takes advantage of NuSOAP, a predefined PHP
library, designed to perform Remote Procedure Calls.
Before we get into the real work, however, we will
cover SOAP and WSDL basics, without getting too deep,
just to make things a bit clearer. We won’t, however,
see any complex practical application of Web Services. In
fact, this article’s intent is introductory. If you’re looking
for a little more meat, you should take a look at the
upcoming php|a NanoBook, “Practical Web Services,”
which I will quote several times in the following text.
Simple Object Access Protocol:
an overview
SOAP is an XML-based protocol, created by the World
Wide Web Consortium. It was created to help server
applications exchange structured and typed information
in a distributed environment. A SOAP message can be
sent on any Internet protocol (HTTP and HTTPS are the
most common).
What makes SOAP so powerful is that the application
that receives the message doesn’t need to be written in
the same programming language, or even to be run on
the same operating system as the one that originated the
request. The platform is simply irrelevant—so you could
easily make a .NET application exchange data with one
written in Python.
A SOAP message is normally composed of three
elements: an envelope, a header and a body. When dealing

with an error condition, a SOAP fault element will also
be present.
The envelope is the first element in a SOAP
message, and it’s mandatory. It may contain namespace
declarations or additional attributes, which must be
namespace-qualified. It may also contain additional
namespace-qualified sub-elements that must follow the
body element.
The header is optional and, if used, must be the first
child element of the envelope. It may contain a set of
namespace-qualified header entries as an immediate
child element of the header element, and it may also
contain general information about the message, such as
language, date, etc.
The body is mandatory, and must be an immediate
child element of the envelope (and follow the header,
if it’s present). It may contain a set of body entries,
18 • php|architect • Volume 4 Issue 12
PHP Web Services: An Introduction to SOAP
which must be an immediate child of the body element
and each entry may be namespace-qualified. This is the
most important part of the message, since it contains
the request or the response, and the part that is used to
perform Remote Procedure Calls (RPCs).
As I mentioned, a particular type of body entry,
named fault, is used to indicate error messages. Its sub-
elements are used to report information about the error
(the error code and name, what caused it, etc.). Any type
of application may need to use this kind entry, so we will
examine it, too (briefly).

For a detailed description of the SOAP language,
check the World Wide Web Consortium documentation
at
/>. We won’t examine WSDL
in depth, as it is quite a complex topic, but we can’t
completely overlook it because of its importance—it’s
definitely worth a quick glance, if for nothing else, then
to understand its main purpose.
SOAP Envelope element
This element must always contain a namespace URI to
define the SOAP versioning model. The only valid namespace
URI is:
/>.
The envelope may also contain an
encodingStyle

attribute to indicate the serialization rules used; here
are some examples of valid URIs:

/>•
/>•
/>As you can see, you can use more than one URI
separated by a space (ordered from the most specific to
the least specific). A blank URI means that there are no
claims for the encoding style.
Here is an example of a valid envelope element:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV= “ /> SOAP-ENV:encodingStyle=
“ /></SOAP-ENV:Envelope>
It has namespace and encoding style declarations. We

will insert our other elements or sub-elements within
this main tag.
SOAP Header Element
The SOAP header is qualified by its local name and
namespace URI. It is optional, and may contain general
information about the message. The
encodingStyle

attribute may be used to indicate the encoding style.
Two attributes are frequently used in this element:
mustUnderstand
and
actor
.
The
mustUnderstand
attribute indicates whether the
header entry must be processed by the recipient. Its
value can be
1
or
0
(if it’s absent, a default value of
0
is
assumed). If it’s set to
1
, the entry must be processed.
The
actor

attribute is useful for messages that travel
from the originator to their final destination by passing
through one or more intermediaries (SOAP servers can
have the ability to both receive and forward a SOAP
message).
actor
specifies which of these intermediaries
should receive and process the header entry (which, when
processed, will be no longer forwarded). The value of
actor
is the URI of the recipient. There are, however, two
special cases: if the attribute is absent, then the recipient
automatically becomes the recipient; if the attribute
is set to
/> the
destination is intended to be the first intermediary.
SOAP Body element
The
body
element is used to send RPC calls or responses,
and to report errors. A
body
entry is defined by its name,
composed by a valid namespace URI and a local name.
Immediate child elements of body element may be
namespace-qualified.
When sending the message over HTTP (as we will),
the POST method should be used to both send the call
and obtain the response. In PHP, we can do this using
the socket functions. The content type we should specify

is
text/xml
, but
text/plain
also works. The encoding
depends on the application that we are dealing with.
In the first part of Listing 1, there is an example of
a valid RPC call, performed using SOAP. In this message,
there is no header element, and that’s OK, since it is
optional. Look at the body element: in sub-element
GetPrice
(defined by the URI
Some-URI
), we store the
product code and name, to obtain the price. The second
part of Listing 1 contains a possible response.
Note that this is the bare XML response message,
without HTTP headers (a few lines that the server sends
to indicate whether the operation was successful and
additional information like date and content-length).
This is a very basic example of a SOAP RPC call and
response. Real-life applications usually manage a larger
amount of data, including arrays of sub-elements, which
makes things more complex. I’ve intentionally kept this
example simple, to make things a bit clearer.
SOAP Fault Element
If, during the execution of the remote application, an
error occurs, preventing the program from producing the
expected output, it is necessary to inform the client of
what happened. This is exactly the purpose of SOAP fault

element. It is a child element of the envelope and the
1 # Dump of “transactions”
2
3 CREATE TABLE transactions(
4 tid INT UNSIGNED NOT NULL AUTO_INCREMENT ,
5 cid INT UNSIGNED NOT NULL ,
6 description VARCHAR(30) NOT NULL ,
7 amount FLOAT(7,2) UNSIGNED NOT NULL ,
8 STATUS ENUM(‘pending’,’failed’,’OK’)
9 DEFAULT ‘pending’ NOT NULL ,
10 PRIMARY KEY (tid)
11 );
LISTING 2
1 <?php
2 /* CLIENT FILE*/
3
4 require(“nusoap.php”);
5 $s = new soapclient(“http://host/server.php”);
6 /* Creates a client object */
7
8 $params = array(‘tid’=>4636, //Transaction ID
9 ‘cid’=>1059);//Customer ID
10
11 $res = $s -> call(‘get_transaction’, $params);
12 /* Invokes the remote method */
13
14 if(isset($fault)) // If a fault occurred
15 die($fault); // Prints it and exits
16
17 if($params[‘tid’] != $res[‘tid’])

18 die(‘Transaction ID does not match’);
19 if($params[‘cid’] != $res[‘cid’])
20 die(‘Costumer ID does not match’);
21 /* Checks tid & cid */
22
23 echo ‘Amount ‘.$res[‘amount’].’ status ‘.$res[‘status’];
24 ?>
LISTING 3
1 <?php
2 /* SERVER FILE */
3
4 if($_SERVER[“REQUEST_METHOD”] != “POST”)
5 exit; // Check whether the req. method was POST
6
7 require(“nusoap.php”);
8 $s = new soap_server;
9 /* Creates a server object */
10
11 $s -> register(‘get_transaction’);
12 /* Registers the method */
13
14 function get_transaction($tid, $cid)
15 {
16 if(!is_int($tid) || !is_int($cid))
17 return new soap_fault(“Sender”, “Input err”,
18 “ID type must be INTEGER”); //DataType fault
19
20 $q = “SELECT tid,cid,amount,status FROM transactions”
21 .” WHERE tid = $tid AND cid = $cid”; //MySQL query
22

23 if(($conn = @mysql_connect()) === FALSE)
24 return new soap_fault(“Receiver”, “MySQL”,
25 mysql_error()); //MySQL connect. fault
26
27 if((@mysql_select_db(“liceogiovio_”, $conn)) === FALSE)
28 return new soap_fault(“Receiver”, “MySQL”,
29 mysql_error()); //MySQL selectDB fault
30
31 $res = @mysql_query($q, $conn);
32 if(mysql_num_rows($res) != 1)
33 return new soap_fault(“Sender”, “Bad IDs”,
34 “No record matches the IDs”); //No results
35
36 $resp = @mysql_fetch_array($res, MYSQL_ASSOC);
37 @mysql_close($conn);
38 $resp[“time”] = time(); //Add time() value
39 return $resp; //Returns the result
40 }
41
42 $s -> service($HTTP_RAW_POST_DATA); //Executes the RPC
43 ?>
LISTING 4
only child element of the body element—which means
that when a body carries a fault, no other information
is passed.
A fault mainly consists of a mandatory standard error
code named
Code
, which identifies the problem (e. g.
Sender

or
Receiver
to identify the party responsible
for the fault) and a mandatory
Reason
explaining what
went wrong (e. g.
Timeout
). It may contain additional
information, like
Node
which explains which node of the
SOAP message path caused the error, and
Role
, which
is used to describe the role of that node. Additionally,
a
Detail
element is available to explain precisely what
went wrong.
We will actually use these fault sub-elements in our
applications.
A quick glance to WSDL
As I mentioned earlier, we will take only a quick look at
WSDL, to better understand how web services work. WSDL
is an XML-based document format created to describe Web
Services. In particular, its aim is to provide information
about the public interface of the web service.
A WSDL document contains all the information needed
about how to reach the web service—the methods to be

used, the parameters they require and the type of output
they will produce.
If you want to learn more about WSDL, you can
check the World Wide Web Consortium page about it at
/>.
How to Write an Application
The application that we will write consists of two parts:
client.php
(Listing 3) is designed to send a request
to a remote application and fetch its response, while
server.php
(Listing 4) will receive the request, process
it, and produce output to send as a response.
As we have seen in the previous paragraphs, SOAP
is simple enough that we could write the request
“manually”, simply by concatenating strings and
variables. The problem comes when we have to parse an
XML document: there are several PHP functions designed
for this purpose, but a parsing application is often quite
complex to write, especially when receiving long and
complex messages.
Fortunately, there are open source libraries which
can handle the tricky part for us. This will allow us to
spend more time on the other parts of our application—
security, for example, is the most important aspect of a
Web Service!
Of course, writing our own code is generally the best
approach, as in doing so, we are fully aware of how it
19 • php|architect • Volume 4 Issue 12
PHP Web Services: An Introduction to SOAP

20 • php|architect • Volume 4 Issue 12
PHP Web Services: An Introduction to SOAP
If, during the execution of the remote
application, an error occurs, it is necessary
to inform the client of what happened.
works and how to optimize it. But this takes a lot of
work, and may introduce some errors in our app—it’s not
only a matter of laziness.
So there isn’t a best way of coding—avoiding libraries
or using them—as it all depends on our particular situation
and time limits. In this article we will use NuSOAP, an
open source PHP library, to simplify our task.
PHP NuSOAP library
NuSOAP, a group of classes designed to allow developers
to manage SOAP web services, is licensed under LGPL and
is available for free at
/>.
All we have to do to use it is to include
nusoap.php
in our
scripts, by using
require()
.
Writing a client with this library is really easy. Instead
of building a SOAP message and sending it to the remote
API we can just pass to a class the variables we need and
instruct it to send the SOAP-encoded variables over HTTP
or any of the most common TCP/IP protocols.
Let’s see an example:
<?php

require(“nusoap.php”);
$params = array(“id” => 42);
$client = new soapclient($remote, $wsdl);
$resp = $client->call(‘getbyid’,$params);
?>
First of all, we include NuSOAP, then we store the
parameters we will use for the RPC in the associative array,
$params
. We create an object passing two arguments:
the SOAP server address
$remote
(a string) and
$wsdl
, a
boolean value which indicates if the server uses a WSDL
document.
As we have seen, a WSDL (Web Services Description
Language) document contains information about the Web
Service, its methods and properties and is often used by
Web Services, especially if they reach a certain degree of
complexity.
Once we have created the object, we only have to
execute the RPC: we invoke the
call()
method, specifying
the remote method name and the parameters to be passed
(contained in
$params
). NuSOAP automatically fetches
the result and stores it in the

$result
associative array.
If we are working with a WSDL-based server (and
consequently
$wsdl
is set to
TRUE
), once created,
$client

can also invoke the remote method in this way:
<?php
$proxy = $client->getproxy();
$results = $proxy->getbyid($params);
?>
This can be useful to simplify our code: first we create
a proxy client (
$proxy
), then we can invoke any remote
method specified in the WSDL document using the proxy,
without having to use NuSOAP
call()
method.
Now, let’s see how to configure a basic remote
interface with NuSOAP:
<?php
$server = new soap_server;
$server->register(‘mymethod’);
/* mymethod function declaration */
$server->service($HTTP_RAW_POST_DATA);

?>
Once we’ve included the library, we can create a server
object and register a method that we want to make
available. Then, we declare a function with the same name
and instruct it to perform some operations and return a
result, just as we would do for any PHP function. Finally,
we pass to the server object all of the HTTP POST data we
received, and it will automatically produce output.
Designing the Application
Remember, our application will consist of two PHP files,
both based on NuSOAP library:
client.php
and
server.php
.
We won’t use a WSDL file, as our web service will be very
basic. Let’s have a look to his structure.
In
client.php
we will send a SOAP message to retrieve
21 • php|architect • Volume 4 Issue 12
PHP Web Services: An Introduction to SOAP
information about a transaction, sending a transaction
ID (
tid
) and a customer ID (
cid
) as parameters to the
remote method,
get_transaction()

. We expect the remote
application to send back a
status
code (“
OK
”, “
pending
”,

failed
”), the
amount
of the transaction, and the two
IDs (to verify that no errors have occurred). In addition,
server.php
will append the current value of
date()
to
those variables.
In
server.php
, we will first check that the remote
method has been invoked in the right way (e.g. via
POST), next that all the data required is provided. So, we
try to retrieve the data required from our database (we
will use MySQL), and send it back.
In Listing 2, you can find the dump of the table we
will use.
Writing the Client
Look at Listing 3: first, we include NuSOAP and create the

client object as we have done in the previous examples.
Note that the
$wsdl
boolean parameter is absent: this
means that it is assumed
FALSE
and no WSDL file is
available for this Web Service.
Next, we store the input data for the remote
application in the
$params
associative array. Note that
if this had been a “real life” application, the input data
could have come from a form submitted by the user, from
the
$_SESSION
array, or from our database. In order to
simplify our code, let’s assume that, no matter where the
data may have come from, it is now stored in this array.
Now, the heavy lifting is done by NuSOAP: just one
line of code to build a request, send it, retrieve and parse
the response. Sounds fantastic, doesn’t it?
Once the results are stored in
$res
, we check whether
any fault occurred (we analyze the
$fault
variable
created by NuSOAP), whether the IDs sent match the
ones returned, and eventually print the result.

This was a really basic program, just to get started
with the simplest possible application of Web Services—
a sort of “Hello World.” Writing the server will be a bit
more difficult.
Writing the server file
In Listing 4, you can find the code for the server.
As the server file is not designed to be reached by a
browser, but only by a remote application via POST, we
first check whether the request method is POST; otherwise
the program exits. We could also check the IP of the
remote application or require a username & password. In
this case, remember that to ensure secure transmission
of data we must use HTTPS instead of HTTP.
Next, we include NuSOAP, create the server object
(
$s
) and register a method (
get_transaction()
).
The interesting part of the code is this function. It
requires two parameters—the transaction ID and the
customer ID—which we will use to build our MySQL
query.
The first step of the function is to check that the
data type of the parameters is “integer”; otherwise, it
will produce an error message. This message is worth a
closer look, as we don’t use
die()
but we produce a SOAP
Fault document using NuSOAP

soap_fault()
method. We
specify three properties:
• the fault
Code
—which can be either the client
or the server—is set to “
Sender
”, as the
problem lies in the wrong data type of the
input the client sent
• the
Reason
, set to “
Input err
”,
• and the
Detail
, which explains the problem
that occurred
Of course, using
return
to produce the SOAP Fault
document we prevent
get_transaction()
from performing
any other operation.
Next, we build the MySQL query and store it in
$q
. We

connect to MySQL and select a database, verifying that
each step was successful—producing a
Fault
if it wasn’t.
Once we have executed the query, we count the results
returned. An error occurs if
N < 1
, because this means
that the query produced no result—likely because the
transaction ID & customer ID sequence wasn’t correct—
but also the case
N > 1
, which is even less probable, and
represents an error, as each transaction must be unique.
So, we join these two conditions as
N != 1
.
Finally, we retrieve an associative array with the
results, append a
time
element, in which we record the
value of
time()
, when the operation has been performed,
and return the
$resp
array. All we have to do to execute
the remote procedure call is pass the raw POST data as
input to
service()

.
So what our application will do, in the end, is fetch
(over HTTP) information stored in the database of a
remote machine, and make it available to our user. It’s
something really simple, but the underlying idea is the
same at the base of Amazon or PayPal web services.
A first step to Practical Web Services
This article is just a first step to the practical use of web
services, as it may be regarded as a general introduction
to SOAP and to remote procedure calls. There are many
other things to say about SOAP, about writing a client
or server without using libraries, and also about using
NuSOAP in a more sophisticated way.
Of course, all of this would require a deeper theoretical
introduction and—more importantly—many more
22 • php|architect • Volume 4 Issue 12
PHP Web Services: An Introduction to SOAP
ALESSANDRO SFONDRINI
is a young programmer from Como,
Italy. His interests are mainly related to PHP and C, with a particular
focus on Web Services. Alessandro is the author of the upcoming
php|a Nanobook, “Practical Web Services.” You can contact him at

.
examples. It is clear that an article is not the right place
to talk in an exhaustive way about a topic as elaborate
as web services.
Furthermore, even if we could have dealt with the
topics above, we would still have been far away from
what mainly interests a PHP developer: how can I

use all these things in my job? What about payments
with PayPal, or online shopping with eBay? If you are
interested in any of these topics, or simply would like to
have a deeper view of PHP & Web Services, you might like
to know the topics of the upcoming NanoBook “Practical
Web Services”.
Practical Web Services
The book overlooks a complete theoretical lesson about
SOAP: this article provided a brief one which is enough
to start working.
As the title underlines, the attention is focused
on the practical aspects, so after a short introduction
to Web Services, we dive straight into some code. In
fact, the majority of the work is composed of examples
of real-life applications, realized with many different
programming techniques and commented almost line by
line, sometimes with the help of pictures.
Conclusions
Coordinating data with a remote application, or sharing
local data with public or private clients is becoming more
and more necessary as the Web evolves. For these reasons
Web Services are gaining a central position in the world
of web based application, and for a programmer is an
often required skill.
I hope that this article has been an useful introduction
to SOAP and Web Services, even if represents just a
starting point for a developer interested in writing
applications using these technologies and acquiring an
important skill. If you have any doubt about the content
of this article, drop me a note at


or leave
a message on php|a online discussion board. 
23 • php|architect • Volume 4 Issue 12
Logging and Monitoring with log4php
FEATURE
by KNUT U RDALE N
TO DISCUSS THIS ARTICLE VISIT:
/>Monitoring your application involves keeping a close watch on your
implementation and getting notified when an error occurs. Error
logging is closely related to monitoring, and with log4php, you can
write logging code once and configure the destination of different
type of logging messages, without changing your code. This is a
useful way of applying a logging mechanism to your application,
especially when it will be deployed in a lot of different ways.
I
n this article, I will demonstrate how you can
apply and maintain logging and monitoring in
your own web applications using
log4php
. The
text is based on my experience with
log4php
in
some of our latest in-house products at Telio.
The first part contains a brief introduction with some
sample code of core functionality; the second part covers
some more advanced topics and useful examples on how
to deal with errors, and how to apply context data to
logging events, as well as some optimization tips. In the

last part, I will also show you how to create a centralized
logging server.
Introduction
You never know what could happen with your code.
Errors will always occur, either because of bugs in your
own code, or an external interface or resource going
down. You could have lost your network connection to
the MySQL server, the hard disk could have become full,
there can be bugs in third party code, or there may be
bugs in your code that you did not catch before you
released your product.
PHP: 4.2+
OTHER SOFTWARE: log4php
LINKS:
/>LOGGING & MONITORING WITH
log4php
CODE DIRECTORY: log4php
Logging in PHP applications is traditionally done by
using your own logging function to send a message to
a file or by mail, or through a small 3rd party logging
class. However, writing logging code with a configurable
logging system lets you write this code once and allows
the system administrator to decide what kind of messages
he wants to capture, and where those messages should
be sent. When serving a mission critical application, you
24 • php|architect • Volume 4 Issue 12
Logging and Monitoring with log4php
1 <?php
2 require_once ‘log4php/LoggerManager.php’;
3 $logger =& LoggerManager::getRootLogger();

4 $logger->debug(“Hello World!”);
5 ?>
LISTING 2
1 log4php.appender.default = LoggerAppenderFile
2 log4php.appender.default.file = audit.log
3 log4php.appender.default.layout = LoggerLayoutTTCC
4 log4php.logger.audit = INFO, default
LISTING 3
1 <?xml version=”1.0” encoding=”UTF-8”?>
2 <log4php:configuration
3 xmlns:log4php=”
4 threshold=”all” debug=”false”>
5 <appender name=”default” class=”LoggerAppenderEcho”>
6 <layout class=”LoggerLayoutSimple” />
7 </appender>
8 <root>
9 <level value=”DEBUG” />
10 <appender_ref ref=”default” />
11 </root>
12 </log4php:configuration>
LISTING 4
can’t afford to wait until users let you know when your
application fails.
In most companies, application monitoring is the
responsibility of administrators or an operation team. It
is critical for these attendants to establish procedures
and strategies on how to handle application monitoring.
Communicating these strategies to developers within the
development team will help both teams work together
on improving logging and monitoring information that,

in the end, will help resolve small issues before they
become bigger problems.
It is not an easy task to apply logging to a large
base of preexisting code. A better approach is to make a
strategic decision early in the design phase to determine
the manner in which you will apply error logging,
monitoring and audit logging.
What is log4php?
log4php
is a port of the popular
log4j
open source logging
API for Java and has been around since early 2003.
In looking at the adoption of
log4php
in open source
projects and activity on the project’s own mailing lists,
it does not seem that many PHP developers are actually
using it. However, it is a robust and flexible logging
system and does not have any real competitors. Earlier
this year,
log4php
was adopted by Apache’s Logging
Services Project whose intention is to provide cross-
language logging services based on the work of
log4j
.
That means that
log4php
will be backed up in the same

way as
log4j
,
log4cxx
and
log4net
when the incubation
stage is finished.
How does it work?
Log4php logically consists of three main components:
appenders, layouts and loggers.
• An appender is responsible for appending a
log message to a resource. Some available
appenders are console, database, file, email,
socket and daily rotating logfiles.
• A layout is the view of an appender and
how the log message should be formatted.
Typically, these are HTML, XML or text based
on a pattern string.
• A logger combines a set of appenders with a
unique name, which is used to reference the
logger from program code. One and only one
log level is attached to a logger.
Additionally, there are two other terms that are very
common: log level and root logger.
• A log level is a defined severity for the log
1 ; log4php.properties
2 log4php.appender.default = LoggerAppenderEcho
3 log4php.appender.default.layout = LoggerLayoutSimple
4 log4php.rootLogger = DEBUG, default

LISTING 1
1 <?php
2 define(‘LOG4PHP_CONFIGURATION’, ‘listing4.xml’);
3 define(‘LOG4PHP_CONFIGURATOR_CLASS’,
4 ‘log4php/xml/LoggerDOMConfigurator’);
5 require_once ‘log4php/LoggerManager.php’;
6 $logger =& LoggerManager::getRootLogger();
7 $logger->debug(“Hello World!”);
8 $logger->fatal(“System crash!”);
9 ?>
LISTING 5
1 log4php.appender.default = LoggerAppenderDailyFile
2 log4php.appender.default.layout = LoggerLayoutTTCC
3 log4php.appender.default.datePattern = Ymd
4 log4php.appender.default.file = /path/to/dailylog_%s.log
5 log4php.rootLogger = INFO, default
LISTING 6
1 log4php.appender.email = LoggerAppenderMail
2 log4php.appender.email.layout = LoggerLayoutTTCC
3 log4php.appender.email.from = root@localhost
4 log4php.appender.email.to =
5 log4php.appender.email.subject = Log4php test
6 log4php.rootLogger = FATAL, email
LISTING 7
1 log4php.appender.default = LoggerAppenderConsole
2 log4php.appender.default.layout = LoggerLayoutTTCC
3 log4php.appender.default.layout.threadPrinting = true
4 log4php.appender.default.layout.categoryPrefixing = true
5 log4php.appender.default.layout.contextPrinting = false
6 log4php.appender.default.layout.microSecondsPrinting = false

7 log4php.appender.default.layout.dateFormat = %d-%m-%Y
%H:%M:%S
8 log4php.rootLogger = INFO, default
LISTING 8
25 • php|architect • Volume 4 Issue 12
Logging and Monitoring with log4php
The root logger will catch all logging events, so you
may create other loggers for different logging purposes.
Using the configuration in Listing 1 as a base, we can
add another logger called “
audit
” for tracking audit
messages and send them to a file with more information
in the layout (see Listing 3).
To get the new logger you can call
LoggerManager::getLogger(‘audit’)
:
$logger =& LoggerManager::getLogger(‘audit’);
$logger->info(“User profile updated“);
Configuration
By default,
log4php
will look for a configuration file
called
log4php.properties
within the current directory
and use the
LoggerPropertyConfigurator
to parse the
property file which is in a simple INI-file format. The

filename is set by the
LOG4PHP_CONFIGURATION
constant,
and can be changed to whatever you’d like to name your
configuration file (e.g.
log4php.ini
).
You can also configure
log4php
through an XML based
configuration file which tends to be a bit more readable
than the simple key-value format. Listing 4 shows an
example of the configuration from Listing 1 converted
to an XML configuration. Using XML, you get a better
feeling of what you’ve put into the different parts of
your configuration. In order to enable the use of an
XML based configuration file, you need to change that
class
log4php
uses to parse a configuration file. This is
done through the
LOG4PHP_CONFIGURATOR_CLASS
constant.
Listing 5 shows a complete sample script for using the
configuration from Listing 4.
If you do not get log messages from
log4php
, you
should check your setup once more. If
log4php

does not
find a resource needed for appending a logging event,
or your configuration is wrong, it will drop the logging
event and continue execution. This way, it does not
get in the way for your application. You should ensure
that you get the expected messages when you configure
log4php
the first time to verify your setup.
If you have problems with configuration you can
always turn on internal debugging in
log4php
by adding
log4php.debug = true
to your configuration file. This will
give more output about what
log4php
is actually doing.
If your configuration is wrong you will get warning
messages like this:
Warning: LoggerDOMConfigurator::tagOpen() APPENDER
cannot instantiate appender ‘default’
However, never leave this on by default; use it only
for debugging.
message. Standard log levels are
debug
,
info
,
warn
,

error
and
fatal
.
• A root logger is the base logger that log events
if a named logger does not exist, or when a
logging event is caught by another logger.
The root logger sits on the top of the logger
hierarchy.
To get started and be able try out some of the code in
this article, you should grab the latest version of
log4php

from

. After unpacking the archive,
you should add the
src
directory within
log4php
to your
include_path
so it is available from all scripts.
I will start with an absolute minimal “Hello World!”
example, to give you an idea of how the system works.
The first thing you need to do is to set up a
log4php

configuration file (see Listing 1). Save this code to a
file called

log4php.properties
. A minimal configuration
should contain at least a logger and an appender. I’ve
first defined an appender named “
default
” attaching the
LoggerAppenderEcho
class and giving it a simple layout
using the
LoggerLayoutSimple
class. I then attach the
appender to the root logger with the log level set to
DEBUG
.
Listing 2 contains a small script that makes use of this
configuration file. For simplicity, you should save this
code to a file in the same directory as the configuration
file, since
log4php
looks for the configuration file in the
same directory by default—more on this in a moment.
The first thing that is done here is to include the
LoggerManager
which is responsible for providing logger
instances that are defined by the configuration file. The
LoggerManager
operates as a singleton pattern, and the
configuration is read only once per request. The last
thing in this code is to get the root logger by calling
LoggerManager::getRootLogger()

and call its
debug()

function with a message.
Running this code will give you this result:
DEBUG - Hello World!
The most used functions for a logger are:
• debug()
- used for debug messages
• info()
- used in an informational context like
“username logged in” or “user typed wrong
password”
• warn()
- used when entering a potentially
harmful situation
• error()
- used when something goes wrong,
does not cause the application to terminate
(non-fatal)
• fatal()
- used for really bad situations where
execution must be aborted

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×