Last active
May 7, 2023 16:18
-
-
Save nigrosimone/401221c9439ae9d0c02bb5889562e3fd to your computer and use it in GitHub Desktop.
Simple php cache using php generated files and opcache
This file contains hidden or 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 | |
/** | |
* Simple php cache using php generated files and opcache | |
* Usage: | |
* $diskCache = new DiskCache(); | |
* $diskCache->write('foo', 'bar'); | |
* echo $diskCache->read('foo'); // print bar | |
*/ | |
class DiskCache { | |
const CACHE_FRTNAME = 'cache_%s.php'; | |
const DEFAULT_TTL = 3600; | |
/** | |
* @var callable | |
*/ | |
private static $emptyErrorHandler; | |
/** | |
* @var string | |
*/ | |
protected $cacheDir; | |
/** | |
* @var int | |
*/ | |
protected $defaultTtl; | |
/** | |
* Constructor | |
* @param string $cacheDir where to store cache files | |
* @param integer $ttl time to live | |
*/ | |
public function __construct($cacheDir = null, $ttl = self::DEFAULT_TTL) { | |
if( empty($cacheDir) ){ | |
$cacheDir = sys_get_temp_dir(); | |
} | |
$cacheDir = realpath(rtrim($cacheDir, DIRECTORY_SEPARATOR)); | |
if( !is_dir($cacheDir) ) { | |
throw new InvalidArgumentException('Provided cache dir is not a directory'); | |
} | |
if( !(is_readable($cacheDir) && is_writable($cacheDir)) ) { | |
throw new InvalidArgumentException('Provided cache dir is not writable and readable'); | |
} | |
$this->cacheDir = $cacheDir; | |
$this->defaultTtl = (int) $ttl; | |
self::$emptyErrorHandler = function(){}; | |
} | |
/** | |
* Read cache | |
* @param string $key the key | |
* @return mixed|false cached data | |
*/ | |
public function read($key) { | |
$fileName = $this->getCacheFilename($key); | |
set_error_handler(self::$emptyErrorHandler); | |
$cached = include $fileName; | |
restore_error_handler(); | |
if( $cached && isset($cached['timestamp'], $cached['ttl'], $cached['data']) ) { | |
if((time() - $cached['timestamp']) < $cached['ttl']){ | |
return $cached['data']; | |
} | |
} | |
if( $cached ) { | |
$this->delete($key); | |
} | |
return false; | |
} | |
/** | |
* Write cache | |
* @param string $key the key | |
* @param mixed $data the data | |
* @param integer $ttl time to live | |
* @return boolean | |
*/ | |
public function write($key, $data, $ttl = null) { | |
$ttl = $ttl > 0 ? (int) $ttl : $this->defaultTtl; | |
$fileName = $this->getCacheFilename($key); | |
$code = null; | |
$result = false; | |
$value = array( | |
'timestamp' => time(), | |
'ttl' => $ttl, | |
'data' => $data | |
); | |
if (is_object($data) && method_exists($data, '__set_state')) { | |
$code = sprintf('<?php return %s;', var_export($value, true)); | |
} else { | |
$code = sprintf('<?php return unserialize(%s);', var_export(serialize($value), true)); | |
} | |
if( $code ){ | |
$result = (boolean) @file_put_contents($fileName, $code, LOCK_EX); | |
if( $result ){ | |
// force opcache to invalidate the file cache | |
if( function_exists('opcache_invalidate') ){ | |
opcache_invalidate($fileName, true); | |
} | |
} | |
} | |
return $result; | |
} | |
/** | |
* Delete cache | |
* @param string $key | |
* @return boolean | |
*/ | |
public function delete($key) { | |
$fileName = $this->getCacheFilename($key); | |
$result = @unlink($fileName); | |
if( $result ){ | |
if( function_exists('opcache_invalidate') ){ | |
opcache_invalidate($fileName, true); | |
} | |
} | |
return $result; | |
} | |
/** | |
* Flush the cache | |
* @return boolean | |
*/ | |
public function flush() { | |
$result = false; | |
$files = glob($this->cacheDir . DIRECTORY_SEPARATOR . sprintf(self::CACHE_FRTNAME, '*')); | |
if( $files ){ | |
$result = true; | |
foreach ($files as $file){ | |
if( !@unlink($file) ){ | |
$result = false; | |
} | |
} | |
if( function_exists('opcache_reset') ){ | |
opcache_reset(); | |
} | |
} | |
return $result; | |
} | |
/** | |
* Return the cache filename | |
* @param string $key | |
* @throws InvalidArgumentException | |
* @return string | |
*/ | |
public function getCacheFilename($key){ | |
if( $key == '' ) { | |
throw new InvalidArgumentException('key is empty'); | |
} | |
return $this->cacheDir . DIRECTORY_SEPARATOR . sprintf(self::CACHE_FRTNAME, md5($key)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
add in after line 185 }