SOAP is a messaging protocol that is platform agnostic and happy to use a variety of Internet protocols such as HTTP, SMTP, and even MIME. We already know that it makes use of XML as part of its information exchange methodology, and the only other thing we need to note here is that WSDL (Web Service Description Language) is also used to make our lives easier by describing how we can use the services that are to be accessed by SOAP. We discuss WSDL, as well as all other aspects of SOAP, in more detail a little later on in the chapter.
But what does SOAP do? The simple answer is that it allows us to pass structured, typed data in a decentralized, distributed environment. Perhaps we should clarify how astounding this is. The second we can pass information from one platform to another at will, we effectively drop the boundaries of communication between heterogeneous platforms and systems a veritable babel fish (see The Hitchhiker's Guide to the Galaxy by Douglas Adams) for computers.
PHP5, not to be left behind, provides several different libraries for implementing SOAP. They are as follows:
The PHP5 SOAP extension: Bundled with PHP5
Depending on what you feel most comfortable with, you can pick and choose which you would like to go for. However, for the purposes of this chapter we look only at the use of the SOAP extension that comes bundled with PHP5.
As of this writing you have to manually write in the SOAP extension to the php.ini file, extension= php_soap.dll, for Windows, or compile with --enable-soap for Linux versions. Please be aware that this may change, so keep an eye on the documentation.
There are a couple of things to note with regards to configuring SOAP in PHP5. One of the biggest drawbacks to using SOAP is that you really end up relying on the speed of your connection because the SOAP client making the request needs to first download the WSDL document in order to know how to make a function call to the target service. Obviously, downloading a file over a slow connection or, perhaps more important, one with a high latency ("ping time''), could present the greatest bottleneck in terms of the time taken for a given task to be executed.
The solution is provided in the form of PHP configuration settings, which allow you to specify whether you want to cache WSDL pages, where you want them to be cached to, and how long you want to use that cached copy of the files. This means that your application's execution time is "charged" only once in order to download the WSDL; from then on, you use the cached version.
If you think that this will significantly enhance the performance of your application, you can go ahead and add the following lines to your php.ini file (substituting whatever values you deem necessary):
; SOAP ;Boolean paramater to indicate whether caching should occur soap.wsdl_cache_enabled = "1" ;directory where files are to be cached soap.wsdl_cache_dir = "/usr/local/php/wsdlcache" ;time, given in seconds, to use the cached copy ttl = time to live soap.wsdl_cache_ttl = "1000"
The functions provided with PHP5 can nominally be divided into three categories. The main two are SoapClient and SoapServer functions, with the other category handling miscellaneous functions. We discuss each one briefly in the next few sections, but for more comprehensive coverage, see the documentation at http://www.php.net/manual/en/ref.soap.php.
In keeping with all things object oriented, available SOAP functions are exposed through the use of SOAP objects, and you can instantiate a generic SoapClient object to work with as follows:
$client = new SoapClient (mixed wsdl [, array options]);
The first parameter can take either the null value (if you aren't using WSDL), or the Uniform Resource Identifier (URI) of the WSDL document to be used. The options parameter that follows should be passed as an array, and can be used to give proxy settings or stipulate the SOAP specification to which the SOAP client should adhere. For example, to create a SOAP client that uses encoded SOAP messages and RPC style, you can say:
$client = new SoapClient(null, array('location' => "http://localhost/my_soap.php", 'uri' => "http://my_uri/", 'style' => SOAP_RPC, 'use' => SOAP_ENCODED));
After you have the SOAP client instantiated, you have a number of methods provided by PHP5 that you can call in the resulting client object. They are as follows:
__call: Use this to make a SOAP call directly. Most times you can simply call the SOAP functions as a SoapClient method, but this may come in handy for transmitting SOAP headers and footers, for example.
__getFunctions: Exposes the functions provided by a given Web Service.
__getLastRequest: As the name implies, you can retrieve the previous request made by the SOAP client, but only if your SoapClient instance was created with the trace option set to true in the options array parameter.
__getLastResponse: Again, you can use this to determine the previous response received by the SOAP client, again provided that your SoapClient has the trace option enabled.
__getTypes: This will return a list of SOAP types (i.e., structures and objects defined and implemented by the Web Service) and can be used only if your SoapClient was instantiated in WSDL mode (i.e. supplied with a WSDL URI as its first argument).
We discuss how to create and use a SOAP client in some detail a little later but, for the moment, we'll continue to explore the other SOAP functionality provided by PHP5.
Of course, accessing information from a client is not the only way developers use SOAP. Providing the server is high up on the Web Service to-do list, and PHP5 provides some methods to create SOAP servers.
As with the SoapClient, you have a constructor that can be used to create the SoapServer object as follows:
$server = new SoapServer (mixed wsdl [, array options])
You can either specify the WSDL document to use in the first parameter, or leave it as null. If the first option is null, you have to set the uri option as part of the options array in much the same way as the SoapClient. The server methods available are the following:
addFunction: Allows functions to be added to service SOAP requests.
getFunctions: Returns a list of the functions available on the server.
handle: Takes values either from the single soap_request parameter or, in its absence, the global variable $HTTP_RAW_POST_DATA and deals with the given request, returning a response to the client.
setClass: Allows PHP methods (and entire classes) to be added to the server in order to handle SOAP requests.
setPersistence: Assuming that you have used setClass to add the server's functionality, this can be used to perpetuate data between requests in a session.
The final few SOAP functions deal with a couple of different issues, the most important of which is exception handling. You can create a SoapFault object to return fault responses from the server as follows:
$fault = new SoapFault (string faultcode, string faultstring [, string faultactor [, mixed detail [, string faultname [, mixed headerfault]]]]);
If a SoapClient has its exceptions option set to 0, the requested method will return the SoapFault object on any failure. With this in mind, you can use the following function (just a function, not part of any class) to test whether a function call failed:
This returns true if the result parameter passed in is in fact an instance of the SoapFault object.
Apart from these exception-related issues, PHP5's SOAP extension also implements the SoapVar object, which can be used to set type properties when not in WSDL mode. It is instantiated like this:
$type = new SoapVar (mixed data, int encoding [, string type_name [, string type_namespace [, string node_name [, string node_namespace]]]]);
SoapHeader, as the name implies, allows you to pass raw SOAP headers between client and server. This can be done from either the __call() or handle() functions:
client->__call("myFunction", null, null, new SoapHeader('http://thenamespace.org/mynamespace/', 'myExample', 'an example'));
Finally, you are also given the SoapParam object to pass name and value pairs as SOAP parameters from clients that are not in WSDL mode. For example, to supply parameters to a SOAP server's method call, you can say something like:
$client->__call ("getSoapMethod", array(new SoapParam($value, "name")));
With that, you now have a brief idea of how the first bundled SOAP extension goes about using SOAP. You can use this to create an example SOAP client as well as a simple SOAP server, as discussed near the end of the chapter.