Tuesday, July 28, 2009

Fixing zend_mm_heap corrupted on Centos 5.x

When you do a google search on 'zend_mm_heap corrupted' you will find it's been keeping sysadmins busy for some time. I had it on one of my new production boxes (Centos 5.2) after updating to php 5.2.9, and later after updating apache to 2.2.3. It is not a PHP problem!, it is related to the php extensions in use.

Extension: Memcached
If you use memcached in php as a session handler; first check
* Is memcached started
* Is the serverconfig (in /etc/php.ini or /etc/php.d/memcache.ini) correct?

Not being able to connect to the memcached server will result in zend_mm_heap corrupted


Other extensions
To troubleshoot the problem
* Move all extension configs from the /etc/php.d directory to a safe place
* Add them one by one, restart httpd and reload the page after each add
* This way (isolation) you will find the extension that is causing the problem

Friday, June 5, 2009

Making Webservices with NuSoap

Php can make an excellent webservice. NuSoap is an excellent library to provide standards compilant web services to your audience.

It took me some time to find out recent versions of PHP (5.2+) do not populate
the $HTTP_RAW_POST_DATA properly.So in this case the server part will use
file_get_contents('php://input') to get its data.

Here is a working example.
Server Part:

date_default_timezone_set('Europe/Amsterdam');
require_once('nusoap/lib/nusoap.php');
$server = new soap_server;

function hello($name, $role)
{
return "Hi ".$name." you are a ".$role;
}

$server->register('hello', // method name
array('name' => 'xsd:string', 'role' => 'xsd:string'),
array('return' => 'xsd:string'),
'uri:helloapp',
'uri:helloapp/hello',
'rpc',
'encoded');

$server->service(file_get_contents('php://input'));


Client Part:

date_default_timezone_set('Europe/Amsterdam');
require_once('nusoap/lib/nusoap.php');

$objClient = new soapclient('http://work/soap/server.php');
echo $objClient->call('hello', array('name' => 'John','role' => 'programmer'));

Find out absolute path of PHP script, cross platform 100% reliable

Ever had the problem wanting to include a php file 1 from within php file 2 regardless where php file 2 is included from?

$strPath = substr(__FILE__,0,strrpos(__FILE__,DIRECTORY_SEPARATOR)).DIRECTORY_SEPARATOR;

Wednesday, June 3, 2009

Using Arrays in PHP constants

Sooner or later you wil run into the following construction:

define('MY_ARRAY', array(1 => 'foo', 2 => 'bar', 3 => 'baz');

PHP will not allow this construction.

Warning: Constants may only evaluate to scalar values

This can be anoying. The solution: a static constants class

How to use this solution?
1- Include the file staticconstants.php (see below)
2- Define a constant (no need to instanciate since the class is static)

Constants::AddStructure('MY_ARRAY','id','value');'
Constants::Define(1,'foo');
Constants::Define(2,'bar');
Constants::Define(3,'baz');

3- Acces the constant array

$arrMyArray = Constants::Get('MY_ARRAY');
print_r($arrMyArray);

this will return: Array ( [1] => foo [2] => bar [3] => baz )

4- Or access a single member

$strMyString = Constants::Get('MY_ARRAY',1);
print_r($strMyString);

this will return: foo

It is also possible to store any other kind of php variable like multi dimensional array's and objects etc.Example with more fields;

Constants::AddStructure('MY_CARS',array('id','brand','color'));
Constants::Define(1,'toyota','red');
Constants::Define(2,'buick','green');
Constants::Define(3,'honda','yellow');
print_r(Constants::Get('MY_CARS'));

this will return:
Array
(
[1] => Array
(
[brand] => toyota
[color] => red
)
[2] => Array
(
[brand] => buick
[color] => green
)
[3] => Array
(
[brand] => honda
[color] => yellow
)
)

This class will never replace a relational database system. But for small code-related data structures this solution is excellent. Alternatively one could use global variables, but this has unique naming issues and requires scoping commands within functions and class methods (global etc.).

The static class construction provides encapsulation and is accessible from anywhere with just a single command (Constants::Get).

Compacted source code of static constants Class

/** Constants Class,
Copyright Pim Koeman 2009 (c)
License: GPL3
**/
class Constants
{
static $arrContent = array();
static $arrStructure = array();
static $strCurrentStructure = '';

// Set the Section (Array Name) and the PHP constant prefix for this section
static function AddStructure($strName, $arrStructure)
{
// remove the id fieldname
array_shift($arrStructure);
self::$strCurrentStructure = $strName;
self::$arrStructure[$strName] = $arrStructure;
}

/**
* Define a member within the currently selected structure
* Define($strConstantName, $strConstantValue, $varContent1, $varContent2, $varContentN ....)
* First parameter is array index, more parameters are array content
**/
static function Define()
{
$arrArgs = func_get_args();
$strId = array_shift($arrArgs);

// one arg ? do not store array but only own value
if (count($arrArgs) == 1) $arrArgs = $arrArgs[0];

foreach($arrArgs as $strKey => $strValue)
{
self::$arrContent[self::$strCurrentStructure][$strId][self::$arrStructure[self::$strCurrentStructure][$strKey]] = $strValue;
}
}

/**
* Read structure
* Return value depends on the number of parameters, see below
**/
static function Get($strStructure = '', $strIndex = '')
{
if ($strStructure == '')
{
// No parameters : Get all
return self::$arrContent;
}
elseif ($strIndex == '')
{
// Structurename : Get Full Structure
return self::$arrContent[$strStructure];
}
else
{
// Both : Get Single member
return self::$arrContent[$strStructure][$strIndex];
}
}

static function GetObjects($strStructure)
{
$arrOut = array();

foreach(self::$arrContent[$strStructure] as $varKey => $arrValue)
{
$arrOut[$varKey] = new stdClass;
foreach($arrValue as $strMemberKey => $varMemberValue)
{
$arrOut[$varKey]->$strMemberKey = $varMemberValue;
}
}

return $arrOut;
}


/**
* Search the structure by value
* Returns member id (first field in structure definition)
**/
static function Search($strStructure, $strField, $strValue)
{
$varOut = FALSE;

foreach(self::$arrContent[$strStructure] as $varKey => $varValue)
{
if ($varValue[$strField] == $strValue) $varOut = $varKey;
}

return $varOut;
}
}