In all versions of Zend Server PHP, there is a feature that is called the data cache. This feature allows the developers to select certain data values and store them in active memory rather than retrieve them from disk. It is useful for frequently accessed elements that do not change often because the data cache can help improve application performance by several factors.

In the example below, there is a performance impact each time a web service is called. Many factors beyond your control can influence the performance of the service, such as load and distance. Because these factors cannot be controlled, the data cache can help minimize their impact.

The PHP script function library currency1.php is modified with two minor changes. At the beginning of the getCurrencyCode function, there is a test to see whether the data cache exists. If it does exist, the value is loaded into $option and then returned by the function and thus the web service is not called. If the value does not exist, the code to populate the cache comes in just after the web service is called and the $option array is built and loaded for 10 hours (10 * 3600 seconds per hour). These changes are shown in the updated script

// Service Functions...
function getCurrencyCode($style = 'array') {
// check to see if the cache exists...
$option = zend_shm_cache_fetch ( 'currencycodes' );
if ($option === null) {
$currencyCode = '';
$currencyCodeXML = file_get_contents ( $currencyCode );
$simpleXML = simplexml_load_string ( $currencyCodeXML );
foreach ( $simpleXML->CcyTbl->CcyNtry as $codes ) {
$Ccy = htmlentities ( ( string ) $codes->Ccy );
if ($Ccy) {
$CtryNum = htmlentities ( ( string ) $codes->CtryNm );
if ($style == 'option') {
$optionString = ' <option value="' . $Ccy . '"';
if ($Ccy == 'USD' && $CtryNum == "UNITED STATES") // default
$optionString .= 'selected';
$optionString .= ">$Ccy - $CtryNum</option>\n";
$option [] = $optionString;
} else
$option [] = array (
'Code' => $Ccy,
'Country' => $CtryNum
// Store the results in cache
zend_shm_cache_store ( 'currencycodes', $option, 10 * 3600 );
if ($option)
return $option;
return false;
function getCurrencyRate($fromRate, $toRate) {
// $serviceURL = '';
$serviceWSDL = '';
$currencySoapClient = new SoapClient ( $serviceWSDL );
$parms = array (
"FromCurrency" => $fromRate,
"ToCurrency" => $toRate
$responseObj = $currencySoapClient->ConversionRate ( $parms );
$conversionRate = $responseObj->ConversionRateResult;
return $conversionRate;
function loadRates() {
$conn = db2_connect ( '*LOCAL', 'PHPUSER', 'phpuser1' );
if (! $conn) {
echo 'Error connecting to DB2--error code ' . db2_stmt_error () . ' - ' .
db2_stmt_errormsg ();
exit ();
$sql = 'select * from zenddata.rates';
$stmt = db2_exec ( $conn, $sql );
if (! $stmt) {
echo 'Error accessing data--error code ' . db2_stmt_error () . ' - ' .
db2_stmt_errormsg ();
exit ();
print '<table border=2><tr><th>From Currency</th><th>To
while ( $row = db2_fetch_assoc ( $stmt ) ) {
$rate = getCurrencyRate ( $row ['FROMCURRENCY'], $row ['TOCURRENCY'] );
$today = date ( 'm/d/Y' );
var_dump ( $today );
$sql2 = "update zenddata.rates set CONVERSIONRATE = $rate, CONVERTDATE =
where FROMCURRENCY = '{$row['FROMCURRENCY']}' and
$stmt2 = db2_exec ( $conn, $sql2 );
echo 'Table Rates Updated in DB2</table>';

There are two performance benefits to this approach. The first benefit is that you can now reduce the number of times the web service is called. If the typical time to call the service is two seconds and you reduce that number by a significant amount because of heavy usage of the GUI, you have saved not only time but also reduced the load on DB2, leaving more DB2 resources for other processes on the system. The second benefit is that you loaded a field in the PHP form directly from memory to significantly improve response and thus improve the productivity of the user.

There are a few additional benefits to this approach:

  • This element is not just available for the user who loads the cache but for every user on the system. It is a little like a file in QTEMP that everyone on the system can share.
  • Each element on the window can be cached and each can have its own expiration interval. For example, say that you had an order entry window with 20 elements and 10 of those elements have drop-down lists that do not change often. Even at 100 milliseconds per list, you are saving an entire second of response time, and that can make the difference between a positive and not so positive user experience.
  • The elements can be forced to expire programmatically or they can be cleared by an administrator by clicking Clear Cache in the upper right corner of the Data Cache component in the Zend Server administration GUI
Cache component of the zend server admin gui

WSDL cache

In the getCurrencyRate function, there are two requests of the SOAPClient each time you run the request. One request comes when the WSDL is retrieved and another when the service is called. But how often does the WSDL change? As with EDI, many web services have SLAs and rules for operation. Currency rates might change wildly throughout the day, but the WSDL itself might not change for months or years. For this reason, the PHP community built another feature into the server that reduces the number of times that the WSDL is retrieved. This system-level setting can cache the WSDL for a significant amount of time and can have a dramatic impact on PHP performance because many unnecessary requests are thrown away in favor of highly improved response times. The cache can be cleared programmatically by using the ini_set function to turn it off, if needed. For example:

ini_set("soap.wsdl_cache_enabled", "0");

This setting is controlled through the Zend Server administration GUI interface

Wsdl cache settings within the zend server administration gui

PHP provides many benefits in some small packages. These scripts are calling multiple services with a database update and barely 100 lines of code were written for a full application example. This provides a concise basis for developing PHP applications by using the procedural approach to PHP. This application might have been written using an object-oriented approach and possibly should have been. However, as many IBM i developers have a solid background in procedural such as RPG and COBOL, it is good to know that the developer can grow into the object-oriented model gradually. It is called modernization on your terms.

REST Web Services: XML Service

XML Service support is built on XML. It is a good fit for REST-based web services. A more detailed explanation is provided in “XMLSERVICE HTML/XML interface” on page 140. The XML Service support can receive REST-based web services requests that can then process your back-end ILE programs or access your DB2 for i data.

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}