SOAP uses XML to describe data. Just like in any programming language, the way to describe data is extremely important. Imagine a SOAP client that is a Perl script, which makes a call to a SOAP server that is a large C++ program. You can be sure that (internally), Perl and C++ do not represent data in the same way. But because they both use SOAP to describe their data, they can talk to one another.
1 : <?php
2 : /* Example SOAP server, providing a function called "multiply".
3 : * Written by Greg Hamerly (11/29/2001)
4 : * This code depends on the SOAPx4 PHP library.
5 : *
6 : * Note that the only thing this file *actually does* is:
7 : * 1. create a server
8 : * 2. tell the server about our function (multiply)
9 : * 3. tell the server to service the client's request
10: */
11:
12: /* Include the client and server classes from the library (both are needed). */
13: include("class.soap_client.php");
14: include("class.soap_server.php");
15:
16: /* 1. Create a new SOAP server */
17: $server = new soap_server;
18:
19: /* 2. Tell the server about the function we will provide The "multiply"
20: * function takes two arguments (string, int) and returns an array object.
21: */
22: $server->add_to_map("multiply", array("string", "int"), array("array"));
23:
24: /* Here is the actual multiply function. It takes one argument, $x, which is an
25: * array of data that the client sent us. The data is dereferenced using the
26: * field names of the data.
27: */
28: function multiply($x) {
29: $str = $x["value"]; /* retrieve the values from the input array */
30: $times = $x["times"];
31: for ($i = 0; $i < $times; $i++) {
32: $result[] = $str; /* create an array of strings */
33: }
34: return $result;
35: }
36:
37: /* 3. Tells the server to parse the data and invoke any functions that have
38: * been called
39: */
40: $server->service($HTTP_RAW_POST_DATA);
41:
42: ?>
|
First let's look at the "multiply()" function of this file, on lines 28-35. The multiply() function is defined to take as a parameter an array. The first element in this array, indexed by "value", is the string that we are interested in multiplying. The second element, indexed by "times", is the integer number of times to multiply the string. The function then creates an array that contains "times" copies of the given string, and returns that array.
Note that the input to the multiply() function was a single array that contained all the parameters; the multiply function itself has only one parameter. Also note that there is nothing particularly unique about this function, other than an odd way of passing in parameters. But in most ways, this is a normal PHP function, and could be used outside of the context of SOAP.
Now let's look at the SOAP-specific parts of the server. On lines 13 and 14, we include the libraries that are needed. Then on line 17, we create a new soap_server object, which will handle everything for us.
On line 22, we tell the server about our function "multiply()", by giving it the name ("multiply"), the input parameters ("string", "int"), and the output parameter ("array"). These values are used for type-checking the function calls made by clients. Additionally, there are data types "float", "soapstruct", and others; but for this project you should be able to get by with what we use here.
Finally, on line 40, we tell the server to process any requests that have come in. Note that in all this, we never called the function multiply() . So how does the function get called? When the server processes the client requests, it will receive a request for the "multiply()" function. Then it will look up in its table for functions that it knows about (which we provided in line 22). Then the server object will call our function, passing it the data from the client, and it will handle returning the data from our server function back to the client.
Now that we have a taste for what this SOAP service will do, let's look at the client code (which is a little messier).
1 : <html><head><title>SOAP example</title><body>
2 : <h1>SOAP test</h1>
3 : <?
4 : /* Example SOAP client, calling a function called "multiply".
5 : * Written by Greg Hamerly (11/29/2001)
6 : * This code depends on the SOAPx4 PHP library.
7 : */
8 :
9 : /* include this for access to SOAPx4 library */
10: include("class.soap_client.php");
11:
12: /* declare the server, the method to call, and the data to send */
13: $server = "http://ai.ucsd.edu/~ghamerly/134A/soap/multiply_server.php";
14: $method = "multiply";
15: $data = array("value" => "foo", "times" => 5);
16:
17: print("<b>Data to send:</b><br>\n");
18: print_r($data);
19: print("<p>\n");
20:
21: /* create the client that will send the data */
22: $soap_client = new soap_client($server);
23:
24: /* create a SOAP message to send */
25: $soap_message = new soapmsg($method, $data);
26:
27: $return = $soap_client->send($soap_message, "foo" /*"urn:soapinterop"*/);
28: if ($return) {
29: /* Assume that we got here without an error... more error checking is
30: * really required here.
31: */
32: print("<b>Data received:</b><br>\n");
33: /* Get the data we're interested in, and print it out. The next few lines
34: * will differ depending on which type of data you get back (e.g. scalar,
35: * array, object).
36: */
37: $outdata = $return->decode();
38: $outdata = $outdata["multiply"];
39: foreach ($outdata as $key => $value) {
40: print("$key => $value<br>\n");
41: }
42: } else {
43: print("An error has occurred\n");
44: }
45: print "<hr><strong>Request:</strong><br>\n";
46: print "<xmp>$soap_client->outgoing_payload</xmp><br>";
47: print "<strong>Response:</strong><br>\n";
48: print "<xmp>$soap_client->incoming_payload</xmp>";
49:
50: ?>
51: </body></html>
|
This SOAP client program does several things:
The soap client and message creation (lines 22, 25) are fairly self-explanatory. The message send() operation on line 27 requires the message to send, and returns the data that the server sends into the variable $return.
The error checking we do here (line 28) is really not enough. We have taken much of it out to simplify it. To do better error checking, we should do the following within the if statement on line 28:
if (get_class($return) == "soapval"){
print "Correctly decoded server's response";
if (eregi("fault",$return->name)){
$status = "failed";
} else {
$status = "passed";
}
} else {
print "Client could not decode server's response";
}
Once we have done the call/return and checked for any errors, we need to
retrieve our data. This is done on lines 37-41, where we first call $return->decode()
to get an array of return values. This array is indexed by the method we
called ("multiply"), which contains another array, which is the data we're
actually interested in. Then we print out that data.
Of course, to create your own SOAP client/server application for project
4, you will have to do more than I have done here. However, you may use
this example as a stepping stone to get you to where you need to be.