2
\$\begingroup\$

i need to create a cache class to avoid making the same calculations more than needed. My idea was something really basic like

class transient_cache {
    static private $cache = array();
    static public function get_value( array $obj, $key ) {
        // $obj is an array( $object, $method )
        $classname = get_class( $obj[0] );
        $method = $obj[1];
        if( ! isset( self::$cache[$classname] ) ) {
            self::$cache[$classname] = array();
        }
        if( ! isset( self::$cache[$classname][$method] ) ) {
            self::$cache[$classname][$method] = array();
        }
        if( ! isset( self::$cache[$classname][$method][$key] ) ) {
            self::$cache[$classname][$method][$key] = call_user_func( $obj );
        }
        return  self::$cache[$classname][$method][$key];
    }   
}

Do you think this approach is correct or would you suggest something better?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I would say that there isn't a correct or incorrect way of achieving this. Everyones requirements differ.

You probably want to expand this out, there's a lot going on in the one static method you have in that class. Whilst I don't have anything against mediator patterns, I would probably combine a number of patterns to build a powerful caching class, as well as utilising magic methods (I know some people are averse to this).

I need to note the below is a lot more complicated and would benefit from some refactoring to be stored against the actual method rather than a key.

class Cache {

    /**
     * Cached objects
     * @static array
     */
    private static $cache = array();

    /**
     * Per instance class name
     * @var string
     */
    private $call;

    /**
     * Per instance method name
     * @static array
     */
    private $method;

    /**
     * Construct the class and build cache array if not set
     * @param string $method
     * @param string $class
     * @param string $key 
     */
    public function __construct($method, $class, $key)
    {
        if ( ! isset(static::$cache[$class] )
            static::$cache[$class] = array();

        if ( ! isset(static::$cache[$class][$method] )
            static::$cache[$class][$method] = array();

        // Set the class for this instance
        $this->call = $class;

        // Set the method for this instance
        $this->method= $method;

        // Set the key for the cache
        $this->key = $key;
    }

    /**
     * Get the cached value
     * @return mixed Cached value
     */
    public function get()
    {
        return $this->{$this->key};
    }

    /**
     * Get magic method to return the key
     * @param string $key
     */
    public function __get($key)
    {
        if (isset(static::$cache[$this->call][$this->method][$key]))
            return static::$cache[$this->call][$this->method][$key];

        return static::$cache[$this->call][$this->method][$key] = call_user_func(array($this->call, $this->method));
    }

    /**
     * Call static magic method, catches all statically called methods
     * and builds an instance of the cache class using a reflector
     * @param $method
     * @param $args 
     */
    public static function __callStatic($method, $args)
    {
        $method = str_replace(__CLASS__ . '::', '', $method);

        $ref = new ReflectionClass(__CLASS__);

        $inst = $ref->newInstanceArgs($args);

        return $inst->get();
    }

}

Usage

$result = Cache::{method}({class}, {key};

To retrieve say a user object from the User class with method get_user;

$user = Cache::get_user('User', 'user_object');

The main advantage to this is that the class can be extended easily using other design patterns such as a Facade that further simplifies the class API. It can also be added to easily with further methods within the class body itself rather than by a pure static call. The class can also be instantiated with the new keyword providing the ability to create separate cache instances that utilise the same static properties and methods.

I need to add this class is very much a prototype that I thought of when I saw your class above. I love cacheing stuff in general and providing standardised interfaces for it is always a great thing to do across all applications you write.

\$\endgroup\$
1
  • \$\begingroup\$ Ah shame :( Though WP functions on PHP > 5.3 just fine... You could however create a static make method that calls an anonymous private method using __call(). I believe that was implemented prior to 5.2.6 \$\endgroup\$ Commented May 4, 2013 at 15:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.