[NOTE: Updated the wsdl2php link as it now has a SourceForge Entry]
In my latest round of web services work in PHP5 I was creating a PHP5 client that interacts with our Java-based ERP. The client needs to be a combination of a couple of WSDL’s into one, nice, compact and powerful client. It should be noted this client will be distributed via the State of Iowa PEAR channel so it will undoubted by used by other project in our organization and throughout state government so the result needs to have a lot more fit-and-finish than would be typical.
Most HOWTO’s covering the PHP5 SOAP support cover it from the basic consumer’s point of view but there are a few limitations to existing implementation when your goal is to build a client that will be distributed. First of all we can’t simply extend the PHP5 SoapClient because we want to generate all the documentation needed to explain how to use the client. If you simply do something like:
$someClient = new SoapClient('http://www.example.com/?wsdl');
You get a client with all the needed methods, however because we used the SoapClient directly we don’t know what we have to pass or have access to other usage information that may help us. So the first thing to do is you will need to create a PHP client class that is a wrapper to the SoapClient where the PHP code has a one-to-one mapping of methods it has to the methods on the web service. Now I can add in the PHPDoc comments. Perfect.
Next problem, however, is the fact that you need to be able to know what data types are needed in making calls to your web service. This is where I find the PHP5 SOAP support nothing short of deficient. There should be a way to give PHP the WSDL and have it generate the objects needed. In fact, not only should PHP generate the data types needed for the web service methods but it should also be able to create the very client code I’m having to write. Luckily for us, however, there is a package in alpha out there called wsdl2php that does this very thing. While I’m very pleased this package even existed, let me make it clear that this should be something the core PHP SOAP support should handle. Without it PHP developers are having to read and understand WSDL’s which is an exercise in pain.
So with wsdl2php (which currently only runs on Linux which I hope to fix), you can give it your WSDL, it spits out all the data types in the WSDL into their own PHP classes along with a client service class that extends the PHP5 SoapClient and explicitly has entries for the methods on the service complete with PHPDoc stubs and even uses type hints in the function prototypes which is very handy in avoiding type mismatches: Here’s a sample call with my modifications as explained below:
#>wsdl2php -n ITE_I3WebServices_ http://www.example.com/?wsdl
The modifications I made to wsdl2php to allow me to specify a prefix to all my class names to avoid namespace issues (something still not addressed in current PHP6 development though we’ve all be assured multiple times that it will be included) and I’ve modified it slightly to include getters/setters on the class objects generated. However, the most useful modification I made to wsdl2php is the ability to dynamically build the SoapClient ‘classmap’ option which allows the calls to the generated PHP web service client to return native PHP classes instead of stdClass instances.
The last thing I need to figure out is how to modify wsdl2php so that you can give it multiple WSDL’s and have it generate a single client capable of calling methods on all services given.