SOAP, the Simple Object Access Protocol, is the powerhouse of web services. It’s a highly adaptable, object-oriented protocol that exists in over 80 implementations on every popular platform, including AppleScript, JavaScript, and Cocoa. It provides a flexible communication layer between applications, regardless of platform and location. As long as they both speak SOAP, a PHP-based web application can ask a C++ database application on another continent to look up the price of a book and have the answer right away. Another Internet Developer article shows how to use SOAP with AppleScript and Perl. SOAP was created collaboratively as an open protocol. Early in its development, XML-RPC was spun off, and now enjoys its own popularity as a simpler alternative to SOAP. Both encode messages as XML, and both use HTTP to transport those messages. SOAP, however, can use other transport protocols, offers a number of high-end features, and is developing rapidly. (For more about SOAP and web services, try XML.com’s helpful demystification.) A SOAP transaction begins with an application making a call to a remote procedure. The SOAP client script then encodes the procedure request as an XML payload and sends it over the transport protocol to a server script. The server parses the request and passes it to a local method, which returns a response. The response is encoded as XML by the server and returned as a response to the client, which parses the response and passes the result to the original function. There are a number of different implementations of SOAP under PHP. It’s a shifting landscape: new ones appear, and old ones aren’t maintained or simply vanish. As of this writing, the most viable PHP implementation of SOAP seems to be Dietrich Ayala’s SOAPx4, also known as NuSOAP. This implementation is the most commonly used and appears to be the most fully developed and actively maintained, and it shows every sign of continuing to be a robust and popular solution. It’s not complete—a number of features, including full documentation, are still in the works—but it’s still a highly viable and easy-to-use SOAP solution. InstallationFirst, you need to get PHP up and running on your Mac. This is easy to do: check out our tutorial to get yourself set up. If you want to send SOAP messages over HTTPS, you’ll need to include the cURL module in your PHP build. The next step is to install NuSOAP. Download the package from the developer’s site. Unzip it to get a folder of documentation, as well as the file nusoap.php, which contains the actual PHP classes that we’ll need. To use them, place nusoap.php in your PHP path and include it in the scripts you write. The base class is A SOAP ServerHere is a simple server, written in PHP, that takes an ISBN (International Standard Book Number) as input, performs a lookup in an imaginary database, and returns the price of the corresponding book. In it, I use the <?php // function to get price from database function lookup($ISBN) { $query = "select price from books where isbn = ". $ISBN; if (mysql_connect("localhost", "username", "passwd")) else { $error = "Database connection error"; return $error; } if (mysql_select_db("books")) else { $error = "Database not found"; return $error; } if ($result = mysql_query($query)) else { $error = "mysql_error()"; return $error; } $price = mysql_result($result, 0, 0); return $price; } // include the SOAP classes require_once('nusoap.php'); // create the server object $server = new soap_server; // register the lookup service $server->register('lookup'); // if the lookup fails, return an error if $price == 0 { $error = "Price lookup error"; } if (isset($error)) { $fault = $server->fault('soap:Server','http://mydomain.com/booklookupscript.php',$err or); } // send the result as a SOAP response over HTTP $server->service($HTTP_RAW_POST_DATA); ?> The first method I use is the register(name, in, out, namespace, SOAPAction, style) The first parameter is the only mandatory one. So, the function is executed, and the returned value is passed to the server object. Then the Dealing with ErrorsBecause databases are not perfect, the script has a series of steps to catch errors. The If any one of these traps finds an error, NuSOAP’s fault(faultcode, faultactor, faultstring, faultdetail) The first two arguments are required, the latter two are optional. For the The
A SOAP ClientNow I’ll write a client for an existing SOAP server, so you can see it in action. I’ll use XMethods’ Barnes & Noble Price Quote server, which acts a lot like the example server, above. It takes an ISBN as input and returns price data from Barnes & Noble. The client script will need to send a request containing an ISBN and then parse the response. In this script, I use the <?php // include the SOAP classes require_once('nusoap.php'); // define parameter array (ISBN number) $param = array('isbn'=>'0385503954'); // define path to server application $serverpath ='http://services.xmethods.net:80/soap/servlet/rpcrouter'; //define method namespace $namespace="urn:xmethods-BNPriceCheck"; // 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 $". $price; } // kill object unset($client); ?> The The parameters for The A Closer Look at the TransactionThe actual XML message sent by the client to the server looks something like this: <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body> <ns1:getPrice xmlns:ns1="urn:xmethods-BNPriceCheck" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <isbn xsi:type="xsd:string">0385503954</isbn> </ns1:getPrice> </SOAP-ENV:Body> </SOAP-ENV:Envelope> The The schema definition is set automatically by NuSOAP to $XMLSchemaVersion = 'http://www.my.org/MYSchema/'; Detailed discussion of the ins and outs of the W3C’s XML schema can be found in O’Reilly’s new book on the subject. Within the The encoding style is set by default to $namespaces[SOAP-ENC] = 'http://my.special.encoding'; The same technique can be used to change other namespace values, if necessary. The keys of the The server’s XML response to the request looks like this: <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <SOAP-ENV:Body> <ns1:getPriceResponse xmlns:ns1="urn:xmethods-BNPriceCheck" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <return xsi:type="xsd:float">14.65</return> </ns1:getPriceResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> The envelope is pretty much the same as that of the request, though you’ll notice that the server uses an older XML schema than the client. The body is also similar: the method namespace and the encoding style are the same. The ConclusionNuSOAP makes working with SOAP very easy by automatically handling the complexity, although it also provides a fair amount of access to the flexibility and nuance underneath. The call method of the To learn more about the details of working with SOAP, refer to the SOAP specification and the API documentation that comes with NuSOAP. If you encounter a specific question about how NuSOAP handles SOAP transactions, it can be helpful to look at the nusoap.php file, which is clearly organized by class and decently commented. Going to the source, as it were, should answer most questions. |