Introduction to NuSOAP

NuSOAP is a group of PHP classes that allow developers to create and consume SOAP web services. It does not require any special PHP extensions. The current release version (0.6.7) of NuSOAP at the time this was written (03-November-2004), supports much of the SOAP 1.1 specification. It can generate WSDL 1.1 and also consume it for use in serialization. Both rpc/encoded and document/literal services are supported. However, it must be noted that NuSOAP does not provide coverage of the SOAP 1.1 and WSDL 1.1 that is as complete as some other implementations, such as .NET and Apache Axis.

This document describes how to obtain and install NuSOAP, then provides some samples to illustrate the capabilities of NuSOAP. It is by no means an exhaustive description of NuSOAP, but it is hopefully enough to get any PHP coder started. Programming with NuSOAP follows this up with more complex samples.

Installation
Hello, World
Debugging
Request and Response
Resources

Installation

The NuSOAP project is hosted by SourceForge. You can obtain NuSOAP either as a downloadable release or from the CVS tree of the NuSOAP project on SourceForge. A browser-based CVS interface is provided. As an example, you can obtain version 1.81 of nusoap.php with the following URL: http://cvs.sourceforge.net/viewcvs.py/*checkout*/nusoap/lib/nusoap.php?rev=1.81. You can start working with the version of the code you choose. I have run the samples below with version 1.81.

Once you have downloaded a copy of nusoap.php, you simply need to place it in your code tree so that you can include it from your PHP code. Some users put in it a separate lib directory. For my examples, I placed it in the same directory as the sample code itself.

Return to top.

Hello, World

Showing no imagination whatsoever, I will start with the ubiquitous "Hello, World" example. This will demonstrate the basic coding of NuSOAP clients and servers.

I will start with the server code, since without a server there is no need to have any client. The server exposes a single SOAP method named Hello, which takes a single string parameter for input and returns a string. Hopefully, the comments within the code provide sufficient explanation! For the simplest services, all that will change are the functions being defined and registered.

<?php
// Pull in the NuSOAP code
require_once('nusoap.php');
// Create the server instance
$server = new soap_server;
// Register the method to expose
$server->register('hello');
// Define the method as a PHP function
function hello($name) {
    return 'Hello, ' . $name;
}
// Use the request to (try to) invoke the service
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>

The client for this service is below. There are a few important things to note. First, when the instance of soapclient is created, the parameter specified is the URL to the service. In my case, helloword.php is accessed from http://localhost/phphack. The services you consume will, of course, be located at different URLs. Second, when calling the service, the first parameter is the service name. This must match the case-sensitive name of a method available on the server. In this example, it must match the method registered within helloworld.php. Finally, the second parameter in the call is an array of parameters that will be passed to the SOAP service method. Since the hello method of helloworld.php requires a single parameter, this array has one element.

<?php
// Pull in the NuSOAP code
require_once('nusoap.php');
// Create the client instance
$client = new soapclient('http://localhost/phphack/helloworld.php');
// Call the SOAP method
$result = $client->call('hello', array('name' => 'Scott'));
// Display the result
print_r($result);
?>
Return to top.

Debugging

As with all programming, there are times when you will have problems you need to debug. NuSOAP provides a couple of facilities to help with that. With SOAP, a very typical step in debugging is to view the request being sent and response being returned. The NuSOAP soapclient class has members named request and response that allow you to view these. For example, here is a modified version of the helloworldclient.php that displays the request and response. In the next section, I will review the structure of the request and response displayed by this client code.

<?php
// Pull in the NuSOAP code
require_once('nusoap.php');
// Create the client instance
$client = new soapclient('http://localhost/phphack/helloworld.php');
// Call the SOAP method
$result = $client->call('hello', array('name' => 'Scott'));
// Display the result
print_r($result);
// Display the request and response
echo '<h2>Request</h2>';
echo '<pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
echo '<h2>Response</h2>';
echo '<pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
?>

NuSOAP also provides a means to view debug information logged throughout its classes. Adding the following to the client code will display this verbose debugging information. Unfortunately, interpretation of the output must be left to the reader.

// Display the debug messages
echo '<h2>Debug</h2>';
echo '<pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';

The server can provide similar debugging. Interestingly, the debug text is written as an XML comment at the end of the SOAP response, so it can be viewed by displaying the response at the client. The server with debugging enabled looks like this.

<?php
// Pull in the NuSOAP code
require_once('nusoap.php');
// Enable debugging *before* creating server instance
$debug = 1;
// Create the server instance
$server = new soap_server;
// Register the method to expose
$server->register('hello');
// Define the method as a PHP function
function hello($name) {
    return 'Hello, ' . $name;
}
// Use the request to (try to) invoke the service
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>

A third means of debugging is not really debugging at all. It is simply good programming practice. The examples above have not checked for errors occurring during the SOAP call. A more robust client would look like the following.

<?php
// Pull in the NuSOAP code
require_once('nusoap.php');
// Create the client instance
$client = new soapclient('http://localhost/phphack/helloworld.php');
// Check for an error
$err = $client->getError();
if ($err) {
    // Display the error
    echo '<p><b>Constructor error: ' . $err . '</b></p>';
    // At this point, you know the call that follows will fail
}
// Call the SOAP method
$result = $client->call('hello', array('name' => 'Scott'));
// Check for a fault
if ($client->fault) {
    echo '<p><b>Fault: ';
    print_r($result);
    echo '</b></p>';
} else {
    // Check for errors
    $err = $client->getError();
    if ($err) {
        // Display the error
        echo '<p><b>Error: ' . $err . '</b></p>';
    } else {
        // Display the result
        print_r($result);
    }
}
?>

To test this code, cause an error to happen, such as by changing the name of the method to invoke from 'hello' to 'goodbye'.

Return to top.

Request and Response

I showed above how easy it is to display the SOAP request and response. Here is what the request from the helloworld2client.php looks like.

POST /phphack/helloworld2.php HTTP/1.0
Host: localhost
User-Agent: NuSOAP/0.6.8 (1.81)
Content-Type: text/xml; charset=ISO-8859-1
SOAPAction: ""
Content-Length: 538

<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope
  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:si="http://soapinterop.org/xsd">
 <SOAP-ENV:Body>
  <ns1:hello xmlns:ns1="http://testuri.org">
   <name xsi:type="xsd:string">Scott</name>
  </ns1:hello>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

In the HTTP headers, you will notice that the SOAPAction is an empty string. This is simply the default. Your service methods can be assigned to a SOAPAction, and your client code can specify a SOAPAction as one of the parameters to the call method.

In the XML payload, you see that NuSOAP uses ISO-8859-1 character encoding, also known as Latin-1. To specify a different encoding, you set the soap_defencoding property on the soapclient instance. It is the programmer's responsibility to encode the parameter data correctly using the specified encoding. Fortunately, PHP provides functions for encoding and decoding data using the most common encoding in SOAP, UTF-8.

Another thing to note is that the element specifying the method call, the element named hello, has been placed in the http://tempuri.org namespace. It is better practice, and necessary with many services, to specify the actual namespace in which the method is defined. This will be shown in a future document.

The response from the SOAP service looks like this.

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Wed, 03 Nov 2004 21:32:34 GMT
X-Powered-By: ASP.NET
X-Powered-By: PHP/4.3.4
Server: NuSOAP Server v0.6.8
X-SOAP-Server: NuSOAP/0.6.8 (1.81)
Content-Type: text/xml; charset=ISO-8859-1
Content-Length: 556

<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope
  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:si="http://soapinterop.org/xsd">
 <SOAP-ENV:Body>
  <ns1:helloResponse xmlns:ns1="http://tempuri.org">
   <return xsi:type="xsd:string">Hello, Scott</return>
  </helloResponse>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Return to top.

You can download the source for this example as well.

Return to top.

Resources

Join the NuSOAP mailing list to learn more and ask questions.
The home of the NuSOAP project.
NuSOAP home of Dietrich Ayala, the author of NuSOAP.
Consuming MapPoint Web Service in PHP on MSDN.

Return to top.

Copyright © 2003-2004 Scott Nichol.
03-Nov-2004