SOAP practical using in PHP 5
SOAP (Simple Object Access Protocol) is a protocol based on XML; it used for structured information exchange. SOAP specification defines the format used by XML messages, coding rules set and data types.
Web-service is a modern technology. The amount of technologies that concern the web-services increases every day. But SOAP is one of the most important technologies. It becomes the standard protocol of web-service access. It uses the XML messages for information exchange and provides some advantages of binary protocols. RPC (Remote Procedure Calls) support has been a minor opportunity for a long period of time, but now it is the most used opportunity.
SOAP extension has a lot of specifications, such as SOAP 1.1, SOAP 1.2 and WSDL 1.1. The main purpose is to use SOAP PRC-means as much as possible.
First SOAP-client
To demonstrate the creating of SOAP-client we will use "Delayed Stock Quote" service. Before writing the PHP-script we have to find the following information:
- Method’s name
- URL where that service is situated
- Value of SOAPAction method header
- Method’s namespace
- Names and types of input and output parameters of the method
That information we can get in the XMethods site.
| Method’s name | getQuote |
| Service URl | http://66.28.98.121:9090/soap |
| SOAPAction | urn:xmethods-delayed-quotes#getQuote |
| Method’s namespace | urn:xmethods-delayed-quotes |
| Input parameters | Symbol (String) |
| Output parameters | Result (float) |
Example 1. (client1.php)
<?php
$client = new SoapClient(NULL,
array(
"location" => "http://66.28.98.121:9090/soap",
"uri" => "urn:xmethods-delayed-quotes",
"style" => SOAP_RPC,
"use" => SOAP_ENCODED
));
print($client->__call(
/* SOAP-method name */
"getQuote",
/* parameters*/
array(
new SoapParam(
/* Parameter value */
"ibm",
/* Parameter name */
"symbol"
)),
/* Options */
array(
/* SOAP-method namespace */
"uri" => "urn:xmethods-delayed-quotes",
/* HTTP-header SOAPAction for SOAP-method*/
"soapaction" => "urn:xmethods-delayed-quotes#getQuote"
)). "\n");
?>
Here is the same client adapted for forking with the help of that WSLD-document. Here we don’t have to show the server URL, namespace, SOAPAction header, the encoding method and parameters’ types. Everything is taken from the WSDL file.
Example 2. (client2.php)
?php
$client = new
SoapClient(
"http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl"
);
print($client->getQuote("ibm"));
?>
What problems can appear using WSDL? The main disadvantage is that client should read WSDL from the server and it can take a lot of time. For increasing the speed of working in the SOAP extension there can be used some configuration parameters, such as soap.wsdl_cache_enabled, soap.wsdl_cache_dir and soap.wsdl_cache_ttl. They can be set in the php.ini file or with the help of ini_set().
Here is a SOAP item in the php.ini file. You can copy them to your php.ini.
[soap]
soap.wsdl_cache_enabled = "1"
; enables or disables WSDL caching
soap.wsdl_cache_dir = "/tmp"
; set the directory name where SOAP-extension stores the caching files
soap.wsdl_cache_ttl = "86400"
;
First SOAP-server
Let’s write our own SOAP-server that will work as "Delayed Stock Quote" on XMethods. At first we have to create WSDL document.
Message issue has two messages. First is getQuoteRequest that transmits the message getQuote and gets parameter with name symbol. Second message is getQuoteResponse; it is a response to getQuote request.
portType issue defines the only operation getQuote that defines the messages for request and response.
In the binding issue are defined the ways of message transmitting and encoding. In our case we’ll send the RPC-request by HTTP and use the SOAP-encoding. Namespace and SOAPAction header’s value are defined too.
URL is defined in the service issue.
Example 3. (stockquote.wsdl)
<?xml version ="1.0" encoding ="UTF-8" ?>
<definitions name="StockQuote"
targetNamespace="http://example.org/StockQuote"
xmlns:tns=" http://example.org/StockQuote "
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<message name="getQuoteRequest">
<part name="symbol" type="xsd:string"/>
</message>
<message name="getQuoteResponse">
<part name="Result" type="xsd:float"/>
</message>
<portType name="StockQuotePortType">
<operation name="getQuote">
<input message="tns:getQuoteRequest"/>
<output message="tns:getQuoteResponse"/>
</operation>
</portType>
<binding name="StockQuoteBinding" type="tns:StockQuotePortType">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getQuote">
<soap:operation soapAction="urn:xmethods-delayed-quotes#getQuote"/>
<input>
<soap:body use="encoded" namespace="urn:xmethods-delayed-quotes"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="urn:xmethods-delayed-quotes"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="StockQuoteService">
<port name="StockQuotePort" binding="StockQuoteBinding">
<soap:address location="http://[insert real path here]/stockquote1.php"/>
</port>
</service>
</definitions>
Notice: WSDL caching is enabled by default. But it is better to disable it for a while.
Now it is a high time to create our server.
At first we’ll develop the getQuote() function that will process the input queries from the web. Then we’ll create the SoapServer class object and connetct our function to it by means of SoapServer::addFunction() method.
Example 4. (server1. php)
<?php
$quotes = array(
"ibm" => 98.42
);
function getQuote($symbol) {
global $quotes;
return $quotes[$symbol];
}
ini_set("soap.wsdl_cache_enabled", "0"); // disable WSDL caching
$server = new SoapServer("stockquote1.wsdl");
$server->addFunction("getQuote");
$server->handle();
?>
SoapServer can work without WSDL, but there are no advantages of using of that method.
Here is a client for accessing our SOAP-server. File "stockquote1.wsdl" should be located in the same directory with SOAP-server.
Example 5. (client3.php)
<?php
$client = new SoapClient("stockquote1.wsdl");
print($client->getQuote("ibm"));
?>
We have some problems in out client and server.
At first they don’t process the errors. What does server do if it can’t find the appropriate result for symbol variable value? There is a special message format in the SOAP for reporting the errors – SoapFault. To generate that message server has to call the exception with the help of SoapFault object. First parameter of SoapFault() constructor is a line with the code of the error, second parameter is a line with the error’s description.
Secondly, web-service functionality should be encapsulated to the PHP-class. In that case there is no need to use the global variables and add to the server every SOAP-method separately. Instead of it we can add the whole class and all its methods will accessible by SOAP. Modified versions of client and server are situated below.
Example 6 (server2.php)
<?php
class QuoteService {
private $quotes = array("ibm" => 98.42);
function getQuote($symbol) {
if (isset($this->quotes[$symbol])) {
return $this->quotes[$symbol];
} else {
throw new SoapFault("Server","Unknown Symbol "$symbol".");
}
}
}
$server = new SoapServer("stockquote2.wsdl");
$server->setClass("QuoteService");
$server->handle();
?>
As you can see I’ve used SoapServer::setClass() method SoapServer object connecting with the QuoteService class.
Example 6 (client4.php)
<?php
$client = new SoapClient("stockquote2.wsdl");
try {
echo "<pre>\n";
print($client->getQuote("ibm"));
echo "\n";
print($client->getQuote("microsoft"));
echo "\n</pre>\n";
} catch (SoapFault $exception) {
echo $exception;
}
?>
And what is inside?
As you could see in the first example SoapClient() constructor’s second parameter is the associative array. With the help of that array we can call different option on the server.
We’ll view only two of them:
- trace – allows client saving the SOAP-requests and responses (enabled by default).
- exceptions – allow client controlling the exceptions mechanism (enabled by default).
Let’s view the next example of the SOAP-client. It is updated client from the Example 5. It shows what is transmitted between client and server. For getting such information we have to use __getLastRequest() and __getLastResponse() methods.
Example 8 (client5.php)
<?php
$client = new SoapClient("stockquote1.wsdl",array(
"trace" => 1,
"exceptions" => 0));
$client->getQuote("ibm");
print "<pre>\n";
print "?????? :\n".htmlspecialchars($client->__getLastRequest()) ."\n";
print "?????:\n".htmlspecialchars($client->__getLastResponse())."\n";
print "</pre>";
?>
Request
<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:xmethods-delayed-quotes"
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/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:getQuote>
<symbol xsi:type="xsd:string">ibm</symbol>
</ns1:getQuote>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Response
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:xmethods-delayed-quotes"
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/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:getQuoteResponse>
<Result xsi:type="xsd:float">98.42</Result>
</ns1:getQuoteResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Resume
In that article I’ve described only some functions of the SOAP-extension. But there are a lot of them. Here are the main functions:
- Complex data types support (arrays, objects)
- SOAP – headers support
- Dynamic support of SOAP 1.1 and SOAP 1.2



