#native_company# #native_desc#

Emulating call_user_func_array() for PHP

By Ryan M Harris
on January 10, 2002

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!


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
    /* 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);";
    /* Get the return value.
    $tmpReturnValue = $GLOBALS["$tmpVariableName2"];
    /* Save memory
    unset($GLOBALS["$tmpVariableName"], $GLOBALS["$tmpVariableName2"]);
    return $tmpReturnValue;