http://www.developer.com/

Back to article

Developing SOAP and RPC Web Services with PHP 5


May 14, 2009

In the constantly changing world of web development, PHP technology has proven to be versatile and practical. It had evolved from the simple scripting language originally created in 19951 to the full fledged enterprise grade web technology platform with vast amount of third party modules, extensive API library, support for object oriented development, namespaces, robust database access, and mush more. In this article I fill focus on development of web services with PHP. I will explore various toolkits that are available and discuss the best ways to create web services in your PHP applications.

1PHP was originally created by Rasmus Lerdorf in 1995

Brief History of PHP

Since the late nineties, PHP (hypertext processor) gained popularity because of its simplicity and specifics geared toward web development. Currently PHP is powering more then 20 million websites2 and web products including some of the most popular sites, such as Facebook, as well as, content management tools such as, Joomla or Wordpress. PHP is free software and is released under the PHP License (different from GNU license).

2http://www.php.net/usage.php

Due to its open source structure, PHP technology is a natural fit with other open source or free technologies used by many startups or small to medium businesses to develop and maintain their web presence and online businesses. Many sites run on what is known as LAMP — Linux, Apache, MySQL and PHP. Which means that the operation system is some flavor of Linux, web server is Apache, database is MySQL, and application server logic or dynamic portion of the site is handled by the PHP. The combination of these products represents the best free source solution to develop and host the web business with minimum upfront costs. PHP technology is scalable and able to handle millions of transactions and requests. However, because of its open source nature and lack of formal support, it is still not very popular among the large enterprises.

PHP has evolved dramatically from its roots, to becoming a fully object oriented language in its 5th edition. It is supported, managed and maintained by PHP group, has a very active developer community and is a de facto standard for most of the online hosting providers (many of whom in the past primarily used CGI to handle dynamic rendering of html).

In addition to object oriented aspects, the language includes plentitude of prebuilt functions, modules and libraries to help with any imaginable web development task. PHP includes build in database support, error and exception handling, advanced string manipulation library and powerful regular expression engine. Other standard features incude networking and email support, session handling, web services toolkits, and much more.

Web services standards – SOAP, XML RPC and REST

There are many books and articles written about web services, and I also covered this technology in the article Enterprise Java Contract-First vs. Contract-Last Web Services. There are also several books specifically devoted to development and consumption of web services with PHP. For the purposes of this article I will briefly mention several standards for web services development and then dive into some actual implementation in PHP.

The three main methodologies for developing web services in PHP (as well as other languages) are SOAP, XML RPC and REST. SOAP or Simple Object Access Protocol is a w3c standard and very popular web service development methodology in the modern enterprise world. With SOAP xml documents and XML schema for communication between client and server are established and services are based on complex XML documents marshaling and un-marshaling (usually into native object structures on the service consumer and provider sides). SOAP is newer web service (WS) methodology and development with SOAP usually presumes "contract first" approach, where schema and communication xml documents are done first and any native code and logic development is done last.

XML RPC is relatively simpler way to develop web services than with SOAP, even though it is also based on the XML. With RPC or Remote Procedure Call, specific methods are invoked on the server from the client and results are usually function return variables. RPC WS are usually a quick and easy way to add web services to legacy applications (because logic to be executed is already developed), and a way to do contract last services.

The third methodology to develop web services is REST (Representational state transfer), which like SOAP involves HTTP requests to the server and processing XML document returned in response. However, unlike SOAP, there is no concrete standard and no definition on how data should be used with REST. REST and RPC are older methodologies compared with SOAP. In PHP, support for SOAP was added in version 5, but support for REST and RPC existed prior with third-party toolkits.

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:

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date