Working with SOAP Messages in PHP

Octavia Anghel shows you how to write a PHP web service using the NuSOAP library, as well as a JavaScript client to consume it using the AJAX technology and the SOAP protocol.

This article discusses how to write a PHP web service using the NuSOAP library as well as a JavaScript client to consume it using the AJAX technology and the SOAP protocol.

But first you need a small dollop of web services terminology.

Short Overview of SOAP and Web Services

Simple Object Access Protocol (SOAP) is an XML-based request/response messaging protocol. One important characteristic of SOAP is that it's independent of any transport protocol (HTTP is the most frequently used, but you can use SMTP, MIME, and so on), operating system, or programming language. This makes it very flexible over different software architectures—and also very easy to use.

A web service is a generic description of a software system designed to be called remotely over a network. The services offered can cover many tasks, and the implementation may vary, but the basic idea of a typical web service presumes the following:

A web service is exposed as a server that can be interrogated based on a set of operations.

It "publishes" available operations using an XML document known as a Web Services Description Language (WSDL) document. Normally, this document is both generated and parsed (interpreted) by machines, not by humans.

Entities that access the web services are known as web service clients.

The communications protocol between clients and servers is SOAP.

Using SOAP in PHP

Because web services quickly became a widely used technology, every popular programming language sought to develop and improve its support for creating and exploiting web services. For example, PHP has a few extensions (PEARs and libraries) that add web services support. Starting with PHP5, such support ships with the language in a library called NuSOAP.

Because the NuSOAP library has a great usability/performance rate, you'll see how to use it in this article to develop a complete web service. The NuSOAP library is a collection of PHP classes that supports sending and receiving SOAP messages using the HTTP protocol. The NuSOAP library, also known as SOAPx4, is a NuSphere product (you can download the NuSOAP library fromhttp://sourceforge.net/projects/nusoap/). To make your PHP source files aware of NuSOAP classes, include the following code snippet:

 

require_once('./nusoap-php5-0.9/lib/nusoap.php'); 
Writing a Web Service Server
The server you'll develop with NuSOAP exposes one method: RectangleArea. As the name suggests, this method calculates the area of a rectangle. Here's the procedure for developing the web service:

><?php
// Pull in the NuSOAP code
require_once('./nusoap-php5-0.9/lib/nusoap.php');
// Create the server instance
$server = new soap_server();
// Initialize WSDL support
$server->configureWSDL('mathwsdl', 'urn:mathwsdl');
// Register the RectangleArea method to expose it
$server->register('RectangleArea',                    // method name
    array('L' => 'xsd:int', 'l' => 'xsd:int'),        // input parameters
    array('area_r' => 'xsd:string'),                  // output parameters
    'urn:mathwsdl',                                   // namespace
    'urn:RectangleAreawsdl#RectangleArea',            // soapaction
    'rpc',                                            // style
    'encoded',                                        // use
    'Calculate a rectangle area as (L*l)'             // documentation
);
// Define the RectangleArea method as a PHP function
function RectangleArea($L, $l) {
        return 'The rectangle area is: ' .($L*$l);
}
// Use the request to invoke the service
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>
A useful feature of NuSOAP is that it lets you verify that a web service exists and ensure that it exposes the methods you need—without having to develop a client.

For example, accessing http://localhost/php/SOAP_MESSAGES/server.php reveals the web service WSDL for the web service you just created (note that you didn't have to write or generate a WSDL, but the WSDL is there, nonetheless), and the service method. Next, you can see that for the RectangleArea method name you can see a list containing the information you need to write a proper web service client. Figure 1 shows a screen capture of the WSDL and the method for the server.php sample web service.
Writing a Web Service Client
After the web service server is completed and verified, you can write a NuSOAP web service client. This is easier than creating a server, as you will see in this section. You may notice that in the following listing that a client instance is created by instantiating the soapclientNusoap class; to call the web service method, you should use the NuSOAP call method.

><?php
// Pull in the NuSOAP code
require_once('./nusoap-php5-0.9/lib/nusoap.php');
// Create the client instance
$client = new soapclientNusoap('http://localhost/php/SOAP_MESSAGES/server.php?wsdl', true);
// Check for an error
$err = $client->getError();
if ($err) {
    // Display the error
    echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
    // At this point, you know the call that follows will fail
}
// Call the RectangleArea SOAP method
$result = $client->call('RectangleArea', array('L' => 40, 'l' => 20));
// Check for a fault
if ($client->fault) {
    echo '<h2>Fault</h2><pre>';
    print_r($result);
    echo '</pre>';
} else {
    // Check for errors
    $err = $client->getError();
    if ($err) {
        // Display the error
        echo '<h2>Error</h2><pre>' . $err . '</pre>';
    } else {
        // Display the result
        echo '<h2>Result</h2><pre>';
        print_r($result);
    echo '</pre>';
    }
}
?>
Write a JavaScript Web Service Client
This section describes how to create a browser web service client in JavaScript that uses AJAX technologies for the RectangleArea method.

You start by writing a simple HTML interface that lets a user specify values for the width and height arguments of the RectangleArea method. You pass the entered values to a JavaScript function named areaAjax, which will reside in a separate JavaScript module named ajaxSOAP.js.

This HTML will contain an empty <div> tag that AJAX will fill with the response received from the web service server. Here's a minimal interface (save it in the SOAP_MESSAGES folder).

The index.html listing is as follows:

<html xmlns="http://www.w3.org/1999/xhtml">
     <head>
       <meta http-equiv="content-type" content="text/html;charset=UTF-8">
       <title>Web Service SOAP and AJAX</title>           
     </head>
     <script type="text/javascript" src="./ajaxSOAP.js"></script> 
     <body>    
       <div style="position:relative;left:0px; top:-12px;background  
        color:#CC0033;margin:0px;">   
       <h2 align="center"><font color="#ffffff">
         Working with SOAP messages in PHP </font></h2></div>
       <table align="center" cellpading="0px" cellspacing="3px" 
         bordercolor="#000000" border="0" 
         style="position:relative;width:300px;height:200px;">
         <tr>   
          <td colspan="2" align="center"><h1><font color="#CC0033">
         Rectangle Area </font></h1></td>
         </tr>
         <tr>
           <td valign="center"><font color="#cc0000" size="3">
             Insert value for l:</font></td>
           <td><input id="l_id" type="text"></td>
         </tr>
         <tr>
           <td><font color="#cc0000" size="3">Insert value for L:</font></td>
           <td><input id="L_id" type="text"></td>
         </tr>
         <tr>
           <td><input type="button" value="Calculate Area" onclick="areaAjax();"></td>
         </tr>
         <tr>
          <td colspan="2">
            <div id="resultDiv"></div>
          </td>
         </tr> 
       </table>     
     </body>
   </html>
The preceding code doesn't offer an implementation for the areaAJAX function; we will do that next. The JavaScript module is named ajaxSOAP.js and will be saved in the same SOAP_MESSAGES folder as the preceding HTML code.

The areaAjax function begins by extracting the arguments that must be passed to the web service server. Remember that users provide the argument's values through the HTML interface, so you have to access the two text fields identified by the IDs l_id and L_id:

    var l_var = document.getElementById("l_id").value;
    var L_var = document.getElementById("L_id").value;
After obtaining the argument's values, you need to write the SOAP message. This simple SOAP message calls the RectangleArea method, passing it the two values that the service needs to calculate the area. For now, you'll store the SOAP message into a JavaScript variable, as you can see in the following code line fragment:

soapMessage = "<?xml version='1.0' encoding='UTF-8'?>";
   soapMessage = soapMessage + "<SOAP-ENV:Envelope SOAP-ENV:encodingStyle='http://
    schemas.xmlsoap.org/soap/encoding/' ";
   soapMessage = soapMessage + "xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' ";
   soapMessage = soapMessage + "xmlns:xsd='http://www.w3.org/2001/XMLSchema' ";
   soapMessage = soapMessage + "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' ";
   soapMessage = soapMessage + "xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/' ";
   soapMessage = soapMessage + "xmlns:tns='urn:mathwsdl'>";
   soapMessage = soapMessage + "<SOAP-ENV:Body><tns:RectangleArea xmlns:tns='urn:mathwsdl'>
    <L xsi:type='xsd:int'>" +L_var+"</L>";
   soapMessage = soapMessage + "<l xsi:type='xsd:int'>" +l_var+"</l>";
   soapMessage = soapMessage + "</tns:RectangleArea></SOAP-ENV:Body></SOAP-ENV:Envelope>";  
Next, implement the AJAX mechanism. Following a typical approach, you start by obtaining an XMLHttpRequest object and continue by opening a POST channel on the server's URL (http://localhost/php/SOAP_MESSAGES/server.php), indicating the AJAX callback function named callbackAjax:

if(window.XMLHttpRequest) {
      httpRequest=new XMLHttpRequest();
   } else if (window.ActiveXObject) { 
      httpRequest=new ActiveXObject("Microsoft.XMLHTTP"); 
   }
                  
   httpRequest.open("POST",url,true);
   if (httpRequest.overrideMimeType) { 
      httpRequest.overrideMimeType("text/xml"); 
   }
   httpRequest.onreadystatechange=callbackAjax;
The next three lines of code are not commonly used in AJAX implementations; they represent three HTML headers that will make an important contribution to the success of calling the web service. You should particularly remember to provide the MessageType header, which indicates that the message contains a call: a SOAP request.

httpRequest.setRequestHeader("Man", "POST 
   http://localhost/php/webservice/nusoap_server.php HTTP/1.1")       
httpRequest.setRequestHeader("MessageType", "CALL");
httpRequest.setRequestHeader("Content-Type", "text/xml");
Finally, you send the SOAP request and wait for the response:

httpRequest.send(soapMessage);
The complete ajaxSOAP.js javascript code looks like this:
var httpRequest = null;
var xhrTimeout = null;
var url = "http://localhost/php/SOAP_MESSAGES/server.php";
var soapMessage = null;
function areaAjax()
{
   var l_var = document.getElementById("l_id").value;
   var L_var = document.getElementById("L_id").value;
    
   soapMessage = "<?xml version='1.0' encoding='UTF-8'?>";
   soapMessage = soapMessage + "<SOAP-ENV:Envelope SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' ";
   soapMessage = soapMessage + "xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' ";
   soapMessage = soapMessage + "xmlns:xsd='http://www.w3.org/2001/XMLSchema' ";
   soapMessage = soapMessage + "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' ";
   soapMessage = soapMessage + "xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/' ";
   soapMessage = soapMessage + "xmlns:tns='urn:mathwsdl'>";
   soapMessage = soapMessage + "<SOAP-ENV:Body><tns:RectangleArea xmlns:tns='urn:mathwsdl'><L xsi:type='xsd:int'>" +L_var+"</L>";
   soapMessage = soapMessage + "<l xsi:type='xsd:int'>" +l_var+"</l>";
   soapMessage = soapMessage + "</tns:RectangleArea></SOAP-ENV:Body></SOAP-ENV:Envelope>";  
    
   if(window.XMLHttpRequest) {
      httpRequest=new XMLHttpRequest();
   } else if (window.ActiveXObject) { 
      httpRequest=new ActiveXObject("Microsoft.XMLHTTP"); 
   }
                  
   httpRequest.open("POST",url,true);
   if (httpRequest.overrideMimeType) { 
      httpRequest.overrideMimeType("text/xml"); 
   }
   httpRequest.onreadystatechange=callbackAjax;
      
   httpRequest.setRequestHeader("Man", 
      "POST http://localhost/php/webservice/server.php HTTP/1.1")
   httpRequest.setRequestHeader("MessageType", "CALL");
   httpRequest.setRequestHeader("Content-Type", "text/xml");
   httpRequest.send(soapMessage);
   xhrTimeout=setTimeout("ajaxTimeout(httpRequest);",120000);                                                
}            
                              
function callbackAjax(){
   try {
      if(httpRequest.readyState==4) {
         if(httpRequest.status==200) {
            clearTimeout(xhrTimeout);                                                             
            resultDiv=document.getElementById("resultDiv");            
            resultDiv.style.display='inline';                                          
            resultDiv.innerHTML='<font color="#cc0000" size="4"><b>' + 
               httpRequest.responseText+'</b></font>';
         }
      } 
   }catch(e) { 
      alert("Error!"+e); }      
   }
  
function ajaxTimeout(ajaxOBJ) {     
   ajaxOBJ.abort();
}
Testing the Java Script/AJAX client
Now for the fun part: testing the Java Script/AJAX client. Open your browser and browse to http://localhost/php/SOAP_MESSAGES/. You should see something similar to Figure 2.

 
Figure 2

Insert two integers in the two text fields (For example, type 45 for l and 67 for L) and press the Calculate Area button. You should now see a figure similar to Figure 3.

 
Figure 3Conclusion
Calling web services from AJAX is an interesting and natural approach, considering that web services typically respond with string messages, numbers, or images in various formats (such as SVG), while developers typically use AJAX in web pages to retrieve and display strings, numbers, and images—exactly the same kind of information.

Putting the two together is a good technique that will help you build cool interactive web sites.

猜你喜欢

转载自msibeq.iteye.com/blog/1386108