-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimple-cache.php
More file actions
171 lines (123 loc) · 4.87 KB
/
simple-cache.php
File metadata and controls
171 lines (123 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php
/**
*
*
* Simple Cache
*
*/
class SimpleCache{
protected $dataFunction;
protected $expiryInterval;
protected $filePath;
protected $cache;
/**
*
* @param string $liveDataFunction The user-defined function
* that returns the data to be cached (must return a serializable string).
* @param int $cacheExpiry [optional] the timer (in seconds) during which live
* data will be served from the cache file instead. After this timer ends, and the cache expires,
* the next request will refresh the cache with live data and reset the timer. The default is 30 seconds.
* @param string $cacheFile [optional] the file where the cache data will be stored.
* The default is 'cache' in the script directory.
*/
public function __construct($liveDataFunction, $cacheExpiry = 30, $cacheFile = 'cache') {
//load properties
$this->dataFunction = $liveDataFunction;
$this->expiryInterval = $cacheExpiry;
$this->filePath = __DIR__.'/'.$cacheFile;
$this->_loadCache();
}
/**
* Gets the data from the cache file, unless it has
* expired (see the constructor's $cacheExpiry parameter).
* If the cache expired, this fetches live data and updates the cache (see the constructor's $liveDataFunction parameter).
* @return string The data (as returned by the live data function).
*/
public function getData(){
if($this->_cacheHasExpired()){
$this->cache = $this->_cache();
}
return $this->cache->data;
}
/**
*
* @return boolean whether the cache is still valid or not
*/
private function _cacheHasExpired(){
$expiryTime = time() - $this->expiryInterval;//the time when the cache expires
if($this->cache->time < $expiryTime){
return true;
}
else return false;
}
/**
* Caches the live data
* @return \stdClass An object with the cache data and timestamp.
*/
private function _cache(){
//get the live data
$data = $this->_getLiveData();
//store the live data
$cacheObject = $this->_storeData($data);
//return the fresh cache
return $cacheObject;
}
/**
* Stores the data into a file
* @param string $data The (serializable) data string to store.
* @return \stdClass An object with the stored data and timestamp.
*/
private function _storeData($data) {
//create a new cache object
$cacheObject = new stdClass();
$cacheObject->time = time();//current time
$cacheObject->data = $data;
//serialize the object for storage
$fileContents = serialize($cacheObject);
//write the the contents to a file (even if the dir doesn't exist, unlike php's file_put_contents)
self::_file_force_contents($this->filePath, $fileContents);
return $cacheObject;
}
/**
* Loads the cache from the file. If the file doesn't exist, it forces a new cache.
*/
private function _loadCache() {
if(file_exists($this->filePath)){//cache file exists, load its contents
//read the contents in the file
$fileContents = file_get_contents($this->filePath);
//recreate the cache object
$cacheObject = unserialize($fileContents);
}else{//no cache file
//cache the live data
$cacheObject = $this->_cache();
}
//load the cache object
$this->cache = $cacheObject;
}
/**
* Fetches the live data by calling your live data function (see the constructor's
* $liveDataFunction parameter).
* @return string a serializable string containing the data.
*/
private function _getLiveData(){
if(!function_exists($this->dataFunction)){
trigger_error('No data function found. ', E_USER_WARNING);
}
else return call_user_func($this->dataFunction);
}
/**
* File put contents fails if you try to put a file in a directory that doesn't exist.
* This creates the directory. (Taken from the user notes in http://php.net/manual/en/function.file-put-contents.php)
* @param string $dir
* @param string $contents
*/
private static function _file_force_contents($dir, $contents){
$parts = explode('/', $dir);
$file = array_pop($parts);
$dir = '';
foreach($parts as $part)
if(!is_dir($dir .= "/$part")) mkdir($dir);
file_put_contents("$dir/$file", $contents);
}
}
?>