?xsd is an standard option to serve an xsd file imported within a wsdl. This was a missing feature in WSF/PHP. In WSF/PHP automatic wsdl generation, it does not generate additional xsds which are imported by the wsdl and hence this option would not be required. However, with wsdl mode, you could have additional xsds imported in the wsdl. Now you can obtain these xsds with the option ?xsd=xsdfilename.xsd.
ScreenCast - How to Consume a Web Service Using WSF/PHP
Wednesday, October 29, 2008
WSDL Generation From PHP - Using Different Names in WSDL and PHP Code
Thursday, October 23, 2008
Coding Schema Inheritance in PHP
Tuesday, October 21, 2008
Demo on Providing PHP Web Service with Username Token
Thursday, October 16, 2008
Developing WSF/PHP Webservices With Contract First Approach - 2 Minutes Introduction
Monday, September 8, 2008
WSF/PHP WSDL Generation 2 Minutes Introduction
Friday, September 5, 2008
Howto Build Custom SOAP Headers in WSDL Using Axis2/C and WSF/PHP
Thursday, August 21, 2008
XML Attributes in your payload
Friday, June 27, 2008
<xs:complexType name=\"myType\">
<xs:sequence>
<xs:element name=\"demo1\" type=\"xs:string\"/>
<xs:element name=\"demo2\" type=\"xs:string\"/>
</xs:sequence>
<xs:attribute name=\"demo3\" type=\"tns:derivedType\"/>
</xs:complexType>
PHP webservices demo site have samples WSDLs that defines attributes http://labs.wso2.org/wsf/php/solutions/wsdl_mode/AttributeService.php?wsdl. And you can test a sample service setting your clients endpoint to http://labs.wso2.org/wsf/php/solutions/wsdl_mode/AttributeService.php. Write your client with the help of the generated code for the WSDL. You can try it online from Here. And make sure you have installed WSF/PHP to do all of these.
Choose among multiple services, multiple ports
Thursday, June 19, 2008
For an example if you take wsdl1.1 with multiple services and ports like this,
<wsdl:service name=\"Adder1\">
<wsdl:port name=\"SOAP11port_http\" binding=\"ns0:AdderSOAP11Binding\">
<soap:address location=\"http://localhost:8080/axis2/services/Adder1\"/>
</wsdl:port>
<wsdl:port name=\"SOAP12port_http\" binding=\"ns0:AdderSOAP12Binding\">
<soap12:address location=\"http://localhost:8080/axis2/services/Adder1\"/>
</wsdl:port>
<wsdl:service/>
<wsdl:service name=\"Adder2\">
<wsdl:port name=\"SOAP11port_http\" binding=\"ns0:AdderSOAP11Binding\">
<soap:address location=\"http://localhost:8080/axis2/services/Adder2\"/>
</wsdl:port>
<wsdl:port name=\"SOAP12port_http\" binding=\"ns0:AdderSOAP12Binding\">
<soap12:address location=\"http://localhost:8080/axis2/services/Adder2\"/>
</wsdl:port>
<wsdl:service/>
You can select the Adder2 service with SOAP12port_http with the following optional arguments to the getProxy method.
$client = new WSClient(array(\"wsdl\" => \"your_wsdl\"));
$proxy = $client->getProxy(\"Adder2\", \"SOAP12Port_http\");
This can be represented in wsdl2 as following,
<service name=\"Adder1\" interface=\"ns0:AdderPortType\">
<endpoint name=\"SOAP11port_http\" binding=\"ns0:SOAP11Binding\" address=\"http://localhost:8080/axis2/services/Adder1\"/>
<endpoint name=\"SOAP12port_http\" binding=\"ns0:AdderSOAP12Binding\" address=\"http://localhost:8080/axis2/services/Adder1\"/>
</service>
<service name=\"Adder2\" interface=\"ns0:AdderPortType\">
<endpoint name=\"SOAP11port_http\" binding=\"ns0:SOAP11Binding\" address=\"http://localhost:8080/axis2/services/Adder2\"/>
<endpoint name=\"SOAP12port_http\" binding=\"ns0:AdderSOAP12Binding\" address=\"http://localhost:8080/axis2/services/Adder2\"/>
</service>
Note that here portName you provided is considered as the endpoint name under the selected service.
When you don't provide either serviceName and the portName, wsf/php will pick the first serviceName and portName listed in the wsdl.
Although multiple services in the same wsdl is very rare, multiple ports /endpoints in the same service is very common. Specially when you support multiple versions of SOAP, addressing, or even completely different policies for the interface you will surely be having multiple ports.
WSF/PHP Code generated for Some famous Web Services
Sunday, June 15, 2008
"opParams" option for WSService
Tuesday, May 6, 2008
/* this is the service function */
function echoFunction($inMessage /* with the type of WSMessage */) {
$outMessage = new WSMessage($inMessage->str);
return $outMessage; /* with the type of WSMessage */
}
$operations = array("echoString" => "echoFunction");
$opParams = array("echoFunction" => "WSMESSAGE");
/* WSMESSAGE is the default value for this situation */
$service = new WSService(array(
"opParams" => $opParams,
"operations" => $operations))
Note that when you provide WSMESSAGE to the "opParams", the service operation parameters(both input and output) are of the type WSMessage.
Now say we put "MIXED" in there like the one in following
/* this is the service function */
function echoFunction($inMessage /* with the type of string */) {
$outMessage = $inMessage;
return $outMessage; /* with the type of String */
}
$operations = array("echoString" => "echoFunction");
$opParams = array("echoFunction" => "MIXED");
/* MIXED is the default value for this situation */
$service = new WSService(array(
"wsdl" => "http://localhost/echostring.wsdl",
"opParams" => $opParams,
"operations" => $operations))
Here note the difference in the service operation. Now the argument types are strings. This types are defined in the wsdl which is provided as an argument to the WSService.
So it is clear
When "wsdl" is provided the opParams are default to "MIXED",
otherwise it is default to "WSMESSAGE".
So you don't need to provide the opParams option explicitly in both above cases.
WSDL Mode Enhancements
Tuesday, February 26, 2008
WSDL mode in WSF/PHP is getting improved day by day. Dimuthu has done many improvements, including class map support and array support.
I managed to fix some RPC style related issues and also add support for the 'choice' and 'all' constructs. There are some work to be done in WSDL mode to integrate it, but we can generate code for WSDL mode now.
If you want to work with WSDL files in PHP, WSF/PHP would be the most comprehensive toolkit out there.
Code Generation for WSDL Mode
Wednesday, February 13, 2008
Both WSF/PHP and SOAP extension has WSDL modes. But none of them has the tools for generating code for a given WSDL. Because of this, the users are in hot water when it comes to implementing the complex type mappings for the request and handling response. If you make a simple mistake in SoapVar or SoapParam classes, debugging could take hours or even days before you get to know the problem.
To address this issue, WSF/PHP is coming up with a nice proposal. Implement code generation tool that can generate all complex type classes along with some demo code. So on one hand, you do not have to write the complex class mappings manually. And on the other hand, you will be provided with some sample code that would help you understand how to consume the service described by WSDL. WSF/PHP already have the model in place to implement the tool. It is only a matter of time before someone put all the pieces together and come up with the code generator.
WSDL Generation with WSF/PHP - Arrays and Complex types
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.
<?phpHere 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.
/**
* 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();
?>
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,
/**NOTE: you should update the $operations and $opParams with the new operation.
* 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 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.
Use WSDL Elements Maps to Your PHP Classes.
Tuesday, February 12, 2008
You have to provide the map of wsdl type to the PHP class name as an option to both WSClient(in a case it is a client) and WSService(in a service).
From WSF/PHP 1.2.1 patch release you will not need to provide the full map of classes to schema construct. Since the engine will be intelligent enough to pick the class with the same name as schema construct when the class is not provided in the class map. If there is no class like that at all, the engine will create a unnamed class and allow to access its properties as it was a class like made to represent that schema construct.
So hope you will enjoy the new improvements to the API.
WSF/PHP 1.2.1 on the way
Friday, February 8, 2008
One of the key feature of this release is improved WSDL mode and WSDL generation support.
In 1.2.0 we had support for simple WSDL generation like this.
<?php
/**
* addUser
* @param string $name here string is for php type
* this maps to xs:string (this is really optional declaration)
* @param int $age the age
* @return int $status
*/
function addUser($name, $age)
{
/* some logic add the user */
return 1;
}
/* map of service operation to php function */
$operations = array("addUser"=> "addUser");
/* this is required in the wsdl generation */
$opParams = array("addUser"=>"MIXED");
$service = new WSService(array("operations"=> $operations,
"opParams"=> $opParams,
"serviceName" => "User"));
$service->reply();
?>
There, the annotations are used to provide meta data about the Service, input and output parameter types.
If you are going to use the new release you would be able to improve the above code to more organized way like one in the following.
<?php
/**
* addUser
* @param object User $user : note the "object User" as the php type.
* @return int $status
*/
function addUser($user)
{
/* some logic add the user */
return 1;
}
/**
* @namespace http://im.me/types the namespace
*/
class User
{
/**
* @property string $name
* schema type xs:string - this is still optional
*/
public $name;
/**
* @property int $name
* xs:int
*/
public $age;
}
$clasmap = array("User"=> "User");
/* map of service operation to php function */
$operations = array("addUser"=> "addUser");
/* this is required in the wsdl generation */
$opParams = array("addUser"=>"MIXED");
$service = new WSService(array("operations"=> $operations,
"opParams"=> $opParams,
"classmap"=> $classmap,
/* the serviceName can provided as an option */
"serviceName" => "User"));
$service->reply();
?>
There we use class "User" to declare a schema type in the WSDL. So if you want to add method like getUsers you can share this type with the current addUser method. Here is how you would define getUsers method with correct annotations. Hopefully you should add this method to "operations" and "opParams" options as well.
/**This illustrate how you should extract the request and build the response in your logic when there are arrays and class types in your service operations.
* @param string $condition
* @return array of object User $users : note the array of is prefixed
* to the php type
*/
function getUsers($condition)
{
$user1 = new User();
$user1->name = "Hiro";
$user1->age =23;
$user2 = new User();
$user2->name = "Clair";
$user2->age = "14";
return array("users" => array($user1, $user2));
}
Well how you would write a client for this operations. Here is a sample client that use simple arrays to build requests and return response. Similarly if you set "classmap" option to the WSClient you would instead build the requests and extract responses from PHP class objects..
<?php
$client = new WSClient(array("wsdl"=>"http://localhost/mails/06_blog/MuchNewService.php?wsdl"));
$proxy = $client->getProxy();
//add user operation
$res = $proxy->addUser(array("user"=>
array("name" => "cyler", "age" => 28)));
print_r($res);
//getUsers operation
$res = $proxy->getUsers(array("conditions" => "none"));
print_r($res);
?>
Hope you all will enjoy this new set of features..
You still like RPC-Enc style WSDLs
Friday, January 25, 2008
I think there are two main reason that made RPC-Encoded not to use anymore.
First is as first part of its name (RPC stands for Remote Procedure Call) imply this is used to do remote procedure call through network. This lead to appear lot of fine grained services which do just very simple function call through the network. This violates a kind of principal (or just a best practice) of web services, that is you should design a coarse grained fixed interface for a web services. So this was -1 for RPC and +10000 for Document style WSDLs.
Second reason for its failure is the second part of its name, the encoding mechanism. It uses soap encoding which is really tedious to implement, (In fact I am thinking of doing an implementation for Axis2/C, but it seems not that straight forward) And it seems different implementations are hard to inter-operate with this encoding. This made WS-I to prohibit use of RPC-ENC and promote doc-lit.
Anyway we can see still there are many people who ask for RPC-Enc style wsdl support. I think this is because of the legacy systems they are using.
Web Service Framework for PHP also has great support on DOC-Lit style than RPC-ENC. But still It is a good tools for legacy system developers, since it gives the basic functionalities like dynamic-invocation and wsdl-generation with the RPC-Enoded wsdl s as well.
What is Missing in PHP SOAP Extension?
Wednesday, January 23, 2008
Couple of days back, I blogged about the features of SOAP extension. Now, are these features good enough. Yes they sure are for simple SOAP services.
However, simple SOAP services draws much criticism, specially form REST fans. If you want to do only simple stuff with SOAP, why not use REST? I see that to be a valid argument, especially in the PHP world, given that HTTP is the dominant transport.
In fact, the real value of SOAP comes, when things get complex, more enterprise in nature. That is where the QoS comes into play. SOAP is not that much useful, when you want to use the Fliker upload images, you of course and use the REST API. SOAP is useful when you want to send an invoice, that contains special discounted rates, securely to one of your customers. You have to be absolutely sure that only that customer sees it. And may be you are using a spread sheet or a PDF file to record the invoice and you want to send it as it is. This requires the need to send binary attachment with security with SOAP. And if you are lucky, your customer's system too would use PHP, however, in this heterogeneous world, it may well be that the customer is on .NET or using J2EE. In short, you need a interoperable comprehensive SOAP stack.
PHP SOAP extension is good to get started, to play around with. However, it falls much short in meeting the enterprise demands in the SOA era.
Can you improve it, to support security and binary attachments? Of course you can. However, the concern is that the time it would take to make it interop side by side with .NET and Java implementations. They have taken years to come to that stage. I have seen how much effort has been spent on Apache Axis2/Java and Apache Axis2/C. Even if you have people with right expertise, WS-Security alone would take at least two person years to complete.
It is the WSDL mode that most users love to use. And if you ever have worked with a WSDL tool, you know how hectic it is to support all the user scenarios. Specially the schema support is an endless game. Most of the interop issues pop up with WSDLs. WSDL mode in SOAP extension already have enough interop issues. And there are no plans to support WSDL 2.0. Let alone, the most critical feature to support in WSDL is the WS-Policy support. Specially when WS-Security in in use, the security policies are the way of conveying rules of the level of security to be used and the rules to follow. Even if basic WS-Security is implemented based on some library like xmlsec, supporting policies would require a WS-Policy processing engine. That too will require at least one person year of work.
In summary, it would be years before serious Web services could be implemented with PHP SOAP extension. Web services are complex!
WSDL Generation with PHP
Thursday, January 10, 2008
WSDL is the key for sharing the service interface. Some people call this the 'contract'. Sometimes, developers have access to an already written WSDL. So they can use that and generate either the client code or the service code or both. This is called the 'contract first model'. Sometimes, what we have is a PHP script, and we want to expose that as a service. In that case, we have the code and we would like to generate the WSDL. This approach is called the 'code first model'.
WSDL generation is supported with WSO2 Web Services Framework for PHP and is done using PHP reflection and an annotation parser. To generate a WSDL from a given PHP Web service, a ?wsdl request should be sent to the server. For example, if you want to generate the WSDL for the service echoService.php, a request should be sent as,
http://localhost/services/echoService.php?wsdl
This will generate a WSDL that adheres to 1.1 specification. You can also generate WSDL 2.0, you can use ?wsdl2 in place of ?wsdl.
For more details, you can refer tot he WSDL generation API documentation.