Passed
Push — master ( c1e721...8ec156 )
by 世昌
02:05
created

FileCache   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 128
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 47
dl 0
loc 128
rs 10
c 0
b 0
f 0
wmc 18

10 Methods

Rating   Name   Duplication   Size   Complexity  
A set() 0 13 3
A get() 0 22 4
A __construct() 0 6 1
A disable() 0 3 1
A has() 0 3 1
A enable() 0 3 1
A gc() 0 8 3
A getPath() 0 10 2
A clear() 0 3 1
A delete() 0 3 1
1
<?php
2
namespace suda\application\cache;
3
4
use suda\application\filesystem\FileSystem;
5
use suda\component\cacheable\CacheInterface;
6
7
/**
8
 * 文件缓存
9
 *
10
 * 由于访问数据库的效率远远低于访问文件的效率,所以我添加了一个文件缓存类,
11
 * 你可以把常用的数据和更改很少的数据查询数据库以后缓存到文件里面,用来加快页面加载速度。
12
 */
13
class FileCache implements CacheInterface
14
{
15
    protected $path;
16
    protected $value;
17
    protected $defaultLiveTime = 3600;
18
19
    public function __construct(string $path, int $live = 3600)
20
    {
21
        $this->path = $path;
22
        $this->defaultLiveTime = $live;
23
        FileSystem::makes($path);
24
        \register_shutdown_function([$this, 'gc']);
25
    }
26
27
28
    /**
29
     * 设置
30
     * @param string $name 名
31
     * @param mixed $value 值
32
     * @param int $expire 过期时间
33
     * @return bool
34
     */
35
    public function set(string $name, $value, int $expire=null):bool
36
    {
37
        if ($this->disable()) {
38
            return false;
39
        }
40
        $path=$this->getPath($name);
41
        $this->value[$name]=$value;
42
        FileSystem::makes(dirname($path));
43
        $value=serialize($value);
44
        if (is_null($expire)) {
45
            $expire=time() + $this->defaultLiveTime;
46
        }
47
        return file_put_contents($path, $expire.'|'.$value)!==false;
48
    }
49
50
    /**
51
     * 获取值
52
     * @param string $name 名
53
     * @return mixed|null
54
     */
55
    public function get(string $name, $defalut=null)
56
    {
57
        // 有值就获取值
58
        if (array_key_exists($name, $this->value)) {
59
            $value=$this->value[$name];
60
            return $value;
61
        }
62
        // 没值就在cache文件中查找
63
        $path=$this->getPath($name);
64
        if (FileSystem::exist($path)) {
65
            $value=FileSystem::get($path);
66
            list($time, $value)=explode('|', $value, 2);
67
            if (time()<intval($time)) {
68
                // 未过期则返回
69
                return unserialize($value);
70
            } else {
71
                // 过期则删除
72
                $this->delete($path);
73
            }
74
        }
75
        // 返回默认值
76
        return $defalut;
77
    }
78
79
    /**
80
     * 删除值
81
     * @param string $name 名
82
     * @return bool
83
     */
84
    public function delete(string $name) :bool
85
    {
86
        return FileSystem::delete($this->getPath($name));
87
    }
88
    
89
    
90
    /**
91
     * 检测是否存在
92
     *
93
     * @param string $name
94
     * @return bool
95
     */
96
    public function has(string $name):bool
97
    {
98
        return $this->get($name)!==null;
99
    }
100
101
    /**
102
     * 垃圾回收
103
     */
104
    public function gc()
105
    {
106
        $files=FileSystem::readFiles($this->path, true);
107
        foreach ($files as $file) {
108
            $value=FileSystem::get($file);
109
            list($time, $value)=explode('|', $value, 2);
110
            if (time()>intval($time)) {
111
                FileSystem::delete($file);
112
            }
113
        }
114
    }
115
116
    public function clear()
117
    {
118
        FileSystem::delete($this->path);
119
    }
120
121
    public function enable():bool
122
    {
123
        return is_writable($this->path);
124
    }
125
126
    public function disable():bool
127
    {
128
        return !$this->enable();
129
    }
130
131
    private function getPath(string $name)
132
    {
133
        if (strpos($name, '.')) {
134
            list($main, $sub)=explode('.', $name, 2);
135
        } else {
136
            $main=$name;
137
            $sub=$name;
138
        }
139
        $fname= $this->path.'/'.$main.'/'.substr(md5($sub), 0, 4).'.cache';
140
        return $fname;
141
    }
142
}
143