I’ve had my head buried in SOAP for the last few months. In particular, ext/soap with PHP. There’s a great opportunity out there for PHP find itself as an incredibly easy and robust way to implement a web service environment through SOAP. Unfortunately, the PHP5 soap extension has let this opportunity slip by again and again.
Sure, it’s fairly easy to implement a simple rpc/encoded SOAP framework, especially if you leverage the Zend_Soap (and Autodiscover) classes. If you plan on only consuming the web service with PHP (or even perl and python) then it’s an excellent choice. But the whole point of a webservice is to offer interoperability. This is something where SOAP itself falls short.
The SOAP “standard” isn’t a standard at all. Rather, it’s a generic, fuzzy guideline for implementing one of a dozen other standards. You’ve got your rpc/encoded, your rpc/literal, document/literal, document/encoded and document/literal wrapped conventions. Each offers various caveats and perks.
Here’s where ext/soap comes in. While the rest of the world has been trying to come up with a SOAP implementation that everyone can agree upon, PHP’s soap extension has been fairly stagnant. The package maintainer, Dmitry, does some casual bug fixes but overall there are several gaping holes that leave a lot to be desired.
As it turns out, most of the world HAS agreed on a SOAP implementation. It’s called “document/literal wrapped”. The wrapped portion dictates that in the WSDL, a binding operation’s parameters must refer to a complex type that defines those parameters, thus avoiding a nasty issue with soap-enc:Array. I won’t attempt to explain the breadth of the issue here, but a good article can be found at http://atmanes.blogspot.com/2005/03/wrapped-documentliteral-convention.html
For the last few months I’ve been in a back-and-forth match between PHP, Java and .NET. The struggle has been in getting a WSDL implementation that can play nice with PHP, Perl, Python, as well as the more robust languages like Java and .NET. It’s not just a casual “wish”, it’s part of my project requirements.
The problems have been numerous. Firstly, Java doesn’t support RPC/Encoded anymore. It doesn’t even support vanilla document/literal, in fact; it requires the wrapped convention to even be able to compile. .NET had similar issues. Unfortunately, my WSDLs were being auto generated by Zend_Soap_Autodiscover, which, as of writing this, is incapable of producing WSI compliant WSDLs.
And so began the hacking. I’ve rearranged, rewritten and added a very large chunk of code to the Zend Framework/Soap code base. I was finally able to get a compliant WSDL out of PHP. It compiled in Java and .NET just fine. It worked in python, perl, even ruby. And then I checked PHP.
So far PHP had been pretty agnostic when it came to my WSDL format. It didn’t seem to care whether or not it was in rpc or document, or even if my namespaces mismatched (Something which python and perl DID care about). However, after implementing my “wrapped” changes, something funny happened. PHP was now throwing a SoapException from the client, telling me that the procedure I was calling didn’t exist. A quick var_dump() of SoapClient::__getFunctions() showed that they were indeed there, but PHP couldn’t interact with them for some reason.
After some quick googling, I was able to turn up a few PHP bug reports describing exactly my issue. Most of these bugs were over two years old, with virtually no feedback from the maintainer. An example is http://bugs.php.net/bug.php?id=30302
I contacted Andi and Dmitry personally to ask about the status of the issue. The response I got wasn’t very optimistic:
It’s not supported, because it wasn’t a part of SOAP specification (I’m not sure about present time).
I didn’t plan to implement it. May be someone else…
So when I have some time, basically my only option is to implement it myself, and submit the patch to internals.
The problems with ext/soap are far more numerous than just that, however. In the past few months I’ve encountered issues that lead me to believe the people writing these implementations know even less about SOAP than I do. Here are the main two issues I encountered:
- ext/soap has no support for retrieving Soap Headers. You’re stuck with one of two hacks. You can either pass an object through from the client that maps to a method call on the server — which is less than helpful when using headers for authentication — or parse the XML from HTTP_RAW_POST_DATA manually in your SOAP request. I opted for the latter.
- ext/soap’s fault support is buggy and inconsistent. Defining custom Soap Faults in an intelligent way means hacking the response envelope.
In conclusion, PHP’s soap extension really needs a complete rewrite. I’m probably not the person to do it, but it’s an idea I’ve been toying with. It’s just not ready to be used in a production environment.