Or you could get me something from my Amazon wish list!
Thanks for your generosity!
|
Were my ramblings useful?I spend over 90% of my work time managing Deviant Audio on a non-paid volunteer basis. If you found my site helpful, donations are always appreciated! :-)
Or you could get me something from my Amazon wish list! Thanks for your generosity! Latest articles
|
Automatic WSDL Generation in PHP 5Downloads for the software described here are available on the downloads page. If site is down, you can directly download wsdl-writer-0.3-katy.1.tar.gz on placeoweb.com. About WSDLWSDL (Web Services Description Language) is part of the XML Web Services technology platform. WSDL files describe to web service clients what services are available at a particular endpoint (server), and how the request and response messages should be (de)serialised. Find out more by reading the Web Services Description Language (WSDL) 1.1 W3C Note. Typically, WSDL files are automatically generated from web service code using reflection, and are imported into clients at design-time. Visual Studio, for example, uses WSDL files to create proxy classes allowing the developer to call remote web services as simple method calls on a local object, making the process seamless (as if you were just calling a local method). The two main platforms used for web services in the real world - J2EE and .NET - can both generate WSDL files easily from code because they are strongly typed languages. This is important because XML web services typically pass strongly typed data between client and server. WSDL generation in PHPPHP is a weakly typed language (meaning it is not necessary to declare a variable's content type when the variable itself is defined, and casts between eg. numbers and strings happen automatically depending on the context in which a variable is used), therefore reflection to generate WSDL files is impossible. This is a serious limitation for the applicability of PHP as a web services platform as it prevents PHP web services from having easy interoperability with clients written in other languages. There have been several attempts to write WSDL auto-generation code for PHP. They typically work by having the developer provide additional data about the types of each argument and return value to each web service defined, for example in comments or arrays. All of the published solutions are rather limited. Perhaps the best attempt I found is David Giffin's wsdl-writer-0.3, available at www.giffin.org. It operates by parsing comments immediately before a web service method to determine the types of its arguments. Here is a simple example: class SimpleService { /** * Add method * * @param int $a First integer * @param int $b Second integer * @return int Result of addition */ public function Add($a, $b) { return $a + $b; } }
wsdl-writer does a very good job of generating WSDL for simple requests but has some major limitations as it stands. David unfortunately does not maintain wsdl-writer so I have decided to publish my modifications here. WSDL Writer 0.3-katy.1The following issues are addressed in this release: Interoperability improvements:
Feature additions:
<types> section of the WSDL file. This effectively means you can now pass and return types of arbitrary complexity among your web services - a very powerful enhancement.
Other bug fixes:
Processing SOAP headers in a PHP SOAP serverHere is an example of a web service class which processes headers and a body method: // To be supplied as a SOAP header element - remember that individual headers must // consist of exactly one complexType argument, so basic xsd types must be boxed in a class class WrappedString { /** @var string Data */ public $data; public function __construct($s) { $this->data = $s; } } // Login credentials to be supplied as a SOAP header class LoginObject { /** @var int Login */ public $login; /** @var int Password */ public $password; public function __construct($l, $p) { $this->login = $l; $this->password = $p; } } // Arbitrary object returned by the test web service method // to prove that the header data was stored in the same class instance class TestObject { /** @var string Result string */ public $result; /** @var int Demo session key */ public $sessionkey; public function __construct($r, $k) { $this->result = $r; $this->sessionkey = $k; } } class MethodWithHeaders { public $sessionKey; /** * HeaderA SOAP header * * To process a SOAP header, create a function with the same name as the header's complexType. * Returned values will be sent back to the client as a SOAP response header. * This example returns the string in a response header, converted to uppercase. * * @param WrappedString $string Input string * @return WrappedString Capitalised string * @internal soapheader */ public function WrappedString($string) { return new WrappedString(strtoupper($string->data)); } /** * HeaderB SOAP header * * You don't have to return a value - you can store the details sent * in the header for later use. * * @param LoginObject $loginobject Username and password * @internal soapheader */ public function LoginObject($loginobject) { $this->sessionKey = $loginobject->login * $loginobject->password; } /** * Some test web service * * Body function - shows that a single MethodWithHeaders object * instantiation is used for all the headers and the body method, * because $this->sessionKey hasn't been declared static. * * @param string $string Input string * @return TestObject Input string and demo session key based on header fields * @internal soaprequires WrappedString LoginObject */ public function testfunction($string) { return new TestObject($string, $this->sessionKey); } }
Supplying SOAP headers and accessing SOAP response headers in a PHP web service clientThe following code calls the server example above. Some items in [square brackets] require substitution as appropriate. // Create SOAP client using only WSDL $headersClient = new SoapClient("[Location of WSDL file]"); // Create headers (use same element name and type name // for .NET interoperability - not required for PHP) $headerA = new SoapHeader('[Namespace URI of WrappedString]', 'WrappedString', new WrappedString('some test string')); $headerB = new SoapHeader('[Namespace URI of LoginObject]', 'LoginObject', new LoginObject(14, 3)); $headersClient->__setSoapHeaders(array($headerA, $headerB)); // Standard call which passes input headers // but doesn't offer access to output headers $headersClient->testfunction("Echo me!")); // Call which allows access to output headers // (input headers persist until changed) $headersClient->__soapCall('testfunction', array("Echo me again!"), null, null, $outputHeaders); print_r($outputHeaders);
Final notesThe changes to wsdl-writer and examples above have been tested against PHP 5.1.1 and Visual Studio .NET 2003 (.NET Framework 1.1). For general usage examples please refer to the examples supplied with the source code. I hope you find this code useful! Please send feedback to katy (at) intelligentstreaming_dot_com. |