WSDL Generation with WSF/PHP - Arrays and Complex types

Wednesday, February 13, 2008

When you are working on code first approach you want to derive the contract WSDL from the code that you already have for the Web Service.

If you may have worked on Java or .NET Web Services you already familiarized with this approach. PHP developers are also provided the opportunity to work on this approach with WSF/PHP. You only need to give a simple introduction for your service operations and their parameter types as annotations, and you will get the WSDL generated in a flash.

Here is how you will put the annotations for a simple operation like add.

<?php

/**
* operation add
* @param int $x operand1 <- This is the PHP type
* maps to xs:int <- This is the schema type
* @param int $y operand2 <- This is the PHP type
* maps to xs:int <- This is the schema type
* @return int $result
*/

function add($x, $y)

{
return array("result" => $x + $y);

}

$operations = array("add" => "add");
$opParams = array("add" => "MIXED");


$svr = new WSService(array("operations" => $operations,
"opParams" => $opParams,
"serviceName" => "Calculator"));


$svr->reply();

?>
Here just examine how the operation parameters are described. If this is not clear you can have a look at the wsdl generation manual[http://wso2.org/project/wsf/php/1.2.0/docs/wsdl_generation_api.html]. It describe the annotation format in a simple fashion.

Anyway in WSF/PHP 1.2.0 you didn't have a way to specify when the input/output parameters are arrays. But in the upcomming 1.2.1 release you will get this facility.

For an example you can add an operation to add vectors like this,

/**
* operation addVectors
* @param array of int $x operand1 <- This is the PHP type
* maps to xs:int <- This is the schema type
* @param array of int $y operand2 <- This is the PHP type
* maps to xs:int <- This is the schema type
* @return array of int $result
* maps to xs:int <- This is the schema type
*/

function addVectors($x, $y)
{

$result = array();
for($i = 0; $i < count($x); $i ++)

{
$result[$i] = $x[$i] + $y[$i];
}

return array("result" => $result);
}
NOTE: you should update the $operations and $opParams with the new operation.

Note the change in annotation notation, you have add a prefix called 'array of' (just 'array' is enough) and you will have the elements maxOccurs="unbounded" in the WSDL means you are having arrays as input and output parameters in your service operation.

How about providing complex types as input and output parameters. That also will available in the WSF/PHP 1.2.1 release.

For an example say you want to add matrices. Here is how your code will look like.


/**
* operation addMatrices
* I have considered matrix as an array of Rows, which in tern array of columns
* @param array of object Row $x operand1 <- This is the PHP type
* maps to non xs:type <- This is required
* @param array of object Row $y operand2 <- This is the PHP type
* maps to non xs:type
* @return array of object Row $result
* maps to non xs:type
*/

function addMetrices($x, $y)
{

$result = array();
for($i = 0; $i < count($x); $i ++)

{
$row1 = $x[$i];
$row2 = $y[$i];
$result[$i] = new Row();
$result[$i]->cols = array();
for($j = 0; $j < count($row1->cols); $j ++)

{
$result[$i]-> cols[$j] = $row1[$j] + $row2[$j];
}

}
return array("result" => $result);
}


/**
* @namespace http://my.org/test/calculator/demo
*/

class Row
{
/**
* @property array of int cols columns
* maps to xs:int
*/

public $cols;
}


NOTE: you should update the $operations and $opParams with the new operation.

Note that you only have to put 'object class_name' to declare that that the parameter is expected to have that PHP class type.

4 comments:

Christoph said...

Hi,

how can i return a WSFault to the client?

When i take your add() example and modify it to throw a WSFault Exception i get a fatal error (Uncaught WS FAULT) on the server site and the following WSFault is send to the client:

NULL parameter was passed when a non NULL parameter was expected.

Thanks

Dimuthu said...

Hi christoph,

Currently you can not throw WSFault when you are using WSDL-mode, You have to use XML in/out API to do that as demonstrated in here, http://phpwebservices.blogspot.com/search/label/WSFault

There were some other users too raise the question in list and forum, This will surely be a fix for the 1.3 release

Thanks
Dimuthu

jkblub said...

Hi Dimuthu,

I have the same requirements like Christoph. I want to use WSFault in the wsdl-mode services. You wrote, this will surely be fixed in version 1.3. Can you tell me, if this feature is implemented and if yes where I can find it.

Thanks Juergen

Dimuthu said...

Hi JKBlub,

Yea It is implemented in 1.3.* and 2.0.0.

You can just throw WSFault object at the service logic and the SOAP response will be fault.

Here is the documentation of the WSFault class. http://wso2.org/project/wsf/php/2.0.0/docs/api_content.html#fault

Thanks
Dimuthu