Repeating same name parameters with nusoap

This article assumes you have a background with nusoap. Start by reading a nusoap tutorial or two, suggest http://www.zend.com/zend/tut/tutorial-campbell.php and http://www.scottnichol.com/nusoapprogwsdl.htm

I’m going to setup a soap server to except parameters. The method will do something silly, the point is to understand how to make a client with nusoap, when the server excepts repeating, same name parameters. This came up for me recently, and I struggled with it for hours, never did find a good explaination of it online, so I’m writing this for the next guy.

Imagine the request is going to look like this:

XML Diagram 1:

<CountBasketItems>
<Basket>
<fruits>
<fruit>
<name>Apple</name>
<color>red</color>
</fruit>
<fruit>
<name>Bananna</name>
<color>yellow</color>
</fruit>
<fruit>
<name>Apple</name>
<color>green</color>
</fruit>
</fruits>
<vegetables>
<vegetable>
<name>Orion</name>
<color>yellow</color>
</vegetable>
<vegetable>
<name>Carot</name>
<color>orange</color>
</vegetable>
<vegetable>
<name>Orion</name>
<color>red</color>
</vegetable>
</vegetables>
</Basket>
</CountBasketItems>

The real question is: how do I setup my parameter array to accommodate this. The answer:

$fruits = array();
$fruits[] = array(‘name’ => ‘Apple’, ‘color’ => ‘red’);
$fruits[] = array(‘name’ => ‘Bananna’, ‘color’ => ‘yellow’);
$fruits[] = array(‘name’ => ‘Apple’, ‘color’ => ‘green’);

$vegetables = array();
$vegetables[] = array(‘name’ => ‘Orion’, ‘color’ => ‘yellow’);
$vegetables[] = array(‘name’ => ‘Carrot’, ‘color’ => ‘orange’);
$vegetables[] = array(‘name’ => ‘Orion’, ‘color’ => ‘red’);

$basket = array ( ‘fruits’ => $fruits, ‘vegetables’ => $vegetables );

Here is what $basket looks like when I run print_r($basket):

Array
(
[fruits] => Array
(
[0] => Array
(
[name] => Apple
[color] => red
)
[1] => Array
(
[name] => Bananna
[color] => yellow
)
[2] => Array
(
[name] => Apple
[color] => green
)
)
[vegetables] => Array
(
[0] => Array
(
[name] => Orion
[color] => yellow
)
[1] => Array
(
[name] => Carrot
[color] => orange
)
[2] => Array
(
[name] => Orion
[color] => red
)
)
)

Here is a complete example, server and client:

server.php:


configureWSDL('maxfruitwsdl', 'urn:maxfruitwsdl');
// Put the WSDL schema types in the namespace with the tns prefix
$server->wsdl->schemaTargetNamespace = 'urn:maxfruitwsdl';
// Register the data structures used by the service
$server->wsdl->addComplexType(
'Fruit',
'complexType',
'struct',
'all',
'',
array(
'name' => array('name' => 'name', 'type' => 'xsd:string'),
'color' => array('name' => 'color', 'type' => 'xsd:string'),
)
);
$server->wsdl->addComplexType(
'Fruits',
'complexType',
'array',
'',
'SOAP-ENC:Array',
array(),
array(
array('ref' => 'SOAP-ENC:arrayType', 'wsdl:arrayType' => 'tns:Fruit[]')
),
'tns:Fruit'
);
$server->wsdl->addComplexType(
'Vegetable',
'complexType',
'struct',
'all',
'',
array(
'name' => array('name' => 'name', 'type' => 'xsd:string'),
'color' => array('name' => 'color', 'type' => 'xsd:string'),
)
);
$server->wsdl->addComplexType(
'Vegetables',
'complexType',
'array',
'',
'SOAP-ENC:Array',
array(),
array(
array('ref' => 'SOAP-ENC:arrayType', 'wsdl:arrayType' => 'tns:Vegetable[]')
),
'tns:Vegetable'
);

$server->wsdl->addComplexType(
'Basket',
'complexType',
'struct',
'all',
'',
array(
'fruits' => array('name' => 'fruits', 'type' => 'tns:Fruits'),
'vegetables' => array('name' => 'vegetables', 'type' => 'tns:Vegetables'),
)
);

// Register the method to expose
$server->register('CountBasketItems', // method name
array('Basket' => 'tns:Basket'), // input parameters
array('return' => 'xsd:int'), // output parameters
'urn:maxfruitwsdl', // namespace
'urn:maxfruitwsdl#CountBasketItems', // soapaction
'rpc', // style
'encoded', // use
'Return the number of items in the basket' // documentation
);

function CountBasketItems( $basket )
{
return count($basket['fruits']) + count($basket['vegetables']);
}

// This returns the result
$server->service($HTTP_RAW_POST_DATA);
?>

client.php


 'Apple', 'color' => 'red');
$fruits[] = array('name' => 'Bananna', 'color' => 'yellow');
$fruits[] = array('name' => 'Apple', 'color' => 'green');

$vegetables = array();
$vegetables[] = array('name' => 'Orion', 'color' => 'yellow');
$vegetables[] = array('name' => 'Carrot', 'color' => 'orange');
$vegetables[] = array('name' => 'Orion', 'color' => 'red');

$basket = array ( 'fruits' => $fruits, 'vegetables' => $vegetables );

print "

My Basket:

"; echo str_replace(' ', ' ', nl2br(htmlspecialchars(print_r($basket, true)))); // Create the client instance $client = new soapclient('http://www.modphp.org/nusoap/server.php?wsdl', true); // Check for an error $err = $client->getError(); if ($err) { // Display the error echo '

Constructor error

' . $err . '

';
// At this point, you know the call that follows will fail
}
// Create the proxy
$proxy = $client->getProxy();
// Call the SOAP method
$result = $proxy->CountBasketItems($basket);

// Check for a fault
if ($proxy->fault) {
echo '

Fault

';
print_r($result);
echo '

';
} else {
// Check for errors
$err = $proxy->getError();
if ($err) {
// Display the error
echo '

Error

' . $err . '

';
} else {
// Display the result
echo '

Result of CountBasketItems

';
print_r($result);
echo '

';
}
}
// Display the request and response
echo '

Request

';
echo str_replace(' ', ' ', nl2br(htmlspecialchars($proxy->request, ENT_QUOTES)));
echo '

Response

';
echo str_replace(' ', ' ', nl2br(htmlspecialchars($proxy->response, ENT_QUOTES)));
// Display the debug messages
echo '

Debug

';
echo str_replace(' ', ' ', nl2br(htmlspecialchars($proxy->debug_str, ENT_QUOTES)));
?>

The result of running the “client.php” is here: http://www.modphp.org/nusoap/client.php

And, if you want to see the interface for the server, look here: http://www.modphp.org/nusoap/server.php

Worth noting… I am going to redo this article soon, so that my server will except an input array that looks like this:

$basket = array ( ‘fruits’ => array( ‘fruit’ => $fruits), ‘vegetables’ => array(‘vegetable’ => $vegetables) );

… this would more closely resemble the structure envisioned in “XML Diagram 1″ above. It’s not until just now, after writing this, that I noticed this mistake. But, it means I need to redo my server and example. I’ll fix soon.

Dave

Comments are closed.