PHP SOAP
March 15th, 2008SOAP (Simple Object Access Protocol) = Useful way to communicate with different machines. SOAP is used with java quite a lot, but not so much with PHP. However doing the same stuff with php is rather easyish.Prequisits:
- PHP with lib2xml and SOAP (dll) installed and enabled
- Of course, you need Apache.
The easiest part is propably the server. When client sends the request, the request is forwarded to a php-script, and one single function call occurs. The soap-server needs to be initiated within the script, and the method registerd. The server initialitation:
<pre style=’font-size:100%’>
ini_set(“soap.wsdl_cache_enabled”, “0″); // disabling WSDL cache
$server = new SoapServer(“SoapServerTest.wsdl”);
$server->addFunction(“getInfo”);
$server->handle();
</pre>
The ini-value, even when set from php.ini, didn’t seem to work for me. Now the SOAP -server is running, and one function, ”getInfo”, is registered. The handle -function executes the call, when script is run. The function is just simple php-function. If parameters are sent through SOAP, the are as parameters of the function.
<pre style=”font-size: 150%”>
function getInfo($param) {
return “This is php soap server:” . $param;
}
</pre>
And return value is sent as response. The client is created sort of similar way (short and easy, that is):
<pre style=”font-size: 150%”>
$client = new SoapClient(“http://yourLogin:yourPassword@127.0.0.1/tests/SoapServerTest.wsdl”, array(
“login” => “yourLogin”,
“password” => “yourPassword”,
“trace” => 1,
“exceptions” => 0));
echo $client->getInfo(“Possu!”);
</pre>
A new SOAPClient object is created, and as parameter there is the address of the service. The client then calls the getInfo -parameter. You can check the sent / received requests by:
<pre style=”font-size: 150%”>
print “<pre>\n”;
print “Request :\n”.htmlspecialchars($client->__getLastRequest()) .“\n”;
print “Response:\n”.htmlspecialchars($client->__getLastResponse()).“\n”;
print “</pre>”;
</pre>
The SOAP envelope and SOAP body are created by the SOAP -class. Now the most complex (at least for me) part is missing, that wsdl -thingie. WSDL (Web Service Definition Language) is, surprisingly, language to define web services. Some parts on the WSDL to show:
<pre style=”font-size:150%;”>
<message name=’getInfoRequest’>
<part name=’MyStringParameter’ type=’xsd:string’/>
</message>
</pre>
Inside that message more parameters can be added. The XML -payload within the SOAP body is about:
<pre style=”font-size:150%;”>
<SOAP-BODY>
<MyStringParameter>
Possu!
</MyStringParameter>
</SOAP-BODY>
</pre>
In the longish WSDL names need to equal to types, etc… but these are easy to figure out.
When sending xml as parameters to the SOAP server, the xml can be sent string, thou this is quite baddish practise. To do it right, you need to define the types with xsd:
<pre style=”font-size:150%;”>
<message name=’getInfoRequest’>
<part name=’MyComplexParameter’ type=’tns:ComplexVariable’/>
</message>
</pre>
And with XSD:
<pre style=”font-size:150%;”>
<types>
<schema>
<element name="ComplexVariable">
<complexType>
<sequence>
<element name="SomeStuff" type="string"/>
<element name="AnotherParameter" type="string"/>
</sequence>
</complexType>
</element>
</schema>
</pre>
And so on… I’ve been working only with simple parameters, making the SOAP -client usually with Java. The wholse WSDL -file for working test:
<pre style=”font-size:150%;”>
<?xml version =’1.0′ encoding =’UTF-8′ ?>
<definitions name=’MySOAPTest’
targetNamespace=’http://example.org/MySOAPTest’
xmlns:tns=’ http://example.org/MySOAPTest ‘
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=’getInfoRequest’>
<part name=’MyStringParameter’ type=’xsd:string’/>
</message>
<message name=’getInfoResponse’>
<part name=’Result’ type=’xsd:string’/>
</message>
<portType ename=’InfoPortType’>
<operation name=’getInfo’>
<input message=’tns:getInfoRequest’/>
<output message=’tns:getInfoResponse’/>
</operation>
</portType>
<binding name=’InfoBinding’ type=’InfoPortType’>
<soap:binding style=’rpc’
transport=’http://schemas.xmlsoap.org/soap/http’/>
<operation name=’getInfo’>
<soap:operation soapAction=’urn:xmethods-delayed-quotes#getInfo’/>
<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=’InfoService’>
<port name=’InfoPortType’ binding=’InfoBinding’>
<soap:address location=’http://127.0.0.1/tests/SoapServerTest.php’/>
</port>
</service>
</definitions>
</pre>
More stuff to read:
-
WSDL @ W3C: http://www.w3.org/TR/wsdl
-
XML Schema: http://www.w3.org/TR/xmlschema-2/
-
Clear example of complexisish wsdl: http://www.extreme.indiana.edu/karma/docs/karma.wsdl


