Customizing and extending PHP’s SoapClient

The last time I had to work with Soap was when I was in college. Fortunately most webservices are RESTful these days, which are a lot easier to use in my opinion. I recently however, had to connect to two different webservices using SOAP which forced me to polish up my skills in this area. The first webservice was quite simple, but the second one was aweful. It required the XML to have all kinds of different attributes and namespaces, which I discovered to my surprise, is close to impossible to implement using PHP’s core SoapClient class. There simpy isn’t something like a method ‘addAttribute’.

I finally managed to crack it after days using PHP’s DOMDocument. I found a vague example of someone using it, but the problem was that they were using an override of __doRequest to return the result, which is XML. While SoapClient returns objects and handles exceptions. And that is exactly what I wanted it to do. This is how to do it:

This, of course, is a basic example. Let me explain what’s going on; some understanding of PHP’s SoapClient and Soap is required. Soap enables you to call webservices by sending data in XML format. WSDL describes the methods you can call on the webservice. Soap-xml should contain a reference to the WSDL file so that it can execute and process the calls. Let’s say you have a webservice with a method ‘doSomething’ you want to call. You initialize a SoapClient with the proper endpoint for the webservice and call ‘doSomething’ on that SoapClient instance. Of course SoapClient doesn’t have this method and will attempt to call this method on the webservice. It will validate the XML and deWDSL in the process and throw an exception if it contains errors. If it succeeds, it will return an object which it creates from the XML response it gets from the webservice.

In my example above, I gave my SoapClient a method ‘doSomething’. I did that because I want to call ‘doSomething’ on the webservice but I need to customize the XML first. Because SoapClient doesn’t offer me the methods to do this properly, I created the custom SoapClient and the method ‘doSomething’ in it. I now call this method with all the parameters I need to build up the XML. In this method I use DOMDocument to create the XML. DOMDocument is a powerful XML building tool which I can use to create exactly the XML I need. When I’m done I assign the XML to property $requestXml. Then I call SoapClient’s __soapCall() – method and pass the name of the remote method I want to call as string (‘doSomething’). Normally SoapClient does this for us when the method ‘doSomething’ doesn’t exist using PHP’s magic methods.

I created an override for method __doRequest which is also used by SoapClient to make the requests. __soapCall somewhere triggers a call to __doRequest, for which I created an override. As you can see, I replaced the first two parameters with my data and call __doRequest on the parent. These two parameters are built by SoapClient when a none-existing method is evoked on SoapClient : in this case I called parent::doSomething, which doesn’t exist on the parent. The $request param will just contain some empty XML because I called ‘doSomething’ on the parent without any parameters. I now replace it with my XML and call __doRequest on the parent. SoapClient now handles the rest of the work for me as it usually would do. My method ‘doSomething’ will now return an object or throw a SoapFault just as SoapClient would normally do.

I hope this made some sense, it’s kind of complicated to make this a simple story. Just let me know if you have any questions.

Published by

Justin

Justin

Hi there! I'm a software engineer currently employed at a company in The Hague in the Netherlands. You can find out more about me and my qualifications on LinkedIn (http://nl.linkedin.com/pub/justin-van-schaick/26/1b0/210). I started this blog in order to share interesting code snippets and tutorials on mainly Javascript, PHP and related frameworks. The internet is an invaluable resource for programmers and unfortunately there's never enough documentation out there. So this is me trying to contribute to that.

Leave a Reply