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.

Concrete 5.7 : Creating a single page for the frontend

In this post I would like to show you how to create a single page in your package for the frontend of a Concrete 5.7 website. In this tutorial we will call that package ‘YourPackage’ but of course that should be whatever your package is called.

Let’s say you want to create a single page where visitors can sign up for a newsletter. A single page is composed of a template and a controller (The controller is optional).

We will call our controller ‘SubscribeTo’. Following C5’s naming conventions this implies that :

    • The filename of the template will be called ‘subscribe_to.php’.
    • The filename of the controller will be called ‘subscribe_to.php’.

Your directory structure will look like this:

For the controller :

/packages/your_package/controllers/single_pages/subscribe_to.php

For the template :

/packages/your_package/single_pages/subscribe_to.php

And this is what your controller file will look like:

Now let’s say you want to install the single page when your package get’s installed. We will add a method to the package controller in order to do so. (The package controller is  :  /packages/your_package/controller.php).

Now the single page gets installed when you install your package. In this example I added the method ‘addSinglePage’ to the package controller but if you want to follow programming conventions it is better to create a separate class with this method (like a service/util). This way you delegate the logic. That makes it easier to refactor and you can call the method from other packages or code you create.