December 20, 2014
Hot Topics:

Developing SOAP and RPC Web Services with PHP 5

  • May 14, 2009
  • By Vlad Kofman
  • Send Email »
  • More Articles »

Developing PHP Web Services

With standard PHP distribution several toolkits already exist or were recently added to facilitate creation and consumption of the web services. Some third party toolkits existed for a while and are either very stable or abandoned at the time of this writing (April, 2009). For instance, a popular toolkit NuSOAP for SOAP based development is currently stable, but has not been updated since July 2005. The NuSOAP (0.7.1) project is currently hosted by sourceforge.net and has not been updated in a while. On the other hand phpxmlrpc (version 2.2.2) toolkit for development of xmlrpc services is also hosted on sourceforge.net and the last update was in March 16, 2009. Yet another third party toolkit comes with the Zend Framework and it offers XML-RPC implementation that includes both client and server.

Latest PHP distribution comes with two native extensions ext/php_xmlrpc and ext/php_soap which are designed for ws development. You will need to install these extensions (or one of them) and make sure they are enabled in the php.ini

 Ex. From windows php.ini :
[PHP_XMLRPC]
extension=php_xmlrpc.dll   

Creating SOAP PHP Web Service

The examples in this article are done with PHP 5 and Apache 2 web server, so before diving in the actual implementation, you should have Apache web server and PHP installed. During PHP installation you should specify that you want to use Apache and enable xml-rpc and xml-soap extensions.

I have used the native extensions for the examples here. Using native extensions for XML-RPC and SOAP is straight forward. If you know how to create contract first services and have understanding of wsdl you can create wsdl file and then construct soap server and pass url of your wsdl. You can also construct soap server in a non-wsdl mode, passing null and url for namespace use. If you are not familiar with SOAP concepts, you can use xml-rpc approach described further.

In my example below, I will create a web server which will take a numeric array as a parameter and return sum of all the elements. This will be done first via SOAP methodology and then via XML - RPC.

SOAP Implementation

To create Service Server with SOAP methodology you need to create wsdl file which will define communication structure, then create php code file for server and client.

Examples of WSDL file - note in bold server will accept array and return string Also note at the end the server endpoint is specified for the incoming requests and the available operation name (getHW).

<?xml version ='1.0' encoding ='UTF-8' ?> 
 

<message name='getHWRequest'> 
  <part name='id' type='xsd:array'/> 
</message> 
<message name='getHWResponse'> 
  <part name='Result' type='xsd:string'/> 
</message> 

<portType name='HWPortType'> 
  <operation name='getHW'> 
    <input message='tns:getHWRequest'/> 
    <output message='tns:getHWResponse'/> 
  </operation> 
</portType> 

<binding name='HWBinding' type='tns:HWPortType'> 
  <soap:binding style='rpc'    transport='http://schemas.xmlsoap.org/soap/http'  /> 
  <operation name='getHW'> 
    <soap:operation soapAction='urn:localhost-hw#getHW'/> 
    <input> 
      <soap:body use='encoded' namespace='urn:localhost-hw' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/> 
    </input> 
    <output> 
      <soap:body use='encoded' namespace='urn:localhost-hw' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/> 
    </output> 
  </operation> 
</binding> 

<service name='HWService'> 
  <port name='HWPort' binding='HWBinding'>
  <soap:address location='http://localhost/soap-server.php'/> 
  </port> 
</service>
</definitions>

SOAP SERVER CODE

Creating SOAP server object is very simple in PHP

Ex:

$server = new SoapServer("some.wsdl");

Or in non-wsdl mode

$server = new SoapServer(null, array('uri' => "http://test-uri/"));

So for my example it's this:

$server = new SoapServer("hw.wsdl");

I also need to register the actual function to be executed and start handling of the incoming requests:

$server->addFunction("getHW"); 
$server->handle(); 

Full code:

<?php 

function getHW($arr) { 

$result  =  array_sum($arr);
  
return "<HTML>
 <HEAD>
  <TITLE>SOAP Server Example</TITLE>
 </HEAD
 <BODY>
 <table>
 <tr>
  <th>SOAP Server Example - adding array on the server</th>  
 </tr>
 <tr>
  <td>$arr[0] + $arr[1] = $result</td>  
 </tr>
</table>
</BODY>
</HTML>";
} 

ini_set("soap.wsdl_cache_enabled", "0"); 
$server = new SoapServer("hw.wsdl");
$server->addFunction("getHW"); 
$server->handle(); 

?>

SOAP CLIENT CODE:

The client code is even simpler. You need to indicate where is the "contract" - wsdl file, and make client call a function per the defintinon passing numeric array.

<?php  
  $client = new SoapClient("http://localhost/hw.wsdl");
  $response = $client->getHW(array(1,2));
  echo $response;
?>

The result will looks like 1 + 2 = 3

Creating XML-RPC PHP Web Service

XML-RPC SERVER CODE

The RPC does not require creation of the wsdl file; it only requires creation of the server and registration of the methods (calls) to be made.

$server = xmlrpc_server_create();
xmlrpc_server_register_method($server, 'math.add', array('Math', 'add'));

In this case a "Math" object is called which will execute method "add"

<?php
/**
 * Math methods
 */
class Math
{
    /**
     * Return the sum of all values in an array
     * 
     * @param array $values An array of values to sum
     * @return int
     */
    public static function add($method, $params)
    {
       return array_sum($params[0]);
    }
}

$server = xmlrpc_server_create();
xmlrpc_server_register_method($server, 'math.add', array('Math', 'add'));
$request = file_get_contents('php://input');
$response = xmlrpc_server_call_method($server, $request, null);
header('Content-Type: text/xml');
echo $response;
?>

XML-RPC CLIENT CODE:

The RPC client is a little more work that the soap client, because request context needs to be created before the call is made.

$context = stream_context_create(array('http' => array(
      'method' => "POST",
      'header' => "Content-Type: text/xml",
      'content' => $request
  )));

The rest is similar to soap client, where response is processed and is displayed

Full source:

<?php

try
{ 
  $requestArr = array(1,2);
  $request = xmlrpc_encode_request('math.add',array($requestArr),array('encoding' => 'UTF-8')); 
  
  $context = stream_context_create(array('http' => array(
      'method' => "POST",
      'header' => "Content-Type: text/xml",
      'content' => $request
  )));
  $file = file_get_contents('http://localhost/xmlrpc-server.php', false, $context);
   
   if(!$file) {
     throw new Exception('Unable to get response from web service');
   }
   
  $response = xmlrpc_decode($file);

  echo 'XML RPC Example - adding array on the server<br>';
  echo $requestArr[0] . ' + ' . $requestArr[1] . ' = ' . $response;
}
catch (Exception $e)
{
  echo $e->getMessage();
}

?>

The client shows 1+2=3, same as the soap client.

Note that this client also has more error handling then the soap client, but this is by design.

Table 1: SOAP functions

Method Description
SoapServer->__construct( mixed wsdl [, array options] ) Creates a SoapServer object. The wsdl parameter specifies the URI of the WSDL. SoapServer options such as SOAP version may be specified in the options array.
SoapServer->addFunction( mixed functions ) Adds one or more PHP functions that will handle SOAP requests. A single function may be added as a string. More than one function may be added as an array.
SoapServer->fault() SoapServer fault indicating an error.
SoapServer->getFunctions() Returns a list of functions.
SoapServer->handle() Processes a SOAP request, invokes required functions and sends back a response.
SoapServer->setClass(string class_name [, mixed args [, mixed ...]] ) Sets the class that will handle SOAP requests. Exports all methods from the specified class. The args are used by the default class constructor.
SoapHeader->__construct() Creates a SOAP header.
SoapClient->__soapCall( string function_name, array arguments [, array options [, mixed input_headers [, array &output_headers]]] ) Invokes a SOAP function.
SoapClient->__doRequest() Performs a SOAP request.
SoapClient->__getFunctions() Returns a list of SOAP functions.
SoapClient->__getTypes() Returns a list of SOAP types.

Conclusion

In this article I have discussed two standard ways to produce and consume web services in PHP. I have also mentioned several third party modules that are designed for PHP ws development. It is good to see that all the latest standards (such as W3C SOAP specification) are supported in PHP, which further reinstates usability of the language and its value in the world of web development.

Source Files

Source files: webservices_php_files.zip

About the Author

Vlad Kofman is working on the enterprise-scale projects for the major Wall Street firms. He has also worked on the defense contracts for the U.S. government. His main interests are object oriented programming methodologies, UI and the design patterns.

References:


Tags: PHP, PHP 5, Web services, programming, SOAP



Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel