In a previous entry I wrote about passing and returning structured data using NuSOAP. While that approach worked when using a client written in the same version of NuSOAP, it didn’t work for more stringest clients which need well formed WSDL to create proxies for methods and structures.

After some more digging I discovered a couple of things:

  1. I was using version 0.6.4 of NuSOAP which I found via Google. That’s quite an old version and frankly doesn’t support WSDL well.
  2. After more searching, I found a more current version of NuSOAP on SourceForge.
  3. There don’t seem to be any official releases (yet), so simply download the latest version from the CVS repository.
  4. I used version 1.59 of nusoap.php and it worked for me without any problems.

So, make sure you use the latest version of NuSOAP from SourceForge in your application.

Note: The example this document links to has been updated 10/30/2003 to correct problems on PHP installation that emit warnings about unquoted string constants.

Using WSDL

Due to PHP’s loose typing, you have to epxlictly specify which types are being used by your functions. I believe you can do this with an external WSDL file. I describe the functional approach for registering the types. The following begins the WSDL configuration for a NuSOAP server object:

require_once('nusoap.php');
 
$NAMESPACE = 'http://books.org/Books';
 
$server = new soap_server;
$server->configureWSDL('Books', $NAMESPACE);
$server->wsdl->schemaTargetNamespace = $NAMESPACE;

Declaring Complext Types for WSDL

You use the addComplexType() method to register structures and arrays. The following code registers a structure Chapter which contains two members (a string title and an int page), an array of Chapter structures and a structure Book which has several members, including a chapter array.

$server->wsdl->addComplexType(
    'Chapter',
    'complexType',
    'struct',
    'all',
    '',
    array(
        'title' => array('name'=>'title','type'=>'xsd:string'),
        'page' => array('name'=>'page','type'=>'xsd:int')
    )
);
 
$server->wsdl->addComplexType(
    'ChapterArray',
    'complexType',
    'array',
    '',
    'SOAP-ENC:Array',
    array(),
    array(
        array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'tns:Chapter[]')
    ),
    'tns:Chapter'
);
 
$server->wsdl->addComplexType(
    'Book',
    'complexType',
    'struct',
    'all',
    '',
    array(
        'author' => array('name'=>'author','type'=>'xsd:string'),
        'title' => array('name'=>'title','type'=>'xsd:string'),
        'numpages' => array('name'=>'numpages','type'=>'xsd:int'),
        'toc' => array('name'=>'toc','type'=>'tns:ChapterArray')
    )
);

Registering Functions for WSDL

When you register functions with the NuSOAP server, you need to specify the incoming parameters/types and the return type. The following registers a function getBook that takes a string parameter title and returns a Book structure.

$server->register(
    'getBook',
    array('title'=>'xsd:string'),
    array('return'=>'tns:Book'),
    $NAMESPACE);

Accessing the WSDL

Once your WSDL specification is complete, you can examine it by passing the wsdl parameter to your PHP script. The script will return the generated WSDL which you can use in your tool to generate proxy classes, etc. Here is the WSDL for this example: http://www.nonplus.net/geek/samples/books.php?wsdl.

Implementing Functions

Using the WSDL specification, you can return SOAP structures as regular PHP associative arrays. When the server handles a SOAP request, it serializes and unserializes the PHP arrays using the WSDL description. The following function returns a book with two chapters (note that it’s blissfully unaware of SOAP):

function getBook($title) {
     // Create TOC
     $toc = array();
     $toc[] = array('title' => 'Chapter One', 'page' => 1);
     $toc[] = array('title' => 'Chapter Two', 'page' => 30);
  
     // Create book
     $book = array(
                 'author' => "Jack London",
                 'title' => $title,
                 'numpages' => 42,
                 'toc' => $toc);
  
     return $book;
}

Tying it All Together

The example books.php implements a SOAP server using the structures described above. It registers two methods getBook(title) and getBooks(author), the latter returns an array of Books. Make sure that you have a current version of NuSOAP installed when using the sample script.