Creating a web service and WSDL using NuSOAP

Well if you have followed the previous post on using NuSOAP to create an amazon web service then you might be interested in using NuSOAP to create a web service of your own (i.e. a server component rather than a client component). I decided to create one myself to allow me to create a .Net application to help me maintain my walks database.

Getting Started

As before, go get NuSOAP and download into a directory. Then create a file called “mywsdl.php” for example.

The first thing I did was to set a namespace for my web service. This makes my web service unique and identifiable. The namespace does not have to be a URL but if you make it a URL things can be a lot easier.

$namespace = "http://www.wackylabs.net/wsdl

Next we need to create the server object and start to program against it:

require("nusoap.php");
$server = new soap_server();
$server->debug_flag = false;
$server->configureWSDL("WackyWsdl", $namespace);
$server->wsdl->schemaTargetNamespace = $namespace;

Creating your data types

There are three main types of data you will be using. Built in types can be used without being declared. The other two are slightly more complicated, structures and arrays.

First lets look at an example structure:

$server->wsdl->addComplexType(
  'Walk',
  'complexType',
  'struct',
  'all',
  '',
  array(
    'WalkId' => array('name' => 'WalkId',
         'type' => 'xsd:int'),
    'WalkTitle' => array('name' => 'WalkTitle',
         'type' => 'xsd:string'),
    'WalkDate' => array('name' => 'WalkDate',
        'type' => 'xsd:date')
    'WalkDescription' => array('name' => 'WalkDescription',
        'type' => 'xsd:string')
  )
);

This is quite a complicated function, and from the source code we see that the parameters are as follows:

  • 1: name
  • 2: typeClass (complexType|simpleType|attribute)
  • 3: phpType: currently supported are array and struct (php assoc array)
  • 4: compositor (all|sequence|choice)
  • 5: restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
  • 6: elements = array ( name = array(name=>”,type=>”) )
  • 7: attrs = array(array(‘ref’ => “http://schemas.xmlsoap.org/soap/encoding/:arrayType”, “http://schemas.xmlsoap.org/wsdl/:arrayType” => “string[]”))
  • 8: arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)

The first is simply the name you want to define (in the context of the ‘targetNamespace’ defined above.
The next is the type. simpleType is usually based on another type with restrictions (e.g. a string with max length of 4 or some such other restriction), complexTypes usually have more than one subelement (as above).
The phpType, as specified is either array or struct.
The compositor is a way of defining how the subelements of the current element work, are they either all optional element, to be included in any order (all), optional but only to be allowed in the given order (sequence) or only one of them is allowed at any one time (choice).
The restrictionBase and attrs and arrayType we shall cover later when we talk about support for arrays.
The elements item is an array containing a list of subelement, each of which has a name and a type.

The above example defines a type called “Walk” which is effectively a struct, containing 4 fields, WalkId, WalkTitle, WalkDate and WalkDescription. It is a complex type and all elements can be included in any order. WalkId is a integer, WalkTitle and WalkDescription are strings and WalkDate is a date field.

What about list of walks

The next think you might want to do is return a list of walks matching some criteria (e.g. latest 10 walks). For this we use the array data type:

$server->wsdl->addComplexType(
  'Walks',
  'complexType',
  'array',
  '',
  'SOAP-ENC:Array',
  array(),
  array(
    array('ref' => 'SOAP-ENC:arrayType',
         'wsdl:arrayType' => 'tns:Walk[]')
  ),
  'tns:Walk'
);

Here the php type is array instead of struct. The compositor is blank and the restrictionBase is ‘SOAP-ENC:Array’. This tells the system that your complex type is based on the Array type defined within the soap-encoding namespace. The elements parameter is then a blank array and the attrs parameter is an array defining the type of the array and the parameter defines the type of the elements within the array (as you can see, these are usually the same except for the [] part after the array definition.

Do some work!

Well so far we’ve defined the types of data (or some extra ones not already defined) that we want to pass in and out of your web service. Next we define the actual operation the web service will support.

$server->register('GetWalk',                    // method name
  array('WalkId' => 'xsd:int'),          // input parameters
  array('return' => 'tns:Walk'),    // output parameters
  $namespace,                         // namespace
  $namespace . '#GetWalk',                   // soapaction
  'rpc',                                    // style
  'encoded',                                // use
  'Get Specific Walk'        // documentation
);

Here we define a method which will input a integer, defining the walk id and get passed back a Walk data struct (containing the id, title, description and date). We again define the namespace and I’ve set the action to the namespace + “#GetWalk” which is the method name.

We define a normal php function to actually do the work:

function GetWalk($walkid)
{
  return array(
    "WalkId" => $walkid,
    "WalkTitle" => "Title of my long walk",
    "WalkDate" => date("Y-m-d", time()),
    "WalkDescription" => "Really long walk description"
  );
}

Dates should be in ISO international format CCYY-MM-DD HH:MM:SS with an optional timezone attached at the end (or shorted as in this example).

Finally, we pass whatever data the php page receives into the soap processor and see what happens:

// Use the request to (try to) invoke the service

$HTTP_RAW_POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA'])
  ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
$server->service($HTTP_RAW_POST_DATA);
exit();

If you now browse to your completed webpage you should find you are presented with a nice page listing the operations supported and the parameters, as well as a link to the wsdl which can be used with code generation tools (such as wsdl.exe with .Net or the java equivalent) to generate client code for your wsdl.

Comments welcome as usual.

26 thoughts on “Creating a web service and WSDL using NuSOAP”

  1. Thanks, I’ve been trying to get started with nusoap for a little while (writing a C# app for windows to manage a vpopmail/qmail server using nusoap in php on the mail server).

    With your tutorial in mind I have written a php/nusoap server for vpopmail’s functions proxied to my app.

  2. I’m having problem returning a an array of structas result to the client.
    I mean the XML-SOAP result seams to be not well formatted …. inthat using IE and flash I do not get the content using Netscape and flash complex I get the result. I seams that Netscape doesn’t care about the not well-format response . For Inernet Explorer it is a problem.
    If you have any sudjest pls. contact me.
    Thanks TonY.

  3. Hi,

    Excellent tutorial. Quick question, I’ve developed an image manipulation engine that I’m interested in deploying as a service accessible to Flickr folk. Can you please say a bit about how to handle a SOAP payload that is an actual image? Thanks.

    Perhaps I can make use of your work to accomplish this.

    See some of my examples on Flickr in my Elastic Imagery set.

    Cheers,
    Douglass Turner
    voice/sms: +354 895 5077

  4. Nice tutorials mate :)
    but can you show us the code for extracting data from the databse like walkID, walkdate etc…

    looking forward to hear from you ….
    Mo

  5. how can we write a java client for a webservice developed using php NuSoap,if u could give me an example for this,it would be appreciated

  6. can we register not a normal php function ?
    I mean, we register some method in our class.

    I was try but still got some errors, like:
    Error: Server: method ‘GetListUser’ not defined in service

  7. I’d have to say I have no idea – you could put a dummy function in place which then just calls your class method – hope that helps.

  8. The above example is all well and good, but what if from the client:
    1) I am sending in a nested array
    2) The nested array isn’r defined e.g. as below, I could send in numerous items.
    How could I define a struct for a nested array with as constantly differing amount of parameters??

    $param_couriers=array(
    ‘general_data’=>array(
    ‘customer_db’=>’chesweb’,
    ‘residence_cntryID’=>’202’,
    ‘delivery_cntryID’=>’202’,
    ‘basket_total’=>’3526’,
    ‘weight_total’=>’60’,
    ‘extra_items’=>’no’
    ),
    ‘items’=>array(
    ‘item_1’=>array(‘item_price’=>’100’),
    ‘item_2’=> array(‘item_price’=>’75’)
    )
    );

  9. I came across the same problem of needing to register a class function in my soap server, after trauling through the nusoap code ive found it is quite possible. nusoap expects you to register the name as “class.method” (note the dot) and to also call the full class.method path in your cilent side requests.

    This appears to call the function statically so if your class is your soap server, then i recommend you register a reference to the object in your globals so you have access to the objects contents again once those functions are called

  10. Thank you very much for your tutorial. It cleared up alot of the mystery of complex parameter passing. However, my question is how do you pass an array of simple type? I’m trying to pass an array of int to my Excel VBA client and having great difficulty in getting it to read the data returned from my nuSoap server correctly. My php client has no problem, but i rather think that’s because php is loosely typed. Do you have a sample of how to pass back simple arrays?

    Thank you very much for your help.

  11. Sorry to have bothered you. I figured it out – the issues was with my VBA code, not my SOAP encoding.

    Thanks

  12. This was a great tutorial. I was looking how to define an array if complex types and this just helped me out. Really appreciated!

  13. This is a great tutorial, thanks alot, wonder if you have any example in handling UTF8 encoding as well?

  14. I am looking to implement a NuSOAP/ php web service. I am concerned about the type of arrays that can be passed to NuSOAP when using the register method. Can you have array’s with complex structures? That is an array where the variables are also arrays?

Comments are closed.