Making a SOAP Client

Making a SOAP Client

As luck would have it, several demo Web Service servers exist on the Internet, many of which are free to use. You'll hook the SOAP client up to one of these. You need to know a few things to get things working properly. For a start, the address of Web site hosting the demo servers would be helpful: Navigate to this page in your browser and go to the bottom of the page. You should see something like Figure 12-1.

Figure 12-1


Of course, if the demo services have been changed or removed, you will need to make some modifications to the code we present in this chapter, but the important thing is the method by which you interact with the server, not which server you use.

Before going any further, take a quick look at the conditions of use, copied verbatim from the site, for these demo services:


The "XMethods Demo Services" are sample services provided by XMethods to help developers experiment. There is no charge for their use. However, please take note of the following.

  1. Our machine resources and bandwidth are limited. Please do not abuse these services through excessive invocation. Any such abuse may lead to blocking of your IP address without warning.

  2. Any of these services may be discontinued at any time without warning.

  3. While we do our best to keep the services running, there are absolutely no uptime guarantees.

  4. We do not warrant the accuracy of the information provided by these services. Use at your own risk.

  5. Because of the points listed above, we strongly discourage the use of these services for "real" production purposes, such as integration into a portal.

Luckily, our friends at XMethods provide a SOAP-based Web server that allows us to get a book price quote from Barnes & Noble, and we will use this one to return a price for this particular book. Click the Barnes and Noble Price Quote link on the home page. Notice that they have made things quite easy in that they have given us the URI (see the following code snippet) for the appropriate WSDL document, which, as you know, will tell your SOAP client how to use the service.

Recall from earlier in the chapter that you have a choice when creating a new SoapClient object: whether to use WSDL mode, or not. Because we have a WSDL link, let's use it:

   <?php    $client = new SoapClient("    BNQuoteService.wsdl");    ?> 

That's pretty much it. If we had chosen not to use WSDL mode, or it were not made available to us, we would have had to add to the array options such as location, URI, style, and so on.

Assuming that the Web Service is working, then our work is done. From the Web site, you can click the Analyze WSDL link to see the service definitions, but let's instead use some of the native PHP5 functions to determine how we can use this service.

The best way to do this is simply dump the output of the __getFunctions() function to the screen, like so:

   <?php    $client = new SoapClient("    BNQuoteService.wsdl");    var_dump($client->__getFunctions());    ?> 

Save this code as soap_functions.php and navigate to it in your browser. You will see something like Figure 12-2.

Figure 12-2

From this you can see that you have one method available, getPrice(), which takes a string denoting the desired book's ISBN number and returns a floating-point value. That's all you need to know. You can now query the server for the price of Professional PHP5:

   <?php    $client = new SoapClient("    BNQuoteService.wsdl");    echo "The price of the book you requested is: <BR><B>$";    print $client->__call("getPrice", array("0764572822"));    ?> 

Save this code as BNQuote.php and navigate to it in your browser. If all is well, you will see something like Figure 12-3.

Figure 12-3


Of course, the result shown here may not be the actual price of this particular book. This is simply a demonstration and may not necessarily reflect the actual price given by Barnes & Noble, so don't feel hard done by if you paid more!

Remember that you don't have to use the __call() method to access a server method. You can simply call the method directly, like this:

   print $client->getPrice("0764572822"); 

As you can see, you can easily get a quote for any book that is stocked by Barnes & Noble with only a few lines of code. Of course, a little more is going on under the hood. Let's take a more detailed look at what's happening here.

Under the Hood

Although the programming interface of PHP5's SOAP extension is simple to use, a lot of work goes into ensuring that all communications are carried out correctly. Understanding the WSDL document's role in this is important, because this determines how communication will be carried out between client and server. Basically, you can think of WSDL as an extensible, XML-based means of defining Web Services as a set of endpoints that can operate on messages.

In this section we discuss the WSDL document that we utilized in the previous example in detail, and we look at the request and response SOAP messages that were passed between the client and server in order to get our book price.

The WSDL Document

A WSDL document is divided into various sections, which together make up the contract by which the clients and servers of this Web Service must communicate. WSDL documents are structured to contain several major components and some slightly less important ones. Not all these elements have to be included at any one time, but here is a list with a short explanation of each:

We don't spend much time discussing WSDL, but to take a more in-depth look at it, go to

As you can see from the first piece of XML that follows, we define which version of XML we are using (1.0), and then declare the definitions element. The definitions element is always the root element and gives the name of the Web Service (in our case, BNQuoteService) as well as defines target namespaces for use in the document:

   <?xml version="1.0" ?>    <definitions name="BNQuoteService"     targetNamespace=""     xmlns:xsd=""     xmlns:soap=""     xmlns=""     xmlns:tns=""> 

Next come the message elements. This section gives the request and response message names and defines the types they will use (refer to the documentation at for a list of what types are defined for use with the SOAP extension):

   <message name="getPriceRequest">      <part name="isbn" type="xsd:string" />    </message>    <message name="getPriceResponse">      <part name="return" type="xsd:float" />    </message> 

The portType describes a full round-trip operation called getPrice, which consists of the input and output messages getPriceRequest and getPriceResponse:

   <portType name="BNQuotePortType">      <operation name="getPrice">        <input message="tns:getPriceRequest" name="getPrice" />        <output message="tns:getPriceResponse" name="getPriceResponse" />      </operation>    </portType> 

Notice that, in the following code snippet, we give the binding a name and then define its type to be BNQuotePortType. What this means is that we are really defining this binding for the portType BNQuotePortType, which is the portType that has just been defined. Further, we define the binding style, in this case RPC, as well as the transport mechanism. Because we are using HTTP, we specify the SOAP HTTP transport. Note that this section also defines the type of encoding to use for the body of the SOAP message in this case it is encoded, but it could have a document or literal-use attribute, for example:

   <binding name="BNQuoteBinding" type="tns:BNQuotePortType">      <soap:binding style="rpc" transport="" />      <operation name="getPrice">        <soap:operation soapAction="" />        <input name="getPrice">          <soap:body use="encoded" namespace="urn:xmethods-BNPriceCheck"           encodingStyle="" />        </input>        <output name="getPriceResponse">          <soap:body use="encoded" namespace="urn:xmethods-BNPriceCheck"           encodingStyle="" />        </output>      </operation>    </binding> 

Finally, we define a single endpoint with the port element, giving the address of the actual service to use. In this case it is Notice also that the creators have snuck in a little documentation element telling us what the service is all about. This doesn't have to be given here but it's as good a place as any:

     <service name="BNQuoteService">        <documentation>         Returns price of a book at given an ISBN number        </documentation>        <port name="BNQuotePort" binding="tns:BNQuoteBinding">          <soap:address           location="" />        </port>      </service>    </definitions> 

We hope this has served as a good introduction for you to create your own WSDL documents. As mentioned, you can find plenty more reading on WSDL at, and if you intend to create your own Web Services, this is where you should start for help in creating WSDL documents for your services.

We'll now look at how requests and responses are formed. We already have an idea from the WSDL document, but PHP can help further here.

The Request and Response Envelopes

PHP5, if you recall, provides a couple of functions that can be used to look at the requests and responses from our client. Open the BNQuote.php file from earlier and modify it like this:

   <?php    $client = new SoapClient("",      array("trace" => 1));    echo "The price of the book you requested is: <BR><B>$";    print $client->__call("getPrice", array("0764572822"));    echo "</B><BR> The request envelope result is: <B>";    print "<BR>".($client->__getLastRequest())."</BR>";    echo "</B> The response envelope result is: <B>";    print "<BR>".($client->__getLastResponse())."</B></BR>";    ?> 

This gives you the output shown in Figure 12-4.

Figure 12-4

Nothing new here. Click View Source to see what we're after. Following is the request envelope, which you can quite easily relate to how message transmission was defined in the WSDL for example, you can see that the request is sent as a string:

   <?xml version="1.0" encoding="UTF-8"?>    <SOAP-ENV:Envelope       xmlns:SOAP-ENV=""       xmlns:ns1="urn:xmethods-BNPriceCheck"       xmlns:xsd=""       xmlns:xsi=""       xmlns:SOAP-ENC=""       SOAP-ENV:encodingStyle="">      <SOAP-ENV:Body>        <ns1:getPrice>          <isbn xsi:type="xsd:string">0764572822</isbn>        </ns1:getPrice>      </SOAP-ENV:Body>    </SOAP-ENV:Envelope> 

Next, we have the response envelope that is returned by the Web Service server. Once again, you can relate it to the WSDL document quite easily; among other things, for example, you will notice that the return type is a floating point number as stipulated:

   <?xml version='1.0' encoding='UTF-8'?>    <SOAP-ENV:Envelope       xmlns:SOAP-ENV=""       xmlns:xsi=""       xmlns:xsd="">      <SOAP-ENV:Body>        <ns1:getPriceResponse xmlns:ns1="urn:xmethods-BNPriceCheck"          SOAP-ENV:encodingStyle="">          <return xsi:type="xsd:float">31.99</return>        </ns1:getPriceResponse>      </SOAP-ENV:Body>    </SOAP-ENV:Envelope> 

Unfortunately, something has been forgotten. If you substitute an impossible ISBN number into your code and run it, you will notice that we don't throw any helpful messages. In a real-world application, we absolutely need to perform some sort of error checking and exception handling.

Obviously, in the larger context of your application you can decide what the best method is for doing this, but let's look quickly at how we can use PHP5's SOAP implementation to make things slightly more robust here and now.

Exception Handling in the SOAP Client

Recall that earlier we mentioned a SoapFault object that's readily available for your use. Open your soap.php file and modify it like this (Save it as soapfaults.php):

   <?php    $client = new SoapClient("",    array("exceptions" => 0));    echo "The price of the book you requested is: <BR><B>$";    print $client->__call("getPrice", array("0764572822"));    ?> 

Having the exceptions array option set to 0 means that the SoapClient object will automatically return a SoapFault object if something goes wrong. You can catch this in a try...catch block, or use the is_soap_fault method provided, which checks to see whether if the argument supplied is a SoapFault object. For this example, modify soapfaults.php to use the PHP is_soap_fault() method:

   <?php    $client = new SoapClient("",    array("exceptions" => 0));    $methodresult = $client->__call("getPriceRequest", array("0764572822"));    if (is_soap_fault($methodresult)){       echo "We have a problem: <BR>";       var_dump($methodresult);    }    ?> 

You can use var_export instead of var_dump if you want to see hidden object members, but the important thing is getting a relatively sensible message explaining the problem by simply getting the client to return SoapFault objects on error. You should get results similar to Figure 12-5, explaining, quite correctly, that you have requested an invalid method.

Figure 12-5

Obviously, there are plenty of ways to go about implementing exception handling, and you should pick the method that fits in with your application as a whole. The point of this section was simply to alert you to the available functionality.

Professional PHP5 (Programmer to Programmer Series)
Professional PHP5 (Programmer to Programmer Series)
Year: 2003
Pages: 182
BUY ON AMAZON © 2008-2017.
If you may any questions please contact us: