Zend Soap

In this article I will introduce you to the Zend_Soap component of the Zend Framework. This component allows you to easily create and consuming SOAP web services. We will create a simple web service with several methods using Zend_Soap_Server, and consume the service with Zend_Soap_Client.

This article requires Zend Framework, downloadable from http://framework.zend.com. At time of writing, the current version of Zend Framework is 1.9.0.

The way SOAP typically works is that the SOAP client (which may be implemented in any language, such as PHP, ASP, Perl, Python or otherwise) connects to the web service endpoint and requests its WSDL (Web Services Description Language) file.

The WSDL file tells the client about the different function calls that are available, as well as a description of any complex types that are used in addition to the basic data types (such as string, integer or Boolean).

When we create our web service, we must not only handle calls to the various methods that we offer, but we must be able to send a WSDL file to clients. Thankfully, Zend_Soap can automate the generation of WSDL files, as I’ll show you later in this article.

In the next three sections I will cover the key steps involved in creating a web service using Zend_Soap_Server. For the purposes of this example the web service will be located at http://example.com/webservice.php.

Our first step in creating a web service is to create a single PHP class that contains the methods you want people to be able to execute using SOAP. Each public method that belongs to this class is a method that can be executed your web service.

Tip: If you want public methods in your class that aren’t auto-discovered (and thereby included in your WSDL), prefix the function name with a double-underscore. For instance, public function __myHiddenPublicFunction() { … }.

Each method in this class must be documented using the PhpDoc syntax, for the purposes of dynamically generating the WSDL file. At minimum this requires specifying input parameters (using @param) and the return data type (using @return). The reason for doing this is for generation of the WSDL file.

Let’s being by creating a simple class with two methods. The first method (getDate()) will return the current date and time of the server. This method has no arguments and returns a string.

The second method (getAgeString()) accepts a name and an age and returns a nicely formatted string using these values. This method has a string argument and an integer argument and returns a string.

If the URL of your web service is http://example.com/webservice.php, then clients will expect to be able to retrieve the WSDL of your web service at http://example.com/webservice.php?wsdl. As such, we must handle requests to this URL.

When somebody hits the URL we will invoke the WSDL generator that comes with Zend_Soap in order to generate the WSDL file, then send it back to the client. The class we use to generate the WSDL is Zend_Soap_AutoDiscover. All that is required is that we pass the name of the class we created in the previous section (MyWebService) to the setClass() method of our Zend_Soap_AutoDiscover instance.

Listing 2 shows the code we use to achieve this. We will improve on this code shortly.

Note: that we need to still include our class in the script so that Zend_Soap_AutoDiscover knows about it.

Figure 1 shows how the WSDL file might look in your browser

If you were to now visit the webservice.php file in your browser you will see the generated WSDL file (which is simply an XML file that web service clients know how to interpret).

As noted previously, we only want to send the WSDL when the client includes a query string of “wsdl”. To check for this we use the $_SERVER['QUERY_STRING'] variable.

Now when you request the webservice.php file nothing will be shown in your browser, but if you request it as webservice.php?wsdl then the WSDL file will once again be displayed.

Another point of interest is that if you add a new method to the MyWebService class, it will automatically be added to the WSDL file, thereby making it available to all clients.

Next we must handle any requests to the web service. This involves filling in the “else” block from the previous listing.

To achieve this, we use the Zend_Soap_Server class. Just like Zend_Soap_AutoDiscover, it needs to the know the name of the class that holds the web service methods.

Additionally, when we instantiate the Zend_Soap_Server class we need to pass to it the URL of the web service. This is so the server knows which methods to handle, as well its data types (Zend_Soap_Server doesn’t do any auto-discovery of the class you pass to it with setClass()).

You can either hard-code the URL of the WSDL file, or you can auto-generate its location as in Listing 4.

Note: This URL auto-generator is somewhat simple. You may need to account for different port names or for using HTTPS.

Listing 4 shows how to instantiate the Zend_Soap_Server class, set the WSDL, set the PHP class and then handle the request.

That’s all there is to it. The next step is to actually consume the web service, as covered in the next section.

Now that we’ve created our web service (at the location http://example.com/webservice.php), we can create a client script to consume the web service.

For this, we are going to use Zend_Soap_Client class. You could use PHP’s built-in SoapClient class (or even use a programming language other than PHP), but since this is a series on the Zend Framework we’ll use the Zend_Soap_Client class.

Consuming the service is simply a matter of instantiating Zend_Soap_Client with the URL of the WSDL file (http://example.com/webservice.php?wsdl) as the only argument, then calling the functions from the PHP class we created earlier as if they were local function calls.

Note: There are several options that can be customised when instantiating Zend_Soap_Client, but to keep things simple I won’t cover them here. You can read more at http://framework.zend.com/manual/en/zend.soap.client.html.

Listing 5 shows how we make use of the web service calls. The PHP script can live on a completely different web server and URL to your server. After all, that is the point of web services!

In this code you will see we call $client->getDate() and $client->getAgeString(). When these functions are called, internally Zend_Soap_Client is communicating with the SOAP server specified in $url.

While this is a somewhat simplified implementation, it works, and it should demonstrate how to implement both the server and client aspects of a SOAP web service!

As stated previously, this is a somewhat simplified implementation of web services. There are several things you can add to make this a more advanced implementation. These may include:

  • Complex data types, such as arrays and objects.
  • Type mapping (automatically mapping SOAP data types to local PHP classes on both the server and client). This allows easier manipulation of data passed to and returned from web service calls.
  • Authentication. There are two levels of authentication: one to protect who can access the web service directly, and the second is to let users authenticate via a web service so they receive an elevated level of access.
  • Error handling. We can’t always assume data passed to web service calls is valid. The server needs the ability to send errors, and clients need to be able to detect errors and handle them accordingly.
  • Caching. Since every call to a web service can potentially be quite expensive (in terms of time and processing power), it can be extremely beneficial to implement a caching mechanism that allows you re-use the response from web service calls without having to communicate with the SOAP server.
  • WSDL file caching. In this article I haven’t covered anything to do with caching of WSDL files. By default, the server and client will cache these files, but you can control this behaviour when instantiating Zend_Soap_Server and Zend_Soap_Client.

Hopefully in an upcoming article I will cover each of these aspects.

In this article I introduced you to the Zend_Soap component of the Zend Framework. I showed you how to create a basic web service with Zend_Soap_Server and then how to consume it with Zend_Soap_Client.

Part of this process included generating a WSDL file to describe all of the functions in the service. We achieved this by using Zend_Soap_AutoDiscover and PhpDoc.

Further reading:

Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedIn

Leave a Reply

Your email address will not be published. Required fields are marked *