. 89
( 132 .)


parses it, and presents it to the user.
Our goal is to use the Web services made available by a couple of providers ” the
Barnes & Noble bookstore and the Babelfish translation service ” to gather infor-
mation. Specifically, we use the Barnes & Noble service to gather information about
books that interest us, and the Babelfish service to translate a passage of text from
English into a series of European languages.
The Barnes & Noble application takes an International Standard Book Number
(ISBN) and returns the price of the book identified by that number at Barnes &
Noble™s Web site, www.bn.com. If you send it the value 0440234816, which is the
ISBN of Karen Marie Moning™s novel To Tame a Highland Warrior, you can expect
to see the following output from your local PHP program:

The price of book number 0440234816 is $6.99.

That price really is a bargain for “a medieval romance with paranormal overtones.”
528 Part IV: Not So Simple Applications

The Babelfish application (http://babelfish.altavista.com) enables you to
translate a phrase from English to French, German, Italian, Spanish, or Portuguese.
By default, the program is set up to send the value From beneath you, it devours
to Babelfish. The application gives you the following translations, which are vari-
ously accurate. Generally, if you see the English word in the translation, it means
Babelfish was stumped.

— French ” De sous vous, il devours.

— German ” Von unter Ihnen es devours.

— Italian ” Sotto da voi, esso devours.

— Spanish ” Debajo de usted, ©l devours.

— Portuguese ” Abaixo de você, ele devours.

Clearly, Babelfish has problems with devours.
The interesting aspect of this is that everything is done with Web services. You
send parameters (the ISBN in the former example, and the target language and
original phrase in the latter), and the Web services (which aren™t hosted locally, per-
haps obviously) return the strings you need.
How does it work? The answer to this question requires a deeper exploration of
our application™s code, which follows in the next section.

Code Breakdown
To see what™s going on in the two applications, you have to take a close look at the
PHP code itself. Both the Babelfish application and the Barnes & Noble application
are clients ” they exist for the purpose of talking to servers that are implemented
somewhere else.
In this case, both of them speak to servers on XMethods (www.xmethods.com or
www.xmethods.net), a site that hosts a number of Web services for the purposes of
testing and experimentation. You don™t need to know how those remote services are
implemented. They could be in Java, C, or PHP. It really makes no difference to you,
because they™re set up to work with SOAP requests from over the Internet.

The Barnes & Noble application
The Barnes & Noble client sends an ISBN value (which uniquely identifies a book in
print) to a Web service, which returns the selling price of the corresponding book
on the Barnes & Noble Web site, www.bn.com. It prints out a simple string, indicat-
ing either the price of the book, the fact that www.bn.com doesn™t list the book, or
the fact that there was an error in the execution of the Web service.
Chapter 16: SOAP 529

Many of the files in the Barnes & Noble and Babelfish applications call a header file
initially. The header file, header.php, does two important things. First, it imports the
critical nusoap.php file. It also specifies how the local applications deal with errors.
Here is header.php:


function soap_errors()
$oh = set_error_handler(˜error_handler™);
if (empty($oh))
set_handler(0, H_ERROR);
set_handler(E_ALL, H_LOG);


// include the class and function definitions for this application

The client file actually handles the process of instantiating a SOAP client that con-
nects to a publicly accessible Web service providing Barnes & Noble prices (really,
it just tells NuSOAP to do the dirty work). Here it is:

// include the SOAP classes
// define parameter array (ISBN number)
$param = array(˜isbn™=>™0385503954™);
// define path to server application
//define method namespace
530 Part IV: Not So Simple Applications

// create client object
$client = new soapclient($serverpath);
// make the call
$price = $client->call(˜getPrice™,$param,$namespace);
// if a fault occurred, output error info
if (isset($fault)) {
print “Error: “. $fault;
else if ($price == -1) {
print “The book is not in the database.”;
} else {
// otherwise output the result
print “The price of book number “. $param[˜isbn™] .” is $”.
// kill object

So, what™s going on here? Some of it should look familiar. First of all, the pro-
gram defines an array:

$param = array(˜isbn™=>™0385503954™);

Then, it sets a variable ($serverpath) that contains, as a string, a URL:


What™s that URL? Well, if you call it up in an ordinary browser, you get an error.
The error says, in effect, that you can™t use a browser in this situation because this
isn™t a document at all ” it™s a remote procedure call (RPC) router. As such, you have
to send it text (that is, SOAP XML) via the HTTP POST command. This makes sense,
because you want to send something from your client to the remote Web service.
Then you specify, on that remote site, the namespace you™re working with. This
line of code serves that purpose:


The purpose of the reference to that site is to examine the Web Services
Description Language (WSDL) file that exists there. WSDL describes the Web services
that exist at a particular site, and the particular methods they expose. You know that
BNPriceCheck is a meaningful namespace on XMethods because you saw it adver-
tised at http://services.xmethods.net. (It™s also described programmatically at
Chapter 16: SOAP 531

The next line should look familiar. It™s the instantiation of a NuSOAP soapclient
object that™s bound to the XMethods RPC router:

$client = new soapclient($serverpath);

With all that done, you can make a call to the remote service, expecting a single
value in return:

$price = $client->call(˜getPrice™,$param,$namespace);

That line invokes the call() function of the local soapclient object (as con-
tained in the $client handle). It sends along three arguments:

— getPrice ” The name of the function you are calling

— $param ” The struct you established earlier, containing the ISBN value

— $namespace ” The namespace you got from the WSDL file, making it clear
to the RPC router that you want to send your query to the Barnes & Noble

After the request goes off ” and remember, it™s the job of NuSOAP to manage the
mechanics of sending the request over HTTP (using POST) and dealing with the
response when it comes ” you have only to react to the string that you get back.
It™ll be one of three things: An indication that the service experienced an error, an
indication that the ISBN you sent doesn™t correspond to a book in the database, or
a price value. Here™s the code that figures out which:

if (isset($fault)) {
print “Error: “. $fault;
else if ($price == -1) {
print “The book is not in the database.”;
} else {
print “The price of book number “. $param[isbn] .” is $”.

From that code you see that you™re expecting a floating-point value if the book
is in the database, or -1 if it™s not. If a variable called $fault (defined in NuSOAP)
exists, it means there was a problem in the service™s execution and an error field in
the Header element of the SOAP response was used (have a look at the SOAP spec-
ification for information on how Header elements indicate error conditions).
532 Part IV: Not So Simple Applications

Be aware that floating-point values have some risk with respect to precision.
If you work with lots of numbers, rounding errors can occur, and when the
errors represent money, you can be in big trouble! Use the math functions to
guarantee precision if you have to, but don™t worry about it here ” it™s not a

The Babelfish application
The Babelfish applications (there are three of them on the CD-ROM) are also
SOAP clients, similarly concerned with talking to a Web service made available on
the XMethods experimental site. The difference between these applications and
the Barnes & Noble application, though, is that the Babelfish applications rely
on the WSDL file exposed at XMethods (www.xmethods.com or www.xmethods.net)
to learn about the Web service.
For discussion purposes, consider babel.php, the simplest of the Babelfish SOAP
clients. The others vary mainly in that they do the same thing several times for dif-
ferent languages. Here is babel.php:


$client = new soapclient(
, ˜wsdl™
$proxy = $client->getProxy();

$languages = array(
˜English™ => ˜en™
, ˜French™ => ˜fr™
, ˜German™ => ˜de™
, ˜Italian™ => ˜it™
, ˜Spanish™ => ˜es™
, ˜Portugese™ => ˜pt™

$phrase = ˜From beneath you, it devours.™;

foreach ($languages as $language => $lc)
if ($language == ˜English™)
Chapter 16: SOAP 533

$result = $proxy->BabelFish(˜en_™.$lc, $phrase);
$result = $proxy->BabelFish($lc.™_en™, $result);
$result = $proxy->BabelFish(˜en_™.$lc, $result);
$result = $proxy->BabelFish($lc.™_en™, $result);
print “English <-> $language : $result\n”;

The most readily obvious difference between this and the Barnes and Noble
application is that the soapclient object (again, part of NuSOAP) uses a construc-
tor that™s different from the ones you saw earlier in this chapter. The soapclient
constructor used here makes reference to a WSDL file:

$client = new soapclient(
, ˜wsdl™

What™s that all about? Have a look at the WSDL file. It™s an XML file itself, so you
can call it up in your browser (or a text editor, if your browser won™t show XML
readably) if you like. The most interesting part of the file, for your purposes, is this


. 89
( 132 .)