<?php
namespace Lm\Service\Cache;
class CacheService
{
use LmCachePluggableTrait;
const CACHE_INSTANCE = 1;
const CACHE_STATIC = 2;
private $_instanceCache = [];
/**
* @var CacheObject[]
*/
private static $_staticCache = [];
/**
* 連想配列のハッシュ値を返す
*
* @param mixed $data
* @return false|string
*/
public static function hash($data)
{
// 連想配列をハッシュ化
$result = hash('sha256', base64_encode(serialize($data)));
//
return $result;
}
/**
* @param $cache_mode
* @param $cache
* @return bool
* @throws \Exception
*/
public function getCache($cache_mode, &$cache)
{
if ($cache_mode == self::CACHE_INSTANCE) {
$cache = $this->_instanceCache;
} else if ($cache_mode == self::CACHE_STATIC) {
$cache = self::$_staticCache;
} else {
throw new \Exception('The parameter “$cache_mode” is invalid.');
}
//
return true;
}
public function getKeys($cache_mode = self::CACHE_STATIC)
{
if ($cache_mode == self::CACHE_INSTANCE) {
$result = array_keys($this->_instanceCache);
} else if ($cache_mode == self::CACHE_STATIC) {
$result = array_keys(self::$_staticCache);
} else {
throw new \Exception('The parameter “$cache_mode” is invalid.');
}
return $result;
}
public function test($key, $cache_mode = self::CACHE_STATIC)
{
// if ($this->getCache($cache_mode, $cache)) {
// //
// var_dump($cache);
// //
// return isset($cache[$key]);
// }
// //
// return false;
if ($cache_mode == self::CACHE_INSTANCE) {
//
$result = isset($this->_instanceCache[$key]);
} else if ($cache_mode == self::CACHE_STATIC) {
//
$result = isset(self::$_staticCache[$key]);
} else {
//
throw new \Exception('The parameter “$cache_mode” is invalid.');
}
//
return $result;
}
public function get($key, $cache_mode = self::CACHE_STATIC)
{
// if ($this->getCache($cache_mode, $cache)) {
// //
// return $cache[$key];
// }
if ($cache_mode == self::CACHE_INSTANCE) {
//
$value = $this->_instanceCache[$key];
} else if ($cache_mode == self::CACHE_STATIC) {
//
$value = self::$_staticCache[$key];
} else {
//
throw new \Exception('The parameter “$cache_mode” is invalid.');
}
//
return $value;
}
public function set($key, $value, $cache_mode = self::CACHE_STATIC)
{
// if ($this->getCache($cache_mode, $cache)) {
// //
// $cache[$key] = $value;
// //
// return true;
// }
// //
// return false;
if ($cache_mode == self::CACHE_INSTANCE) {
//
$this->_instanceCache[$key] = $value;
} else if ($cache_mode == self::CACHE_STATIC) {
//
self::$_staticCache[$key] = $value;
} else {
//
throw new \Exception('The parameter “$cache_mode” is invalid.');
}
//
return true;
}
public function clear($cache_mode = null)
{
if ($cache_mode === null) {
foreach ([self::CACHE_INSTANCE, self::CACHE_STATIC] as $cache_mode) {
$this->clear($cache_mode);
}
} else if ($this->getCache($cache_mode, $cache)) {
//
$cache = [];
}
}
/**
* @param string|mixed|null $label
* @return string
*/
public static function getCacheKey($label = null, $level = 2)
{
//
$caller = debug_backtrace()[$level];
//
$cacheKey = "{$caller['class']}::{$caller['function']}()";
//
if (!empty($label)) {
if (is_array($label)) {
// 配列の場合はハッシュ値を取得
$label = CacheService::hash($label);
}
$cacheKey .= "-{$label}";
}
//
return $cacheKey;
}
/**
* @param callable $callback
* @return array
* @throws \ReflectionException
*/
public static function getCallbackVariables(callable $callback)
{
//
$reflection = new \ReflectionFunction($callback);
$label = $reflection->getStaticVariables();
//
return $label;
}
public static function getCached(callable $callback, $label = null)
{
//
$staticVariables = self::getCallbackVariables($callback);
// $labelの省略時、コールバック関数にuse()ステートメントで渡されたパラメータを採用する
if ($label === null) {
$label = $staticVariables;
}
//
$cacheKey = self::getCacheKey($label);
// var_dump($cacheKey);
if (static::isCacheEnabled()) {
//
if (isset(self::$_staticCache[$cacheKey])) {
//
// echo 'キャッシュあり';
//
$cache = self::$_staticCache[$cacheKey];
//
$result = $cache->getResult();
//
foreach ($staticVariables as $key => &$value) {
$value = $cache->getStaticVariable($key);
}
} else {
//
// echo 'キャッシュなし';
//
$result = $callback();
//
self::$_staticCache[$cacheKey] = new CacheObject($result, $staticVariables);
}
} else {
//
$result = $callback();
}
//
return $result;
}
}