Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caching function results in PHP

I'm making a simple tool to cache function results

It look like:

global $function_results;
$function_results = array();

function getMembers($conditions, $default = array('order' => 'name', array('abc', 'def'))){

    //****Help need from here******
    //make unique id from parameters value and function name
    //ex: $uid;
    //****to here******

    global $function_results;
    if(isset($function_results[$uid])) return $function_results[$uid];
    else{
        //do function logic...
    }
}

(the function and its parameters are just an example)

Any suggestions?

like image 807
StoneHeart Avatar asked Nov 30 '22 18:11

StoneHeart


2 Answers

Here is your missing code:

$numargs = func_num_args();
$arg_list = func_get_args();
$md5this = '';
for ($i = 0; $i < $numargs; $i++) {
    $md5this .= $i.':'.serialize($arg_list[$i]).';';
}
$uid = md5($md5this);

For your reference: http://php.net/manual/en/function.func-get-args.php

like image 78
Alec Smart Avatar answered Dec 05 '22 05:12

Alec Smart


Here is a generic memoization solution that is compatible with PHP 5.2.x.

The call_memoized function:

  1. Generates a unique cache key based on the function name and arguments.
  2. If the cache is empty, invokes the function and updates the cache with the result.
  3. Returns the cached value.

Instead of using call_memoized directly, use the provided memoize function, which returns a new version of the given function that will automatically cache results from the same combination of parameters.

See example below.

Enjoy!

global $MEMO_CACHE;
$MEMO_CACHE = array();

/** Returns the result of the function with the given arguments. 
 * Invokes the function only once, thereafter returns the result 
 * cached by a key based on the function name and arguments. */
function call_memoized($fun, $args=array()) {
    global $MEMO_CACHE;

    // generate a cache key based on the function name and arguments
    $uid = md5(
        implode("|", array_merge((array)$fun, array_map(
            "serialize",
            $args)
        ))
    );

    // if there result hasn't been cached, call the function 
    // and update the cache with the result.
    if(!array_key_exists($uid, $MEMO_CACHE)) {
        $MEMO_CACHE[$uid] = call_user_func_array($fun, $args);
    }

    return $MEMO_CACHE[$uid];
}

/** Returns a memoized version of the given function that will cache 
 * its results for each unique set of inputs. */
function memoize($fun) {
    return create_function(
        '', 
        "\$args = func_get_args(); return call_memoized('$fun', \$args);"
    );
}

Example:

/** Returns a random number with the given greeting. */
function random($greeting) {
    return "$greeting! " . rand();
};

print("Five random numbers:</br />");
for($i=0; $i<5; $i++) {
    print(random("Spin the wheel") . "<br />");
}
print "<br />";

print("After memoizing the random function, it's not so random:<br />");
$not_so_random = memoize("random");
for($i=0; $i<5; $i++) {
    print($not_so_random("Spin the wheel") . "<br />");
}
print "<br />";

print("The same memoized function is invoked with a different argument, and 
       thus creates a different cache key:<br />");
for($i=0; $i<5; $i++) {
    print($not_so_random("Twirl the tire") . "<br />");
}

/* OUTPUT

Five random numbers:
Spin the wheel! 26488
Spin the wheel! 20049
Spin the wheel! 14006
Spin the wheel! 28599
Spin the wheel! 804

After memoizing the random function, it's not so random:
Spin the wheel! 32397
Spin the wheel! 32397
Spin the wheel! 32397
Spin the wheel! 32397
Spin the wheel! 32397

The same memoized function is invoked with a different argument, and 
thus creates a different cache key:
Twirl the tire! 2114
Twirl the tire! 2114
Twirl the tire! 2114
Twirl the tire! 2114
Twirl the tire! 2114
*/
like image 25
Raine Revere Avatar answered Dec 05 '22 04:12

Raine Revere