PHP SOAP Server with Memcached queries

The new thing I wanted to try out this week was to implement a SOAP server using PHP to query against a MySQL database. I also add a memcached server to cache the query results for each SOAP call so that all queries are not hitting the database.

To install a memcached server on the Ubuntu Natty setup was simple. The following command will install memcache as well as the php libraries for memcache and soap:


apt-get install memcached php5-memcache php-soap

Then we need to setup the server.php. In my case what I wanted to do was given a query for an employee id, I want to return their full name. First I check the memcache server and if it is there, then I return it. If not, I do a query against the database, store the name for the key employee id in the memcache server and return the name as the result. The following defines the SOAP Server:


?php
require_once 'SOAP/Value.php';

/* Create a class for your SOAP functions. */
class SOAP_Custom_Server{
var $__dispatch_map = array();

function SOAP_Custom_Server() {
$this->__dispatch_map['getFullName'] =
array('in' => array('emplid' => 'string'),
'out' => array('outputString' => 'string'));
}

/* This private function is called on by SOAP_Server to determine any
* special dispatch information that might be necessary. This, for
* example, can be used to set up a dispatch map for functions that return
* multiple OUT parameters. */
function __dispatch($methodname)
{
if (isset($this->__dispatch_map[$methodname])) {
return $this->__dispatch_map[$methodname];
}
return null;
}

/*Custom function to get person's details*/

function getFullName($emplid)
{
if ($emplid.length < 7) {
return new SOAP_Fault('Invalid Employee ID', 'Client');
}

$memcache = new Memcached();
$memcache->addServer('localhost',11211) or die ('Could not connect');

$value = $memcache->get($emplid);
/*Check if the value to this emplid is in the memcache. If so return
the value from the memcached server. Otherwise query the database
and add the entry into the memcached server */
#I had this as the original if statement but apache was warning against
#the RES_SUCCESS var saying its not there so now adding value 0 to test.
#if($memcache->getResultCode() == $memcache->RES_SUCCESS){
if($memcache->getResultCode() == 0){
#echo "Found Data from Memcached server

";
return $value;
}
else{
#echo "No Data in Memcached server, querying mysql

";
/*Emplid not in the memcached server so query mysql*/

$query = "select full_name from employee_data where emplid='". $emplid . "'";
if (mysql_connect("localhost", "read_user", "password")){}
else { $error = "Database connection error";
return $error; }
if (mysql_select_db("people")){}
else { $error = "Database not found";
return $error; }
if ($result = mysql_query($query)){}
else { $error = "mysql_error()";
return $error; }
$name= mysql_result($result, 0, 0);

$memcache->add($emplid,$name);
return $name;
}
}

}

Now we need to setup a server that listens using this SOAP server definition. That way a client can query this server by calling the function getFullName with an employee id. The server is setup using the following:


/* First, include the SOAP_Server class. */
require_once 'SOAP/Server.php';
$server = new SOAP_Server;

/* Tell server to translate to classes we provide if possible. */
$server->_auto_translation = true;

require_once dirname(__FILE__) . '/server_definition.php';
$soapclass = new SOAP_Custom_Server();
$server->addObjectMap($soapclass, 'urn:SOAP_Custom_Server');

if (isset($_SERVER['REQUEST_METHOD']) &&
$_SERVER['REQUEST_METHOD'] == 'POST') {
$server->service($HTTP_RAW_POST_DATA);
} else {
require_once 'SOAP/Disco.php';
$disco = new SOAP_DISCO_Server($server, 'ServerExample');
header('Content-type: text/xml');
if (isset($_SERVER['QUERY_STRING']) &&
strpos($_SERVER['QUERY_STRING'], 'wsdl') !== false) {
echo $disco->getWSDL();
} else {
echo $disco->getDISCO();
}
}

Note you need to have the server definition in a file called: server_definition.php and have it in the same directory as this file and call it server.php.

My plan is to use a Java client to call this PHP SOAP server to retrieve the data. However for test purposes I setup a simple PHP client as follows:

/** SOAP_Client */
require 'SOAP/Client.php';

/* This client runs against the example server in SOAP/example/server.php. It
* does not use WSDL to run these requests, but that can be changed easily by
* simply adding '?wsdl' to the end of the url. */
$soapclient = new SOAP_Client('http://localhost:8080/server.php');

/* Set a few options. */
$options = array();

/* This namespace is the same as declared in server.php. */
$options['namespace'] = 'urn:SOAP_Custom_Server';

/* Trace the communication for debugging purposes, so we can later inspect the
* data with getWire(). */
$options['trace'] = true;

/* Uncomment the following lines if you want to use Basic HTTP
* Authentication. */
// $options['user'] = 'username';
// $options['pass'] = 'password';

header('Content-Type: text/plain');

/* Calling echoStringSimple. */
$ret = $soapclient->call('getFullName',
array('emplid' => '111111111'),
$options);
echo $soapclient->getWire();
echo "
";
if (PEAR::isError($ret)) {
echo 'Error: ' . $ret->getMessage();
} else {
echo 'Person: ' . $ret;
}

So to summarize:
– In /var/www/ create a file called server_definition.php and copy the definitions from above with the appropriate database/table/sql query.
– create the server listener script called server.php and copy the contents from above into it.
– create a client file and copy the client code and run the client code. You should see the XML Outgoing and Incoming as well as the output.

I will update soon with how I setup the SOAP Java client. I am contemplating setting it up in a spring framework environment. Will update soon.

Thusjanthan Kubendranthan M.Sc.

Leave a Reply