This document follows up Introduction to NuSOAP, Programming with NuSOAP, and Programming with NuSOAP Part 2 with additional samples that demonstrate how to use NuSOAP to create and consume SOAP web services using WSDL.
Hello, World Redux
The New Client
Defining New Data Structures
Hello, World Redux
Showing no imagination whatsoever, I used the ubiquitous "Hello, World" example in Introduction to NuSOAP. In that document, I showed the SOAP request and response exchanged by the client and server. Here, I extend that sample to use WSDL.
A WSDL document provides metadata for a service. NuSOAP allows a programmer to specify the WSDL to be generated for the service programmatically using additional fields and methods of the soap_server class.
The service code must do a number of things in order for correct WSDL to be generated. Information about the service is specified by calling the configureWSDL method. Information about each method is specified by supplying additional parameters to the register method. Service code for using WSDL is shown in the following example.
// Pull in the NuSOAP code
require_once('nusoap.php');
// Create the server instance
$server = new soap_server();
// Initialize WSDL support
$server->configureWSDL('hellowsdl', 'urn:hellowsdl');
// Register the method to expose
$server->register('hello', // method name
array('name' => 'xsd:string'), // input parameters
array('return' => 'xsd:string'), // output parameters
'urn:hellowsdl', // namespace
'urn:hellowsdl#hello', // soapaction
'rpc', // style
'encoded', // use
'Says hello to the caller' // documentation
);
// Define the method as a PHP function
function hello($name) {
return 'Hello, ' . $name;
}
// Use the request to (try to) invoke the service
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>
Now for some magic. Point a Web browser at this service, which in my environment is at http://localhost/phphack/hellowsdl.php. The HTML that is returned to your browser gives you links to view the WSDL for the service or view information about each method, in this case the hello method. The screen should look something like this.
hellowsdl
View the WSDL for the service. Click on an operation name to view it's details.
hello
Displaying the details for the hello operation looks something like this.
hellowsdl
View the WSDL for the service. Click on an operation name to view it's details.
hello
Close
Name: hello
Binding: hellowsdlBinding
Endpoint: http://localhost/phphack/hellowsdl.php
SoapAction: urn:hellowsdl#hello
Style: rpc
Input:
use: encoded
namespace: urn:hellowsdl
encodingStyle: http://schemas.xmlsoap.org/soap/encoding/
message: helloRequest
parts:
name: xsd:string
Output:
use: encoded
namespace: urn:hellowsdl
encodingStyle: http://schemas.xmlsoap.org/soap/encoding/
message: helloResponse
parts:
return: xsd:string
Namespace: urn:hellowsdl
Transport: http://schemas.xmlsoap.org/soap/http
Documentation: Says hello to the caller
So, with just a little code added to the service, NuSOAP provides browsable documentation of the service. But, that is not all. By either clicking the WSDL link on the documentation page, or by pointing the browser at the service with a query string of ?wsdl (e.g. http://localhost/phphack/hellowsdl.php?wsdl), you get the following WSDL.
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd"
xmlns:tns="urn:hellowsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="urn:hellowsdl">
Return to top.
The New Client
Adding a few NuSOAP WSDL calls to the service allows it to generate WSDL and other documentation. By comparison, client support for WSDL is anti-climactic, at least for this simple example. The simple client shown below is not much different than the non-WSDL client. The only difference is that the constructor for the soapclient class is provided the URL of the WSDL, rather than the service endpoint.
// Pull in the NuSOAP code
require_once('nusoap.php');
// Create the client instance
$client = new nusoap_client('http://localhost/phphack/hellowsdl.php?wsdl', true);
// Check for an error
$err = $client->getError();
if ($err) {
// Display the error
echo '
Constructor error
' . $err . '';
// At this point, you know the call that follows will fail
}
// Call the SOAP method
$result = $client->call('hello', array('name' => 'Scott'));
// Check for a fault
if ($client->fault) {
echo '
Fault
';';
print_r($result);
echo '
} else {
// Check for errors
$err = $client->getError();
if ($err) {
// Display the error
echo '
Error
' . $err . '';
} else {
// Display the result
echo '
Result
';';
print_r($result);
echo '
}
}
// Display the request and response
echo '
Request
';echo '
' . htmlspecialchars($client->request, ENT_QUOTES) . '';
echo '
Response
';echo '
' . htmlspecialchars($client->response, ENT_QUOTES) . '';
// Display the debug messages
echo '
Debug
';echo '
' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '';
?>
Here are the request and response for this WSDL implementation.
POST /phphack/hellowsdl.php HTTP/1.0
Host: localhost
User-Agent: NuSOAP/0.6.8 (1.81)
Content-Type: text/xml; charset=ISO-8859-1
SOAPAction: "urn:hellowsdl#hello"
Content-Length: 550
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd"
xmlns:tns="urn:hellowsdl">
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Wed, 03 Nov 2004 21:05:34 GMT
X-Powered-By: ASP.NET
X-Powered-By: PHP/4.3.4
Server: NuSOAP Server v0.6.8
X-SOAP-Server: NuSOAP/0.6.8 (1.81)
Content-Type: text/xml; charset=ISO-8859-1
Content-Length: 551
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd">
Return to top.
Defining New Data Structures
An important aspect of WSDL is that it can encapsulate one or more XML Schema, allowing programmers to describe the data structures used by a service. To illustrate how NuSOAP supports this, I will add WSDL code to the SOAP struct example in Programming with NuSOAP Part 2.
The service code gains the changes already shown in the Hello, World example, but it also has code to define the Person data structure.
// Pull in the NuSOAP code
require_once('nusoap.php');
// Create the server instance
$server = new soap_server();
// Initialize WSDL support
$server->configureWSDL('hellowsdl2', 'urn:hellowsdl2');
// Register the data structures used by the service
$server->wsdl->addComplexType(
'Person',
'complexType',
'struct',
'all',
'',
array(
'firstname' => array('name' => 'firstname', 'type' => 'xsd:string'),
'age' => array('name' => 'age', 'type' => 'xsd:int'),
'gender' => array('name' => 'gender', 'type' => 'xsd:string')
)
);
$server->wsdl->addComplexType(
'SweepstakesGreeting',
'complexType',
'struct',
'all',
'',
array(
'greeting' => array('name' => 'greeting', 'type' => 'xsd:string'),
'winner' => array('name' => 'winner', 'type' => 'xsd:boolean')
)
);
// Register the method to expose
$server->register('hello', // method name
array('person' => 'tns:Person'), // input parameters
array('return' => 'tns:SweepstakesGreeting'), // output parameters
'urn:hellowsdl2', // namespace
'urn:hellowsdl2#hello', // soapaction
'rpc', // style
'encoded', // use
'Greet a person entering the sweepstakes' // documentation
);
// Define the method as a PHP function
function hello($person) {
$greeting = 'Hello, ' . $person['firstname'] .
'. It is nice to meet a ' . $person['age'] .
' year old ' . $person['gender'] . '.';
$winner = $person['firstname'] == 'Scott';
return array(
'greeting' => $greeting,
'winner' => $winner
);
}
// Use the request to (try to) invoke the service
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>
Besides the additional code to support WSDL, the code for the service method itself is changed slightly. With WSDL, it is no longer necessary to use the soapval object to specify the name and data type for the return value.
Similarly, the WSDL client does not need to use a soapval to specify the name and data type of the parameter, as shown in the following code.
// Pull in the NuSOAP code
require_once('nusoap.php');
// Create the client instance
$client = new soapclient('http://localhost/phphack/hellowsdl2.php?wsdl', true);
// Check for an error
$err = $client->getError();
if ($err) {
// Display the error
echo '
Constructor error
' . $err . '';
// At this point, you know the call that follows will fail
}
// Call the SOAP method
$person = array('firstname' => 'Willi', 'age' => 22, 'gender' => 'male');
$result = $client->call('hello', array('person' => $person));
// Check for a fault
if ($client->fault) {
echo '
Fault
';';
print_r($result);
echo '
} else {
// Check for errors
$err = $client->getError();
if ($err) {
// Display the error
echo '
Error
' . $err . '';
} else {
// Display the result
echo '
Result
';';
print_r($result);
echo '
}
}
// Display the request and response
echo '
Request
';echo '
' . htmlspecialchars($client->request, ENT_QUOTES) . '';
echo '
Response
';echo '
' . htmlspecialchars($client->response, ENT_QUOTES) . '';
// Display the debug messages
echo '
Debug
';echo '
' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '';
?>
WSDL enables one more capability on the client. Instead of using the call method of the soapclient class, a proxy can be used. The proxy is a class that mirrors the service, in that it has the same methods with the same parameters as the service. Some programmers prefer to use proxies because the code reads as method calls on object instances, rather than invocations through the call method. A client that uses a proxy is shown below.
// Pull in the NuSOAP code
require_once('nusoap.php');
// Create the client instance
$client = new soapclient('http://localhost/phphack/hellowsdl2.php?wsdl', true);
// Check for an error
$err = $client->getError();
if ($err) {
// Display the error
echo '
Constructor error
' . $err . '';
// At this point, you know the call that follows will fail
}
// Create the proxy
$proxy = $client->getProxy();
// Call the SOAP method
$person = array('firstname' => 'Willi', 'age' => 22, 'gender' => 'male');
$result = $proxy->hello($person);
// Check for a fault
if ($proxy->fault) {
echo '
Fault
';';
print_r($result);
echo '
} else {
// Check for errors
$err = $proxy->getError();
if ($err) {
// Display the error
echo '
Error
' . $err . '';
} else {
// Display the result
echo '
Result
';';
print_r($result);
echo '
}
}
// Display the request and response
echo '
Request
';echo '
' . htmlspecialchars($proxy->request, ENT_QUOTES) . '';
echo '
Response
';echo '
' . htmlspecialchars($proxy->response, ENT_QUOTES) . '';
// Display the debug messages
echo '
Debug
';echo '
' . htmlspecialchars($proxy->debug_str, ENT_QUOTES) . '';
?>
Regardless of whether the "regular" or proxy coding style is used, the request and response messages are the same.
POST /phphack/hellowsdl2.php HTTP/1.0
Host: localhost
User-Agent: NuSOAP/0.6.8 (1.81)
Content-Type: text/xml; charset=ISO-8859-1
SOAPAction: "urn:hellowsdl2#hello"
Content-Length: 676
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd"
xmlns:tns="urn:hellowsdl2">
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Wed, 03 Nov 2004 21:20:44 GMT
X-Powered-By: ASP.NET
X-Powered-By: PHP/4.3.4
Server: NuSOAP Server v0.6.8
X-SOAP-Server: NuSOAP/0.6.8 (1.81)
Content-Type: text/xml; charset=ISO-8859-1
Content-Length: 720
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd"
xmlns:tns="urn:hellowsdl2">
Hello, Willi. It is nice to meet a 22 year old male.
Return to top.
You can download the source for these examples as well.
Return to top.
Resources
Join the NuSOAP mailing list to learn more and ask questions.
The home of the NuSOAP project.
NuSOAP home of Dietrich Ayala, the author of NuSOAP.
PS : If you use PHP5, Use nusoap_client() instead of soapclient(). PHP5 has some problem with legacy functions on NuSoap. Otherwise you will occurs error [PHP Fatal error: SoapClient::SoapClient() Invalid parameters]
reference : http://www.scottnichol.com/nusoapprogwsdl.htm
沒有留言:
張貼留言