Skip to content

Instantly share code, notes, and snippets.

@fprochazka
Created November 26, 2010 17:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fprochazka/717009 to your computer and use it in GitHub Desktop.
Save fprochazka/717009 to your computer and use it in GitHub Desktop.
Cachování metod
<?php
class Foo extends Nette\Object
{
/**
* @Cache(expire=3600)
* @Tags(foo, fuuu)
* @return array
*/
public function foo()
{
echo("getting ");
return func_get_args();
}
/**
* @Cache(expire=3600)
* @Tags(bar, fuuu)
* @return array
*/
public function bar()
{
echo("getting ");
return func_get_args();
}
/**
* @return Foo
*/
public function __call($method, $args)
{
return Kdyby\Tools\ModelTools::tryCall($this, $method, $args);
}
/**
* @param array $conds
*/
public static function cleanCache($conds)
{
Kdyby\Tools\ModelTools::cleanCache($conds);
}
}
echo "<hr>";
$f = new Foo();
dump($f->foo(1), $f->foo(1));
echo "<hr>";
dump($f->c_foo(1), $f->c_foo(1));
dump($f->c_bar('neco'), $f->c_bar('neco'));
$f::cleanCache(array( 'tags' => array('bar') ));
dump($f->c_bar('neco'), $f->c_bar('neco'));
dump($f->c_foo('test', array('test1', 'test2')));
dump($f->c_foo('test', array('test1', 'test2')));
<?php
namespace Kdyby\Tools;
use Nette;
use Nette\Environment;
use Nette\ObjectMixin;
use Kdyby;
/**
* @author Filip Procházka <hosiplan@kdyby.org>
*/
class ModelTools extends Nette\Object
{
const CACHED_PREFIX = 'c_';
private static $methodCache;
/**
* Call to cached or undefined method.
* @param string method name
* @param array arguments
* @return mixed
* @throws \MemberAccessException
* @throws \InvalidStateException
*/
public static function tryCall($_this, $name, $args)
{
if (substr($name, 0, strlen(self::CACHED_PREFIX)) != self::CACHED_PREFIX) {
return ObjectMixin::call($_this, $name, $args);
}
$method = substr($name, strlen(self::CACHED_PREFIX));
if (!\method_exists($_this, $method)){
throw new \InvalidStateException('Invalid call for cached output of ' . get_class($_this) . '::' . $method . ', method not set.');
}
$reflection = new Nette\Reflection\MethodReflection($_this, $method);
$annotations = $reflection->getAnnotations();
if (isset($annotations['Cache'])) {
$key = get_class($_this) . '::' . $method . '?' . md5(serialize($args));
$cache = self::getMethodCache();
if (!isset($cache[$key])) {
$data = call_user_func_array(array($_this, $method), $args);
if (is_array($annotations['Cache'])) {
$depends = array();
$options = $annotations['Cache'];
$options = is_array($options) ? current($options) : array();
$options = $options instanceof \ArrayObject ? $options->getArrayCopy() : $options;
if (isset($annotations['Tags'])) {
$tags = is_array($tags = $annotations['Tags']) ? current($tags) : array();
$tags = $tags instanceof \ArrayObject ? $tags->getArrayCopy() : $tags;
$options[Nette\Caching\Cache::TAGS] = $tags;
}
foreach($options as $index => $value) {
$const = constant('Nette\Caching\Cache::' . strtoupper($index));
if ($const) {
$depends += array($const => $value);
} else {
throw new \InvalidArgumentException('Invalid cache options set for `' . $key . '`, dependency on `' . $index . '` not found.');
}
}
$cache->save($key, $data, $depends);
} else {
$cache[$key] = $data;
}
}
return $cache[$key];
}
return call_user_func_array(array($_this, $method), $args);
}
/**
* @return Nette\Caching\Cache
*/
private static function getMethodCache()
{
if (self::$methodCache === NULL) {
self::$methodCache = Environment::getCache('Kdyby.ClassMethods.Data');
}
return self::$methodCache;
}
/**
* @param array $conditions
* @return <type>
*/
public static function cleanCache($conditions)
{
self::getMethodCache()->clean($conditions);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment