The Problem
As a developer for the Comprehensive Web Programming API project (url: http://sourceforge.net/projects/cwpapi/) for ACD Incorporated (url: http://www.acdinc.net/), I needed to develop a way of performing a sprintf() on an error message string. The only problem is that the values to substitute in had to be passed as an array, and I did not want to call sprintf() recursively because of the string formatting vulnerabilities this would introduce.
I read about the call_user_func_array() function which allows you to call a function and split out an array into individual arguments to that function. For example: the call call_user_func_array("myfunction", array("param1", "param2");
translates to myfunction("param1", "param2");
All was fine and dandy until I noticed the line that said that the function was introduced into CVS after 4.0.4pl1. AHH! Major problem, I need to support ALL php4 versions!
The Solution
So I did what any self respecting programmer would do, I rolled my own.
NOTE: This implementation is smart enough to call call_user_func_array() if it exists.
The Code!
Enjoy!
function call_func_array($Function, $Replace)
{
if (function_exists("call_user_func_array"))
{
return call_user_func_array($Function, $Replace);
}
$Function = ereg_replace("[^0-9A-Za-z_]", "", $Function);
if (!is_array($Replace))
{
$Replace[] = $Replace;
}
/* Reset the variable
*/
reset($Replace);
/* Get a new variable name
*/
$tmpVariableName = "_test"; //. md5(microtime);
$tmpVariableName2 = $tmpVariableName . "_return";
/* Add the "replace" array into the temporary variable
*/
$GLOBALS["$tmpVariableName"] = &$Replace;
$tmpParams = "";
/* Go through the array and do a replace on each
*/
while (list($tmpKey,$tmpVal) = each($Replace))
{
/* Add it on to our list of parameters, we insure index is a integer just to be sure.
*/
$tmpParams .= ', $GLOBALS["' . $tmpVariableName . '"][' . (integer) $tmpKey . ']';
}
/* Trim off our extra comma at the beginning
*/
$tmpParams = substr($tmpParams, 1);
/* Do the call
*/
$tmpCall = "$GLOBALS["" . $tmpVariableName . "_return"] = $Function($tmpParams);";
eval($tmpCall);
/* Get the return value.
*/
$tmpReturnValue = $GLOBALS["$tmpVariableName2"];
/* Save memory
*/
unset($GLOBALS["$tmpVariableName"], $GLOBALS["$tmpVariableName2"]);
return $tmpReturnValue;
}