2 // +----------------------------------------------------------------------+
4 // +----------------------------------------------------------------------+
5 // | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group |
6 // +----------------------------------------------------------------------+
7 // | This source file is subject to version 2.0 of the PHP license, |
8 // | that is bundled with this package in the file LICENSE, and is |
9 // | available at through the world-wide-web at |
10 // | http://www.php.net/license/2_02.txt. |
11 // | If you did not receive a copy of the PHP license and are unable to |
12 // | obtain it through the world-wide-web, please send a note to |
13 // | license@php.net so we can mail you a copy immediately. |
14 // +----------------------------------------------------------------------+
15 // | Authors: Ulf Wendel <ulf.wendel@phpdoc.de> |
16 // | Sebastian Bergmann <sb@sebastian-bergmann.de> |
17 // +----------------------------------------------------------------------+
19 // $Id: Cache.php,v 1.2 2004-04-26 20:44:36 rurban Exp $
21 require_once('PEAR.php');
22 require_once('Cache/Error.php');
25 * Cache is a base class for cache implementations.
27 * The pear cache module is a generic data cache which can be used to
28 * cache script runs. The idea behind the cache is quite simple. If you have
29 * the same input parameters for whatever tasks/algorithm you use you'll
30 * usually get the same output. So why not caching templates, functions calls,
31 * graphic generation etc. Caching certain actions e.g. XSLT tranformations
32 * saves you lots of time.
34 * The design of the cache reminds of PHPLibs session implementation. A
35 * (PHPLib: session) controller uses storage container (PHPLib: ct_*.inc) to save
36 * certain data (PHPLib: session data). In contrast to the session stuff it's up to
37 * you to generate an ID for the data to cache. If you're using the output cache
38 * you might use the script name as a seed for cache::generateID(), if your using the
39 * function cache you'd use an array with all function parameters.
41 * Usage example of the generic data cache:
43 * require_once('Cache.php');
45 * $cache = new Cache('file', array('cache_dir' => 'cache/') );
46 * $id = $cache->generateID('testentry');
48 * if ($data = $cache->get($id)) {
49 * print "Cache hit.<br>Data: $data";
52 * $data = 'data of any kind';
53 * $cache->save($id, $data);
54 * print 'Cache miss.<br>';
57 * WARNING: No File/DB-Table-Row locking is implemented yet,
58 * it's possible, that you get corrupted data-entries under
59 * bad circumstances (especially with the file container)
61 * @author Ulf Wendel <ulf.wendel@phpdoc.de>
62 * @version $Id: Cache.php,v 1.2 2004-04-26 20:44:36 rurban Exp $
66 class Cache extends PEAR {
69 * Enables / disables caching.
71 * TODO: Add explanation what this is good for.
79 * Garbage collection: probability in seconds
81 * If set to a value above 0 a garbage collection will
82 * flush all cache entries older than the specified number
86 * @see $gc_probability, $gc_maxlifetime
92 * Garbage collection: probability in percent
94 * TODO: Add an explanation.
96 * @var integer 0 => never
97 * @see $gc_time, $gc_maxlifetime
100 var $gc_probability = 1;
103 * Garbage collection: delete all entries not use for n seconds.
105 * Default is one day, 60 * 60 * 24 = 86400 seconds.
108 * @see $gc_probability, $gc_time
110 var $gc_maxlifetime = 86400;
113 * Storage container object.
115 * @var object Cache_Container
125 * @param string Name of container class
126 * @param array Array with container class options
128 function Cache($container, $container_options = '')
131 $container = strtolower($container);
132 $container_class = 'Cache_Container_' . $container;
133 $container_classfile = 'Cache/Container/' . $container . '.php';
135 include_once $container_classfile;
136 $this->container = new $container_class($container_options);
142 $this->garbageCollection();
146 * Returns the current caching state.
148 * @return boolean The current caching state.
151 function getCaching()
153 return ($this->caching);
157 * Enables or disables caching.
159 * @param boolean The new caching state.
162 function setCaching($state)
164 $this->caching = $state;
168 * Returns the requested dataset it if exists and is not expired
170 * @param string dataset ID
171 * @param string cache group
172 * @return mixed cached data or NULL on failure
175 function get($id, $group = 'default') {
179 if ($this->isCached($id, $group) && !$this->isExpired($id, $group))
180 return $this->load($id, $group);
186 * Stores the given data in the cache.
188 * @param string dataset ID used as cache identifier
189 * @param mixed data to cache
190 * @param integer lifetime of the cached data in seconds - 0 for endless
191 * @param string cache group
195 function save($id, $data, $expires = 0, $group = 'default') {
199 return $this->extSave($id, $data, '',$expires, $group);
203 * Stores a dataset without additional userdefined data.
205 * @param string dataset ID
206 * @param mixed data to store
207 * @param string additional userdefined data
208 * @param mixed userdefined expire date
209 * @param string cache group
211 * @throws Cache_Error
215 function extSave($id, $cachedata, $userdata, $expires = 0, $group = 'default') {
219 return $this->container->save($id, $cachedata, $expires, $group, $userdata);
220 } // end func extSave
223 * Loads the given ID from the cache.
225 * @param string dataset ID
226 * @param string cache group
227 * @return mixed cached data or NULL on failure
230 function load($id, $group = 'default') {
234 return $this->container->load($id, $group);
238 * Returns the userdata field of a cached data set.
240 * @param string dataset ID
241 * @param string cache group
242 * @return string userdata
246 function getUserdata($id, $group = 'default') {
250 return $this->container->getUserdata($id, $group);
251 } // end func getUserdata
254 * Removes the specified dataset from the cache.
256 * @param string dataset ID
257 * @param string cache group
261 function remove($id, $group = 'default') {
265 return $this->container->remove($id, $group);
269 * Flushes the cache - removes all data from it
271 * @param string cache group, if empty all groups will be flashed
272 * @return integer number of removed datasets
274 function flush($group = 'default') {
278 return $this->container->flush($group);
282 * Checks if a dataset exists.
284 * Note: this does not say that the cached data is not expired!
286 * @param string dataset ID
287 * @param string cache group
291 function isCached($id, $group = 'default') {
295 return $this->container->isCached($id, $group);
296 } // end func isCached
299 * Checks if a dataset is expired
301 * @param string dataset ID
302 * @param string cache group
303 * @param integer maximum age for the cached data in seconds - 0 for endless
304 * If the cached data is older but the given lifetime it will
305 * be removed from the cache. You don't have to provide this
306 * argument if you call isExpired(). Every dataset knows
307 * it's expire date and will be removed automatically. Use
308 * this only if you know what you're doing...
312 function isExpired($id, $group = 'default', $max_age = 0) {
316 return $this->container->isExpired($id, $group, $max_age);
317 } // end func isExpired
320 * Generates a "unique" ID for the given value
322 * This is a quick but dirty hack to get a "unique" ID for a any kind of variable.
323 * ID clashes might occur from time to time although they are extreme unlikely!
325 * @param mixed variable to generate a ID for
326 * @return string "unique" ID
329 function generateID($variable) {
330 // WARNING: ID clashes are possible although unlikely
331 return md5(serialize($variable));
335 * Calls the garbage collector of the storage object with a certain probability
337 * @param boolean Force a garbage collection run?
338 * @see $gc_probability, $gc_time
340 function garbageCollection($force = false) {
341 static $last_run = 0;
346 srand((double) microtime() * 1000000);
348 // time and probability based
349 if (($force) || ($last_run && $last_run < time() + $this->gc_time) || (rand(1, 100) < $this->gc_probability)) {
350 $this->container->garbageCollection($this->gc_maxlifetime);
353 } // end func garbageCollection