#native_company# #native_desc#
#native_cta#

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!

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;
}