Skip to main content

PHP文件缓存示例

简介

在php程序中,缓存可以存储到Redis或者Memcache中,如果没有这些条件,或者服务器内存非常有限怎么办?可以将缓存内容写入到硬盘,写入到文件系统中,也是一个思路。下面是示例代码:

代码

<?php
namespace common\library;

use Psr\SimpleCache\CacheInterface;

class FileCache implements CacheInterface
{
protected $filename;

protected $handle;

protected $keys = [];

protected $spaceSize;

protected $startTimestamp;

public function __construct($filename, $spaceSize = 1024)
{
$this->startTimestamp = time();
$this->filename = $filename;
$this->spaceSize = $spaceSize;

!is_dir(dirname($this->filename)) && mkdir(dirname($this->filename), 0755, true);
$this->handle = fopen($this->filename, 'w+');
}

public function __destruct()
{
fclose($this->handle);
unlink($this->filename);
}

public function get($key, $default = null)
{
$key = substr(md5($key), 0, 20);

if (!isset($this->keys[$key])) {
return $default;
}

$item = $this->parseId($this->keys[$key]);

if ($item[1] != 0 && (time() - $this->startTimestamp) > $item[1]) {
return $default;
}

fseek($this->handle, $item[0] * $this->spaceSize);
$value = fread($this->handle, $this->spaceSize);
return unserialize(rtrim($value));
}

public function set($key, $value, $ttl = null)
{
$key = substr(md5($key), 0, 20);
$value = serialize($value);

if (strlen($value) > $this->spaceSize - 1) {
throw new \RuntimeException('not enough space');
}

if (!is_null($ttl) && $ttl > 1048575) {
throw new \RuntimeException('Ttl out of range');
}

$value = str_pad($value, $this->spaceSize - 1, " ") . "\n";

if (isset($this->keys[$key])) {
$item = $this->parseId($this->keys[$key]);
$start = $item[0] * $this->spaceSize;
$index = $item[0];

} else {
$count = count($this->keys);
$start = $count * $this->spaceSize;
$index = $count;
}

fseek($this->handle, $start, SEEK_SET);
fwrite($this->handle, $value);
fflush($this->handle);

$this->keys[$key] = $this->getId($ttl ? (time() - $this->startTimestamp) + $ttl : 0, $index);
return true;
}

public function delete($key)
{
$key = substr(md5($key), 0, 20);
unset($this->keys[$key]);
return true;
}

public function clear()
{
ftruncate($this->handle, 0);
fflush($this->handle);
return true;
}

public function getMultiple($keys, $default = null)
{
$values = [];

foreach ($keys as $key) {
$values[$key] = $this->get($key, $default);
}

return $values;
}

public function setMultiple($values, $ttl = null)
{
foreach ($values as $key => $value) {
$this->set($key, $value, $ttl);
}

return true;
}

public function deleteMultiple($keys)
{
foreach ($keys as $key) {
$this->delete($key);
}

return true;
}

public function has($key)
{
return isset($this->keys[md5($key)]);
}

protected function getId($time, $count)
{
return $time << 20 | $count;
}

protected function parseId($id)
{
$id = str_pad(decbin($id), 40, '0', STR_PAD_LEFT);
return [bindec(substr($id, 21)), bindec(substr($id, 0, 20))];
}
}