Last active
April 10, 2019 15:03
-
-
Save finagin/8681a5e0fb43629f3b45457b457daf02 to your computer and use it in GitHub Desktop.
RunTime Cache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php declare(strict_types=1); | |
namespace Core; | |
class Cache | |
{ | |
private $object = null; | |
private $cache = null; | |
public function __construct($object) | |
{ | |
$this->object = $object; | |
$this->cache = new StaticCache(); | |
} | |
public function __call($method, $args) | |
{ | |
$closure = [$this->object, $method]; | |
if (!is_callable($closure)) { | |
$object = $this->object; | |
/** | |
* @var \Closure $closure Замыкание для вызова protected и private методов | |
*/ | |
$closure = \Closure::bind(function (...$args) use ($object, $method) { | |
return call_user_func_array([$object, $method], $args); | |
}, is_object($object) ? $object : null, is_object($object) ? get_class($object) : $object); | |
} | |
return $this->cache->cachedCall($closure, [$this->object, $method], $args); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php declare(strict_types=1); | |
namespace Core; | |
trait CacheTrait | |
{ | |
/** | |
* @var static | |
*/ | |
private $cache; | |
/** | |
* @var static | |
*/ | |
private static $internalCache; | |
/** | |
* @return static | |
*/ | |
public function cache() | |
{ | |
if ($this->cache === null) { | |
$this->cache = new Cache($this); | |
} | |
return $this->cache; | |
} | |
/** | |
* @return static | |
*/ | |
public static function cacheStatic() | |
{ | |
if (static::$internalCache === null) { | |
static::$internalCache = new Cache(__CLASS__); | |
} | |
return static::$internalCache; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Test | |
{ | |
use \Core\CacheTrait; | |
static function sum($a, $b) | |
{ | |
echo "\n".'calculate'; | |
return $a + $b; | |
} | |
} | |
echo "\n".Test::cacheStatic() | |
->sum(1, 1); | |
echo "\n".Test::cacheStatic() | |
->sum(1, 2); | |
echo "\n".Test::cacheStatic() | |
->sum(1, 2); | |
echo "\n".Test::cacheStatic() | |
->sum(1, 1); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php declare(strict_types=1); | |
namespace Core; | |
final class StaticCache implements JsonSerializable | |
{ | |
/** | |
* @var \Judy|array | |
*/ | |
private $cache; | |
/** | |
* StaticCacheService constructor. | |
*/ | |
public function __construct() | |
{ | |
$this->clear(); | |
} | |
private function clear() | |
{ | |
$this->cache = extension_loaded('judy') ? new \Judy(\Judy::STRING_TO_MIXED) : []; | |
} | |
public function delete($key) | |
{ | |
unset($this->cache[$key]); | |
} | |
public function set($key, $value) | |
{ | |
$this->cache[$key] = $value; | |
} | |
/** | |
* @param $key | |
* | |
* @return bool | |
*/ | |
public function exists($key) | |
{ | |
return extension_loaded('judy') | |
? $this->cache->offsetExists($key) | |
: array_key_exists($key, $this->cache); | |
} | |
public function get($key) | |
{ | |
if ($this->exists($key)) { | |
return $this->cache[$key]; | |
} | |
throw new \OutOfBoundsException('Key not exists'); | |
} | |
/** | |
* Метод, подсчитывающий хеш от параметров. | |
* | |
* @param array $params Параметры, от которых нужен хеш | |
* | |
* @return null|string Если null, то хеш создать не удалось | |
*/ | |
public function getKey(array $params) | |
{ | |
$keys = []; | |
try { | |
array_walk_recursive($params, function ($obj) use (&$keys) { | |
$keys[] = hash('tiger160,3', serialize($obj)); | |
}); | |
} catch (\Exception $e) { | |
return null; | |
} | |
return hash('tiger160,3', implode($keys)); | |
} | |
/** | |
* Вызывает $func только в том случае, если этого вызова ещё нет в кеше. | |
* | |
* @param callable $func Функция или метод для вызова | |
* @param mixed $ns Префикс кеша, чаще всего — имя метода/ф-и (используется, чтобы пометить Closure) | |
* @param mixed $params Параметры, которые будут переданы вызываемому | |
* | |
* @return mixed Результат вызова вызываемого или взятый из кеша | |
*/ | |
public function cachedCall(callable $func, $ns, array $params) | |
{ | |
$key = $this->getKey([$ns, $params]); | |
if ($key === null) { | |
return call_user_func_array($func, $params); | |
} | |
if ($this->exists($key)) { | |
return $this->get($key); | |
} else { | |
$result = call_user_func_array($func, $params); | |
$this->set($key, $result); | |
return $result; | |
} | |
} | |
public function jsonSerialize() | |
{ | |
if (extension_loaded('judy')) { | |
$cache = []; | |
foreach ($this->cache as $key => $value) { | |
$cache[$key] = $value; | |
} | |
return $cache; | |
} else { | |
return $this->cache; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment