Cache.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. <?php
  2. /**
  3. * KO7 Cache provides a common interface to a variety of caching engines. Tags are
  4. * supported where available natively to the cache system. KO7 Cache supports multiple
  5. * instances of cache engines through a grouped singleton pattern.
  6. *
  7. * ### Supported cache engines
  8. *
  9. * * [APC](http://php.net/manual/en/book.apc.php)
  10. * * [eAccelerator](http://eaccelerator.net/)
  11. * * File
  12. * * [Memcache](http://memcached.org/)
  13. * * [Memcached-tags](http://code.google.com/p/memcached-tags/)
  14. * * [SQLite](http://www.sqlite.org/)
  15. * * [Xcache](http://xcache.lighttpd.net/)
  16. *
  17. * ### Introduction to caching
  18. *
  19. * Caching should be implemented with consideration. Generally, caching the result of resources
  20. * is faster than reprocessing them. Choosing what, how and when to cache is vital. PHP APC is
  21. * presently one of the fastest caching systems available, closely followed by Memcache. SQLite
  22. * and File caching are two of the slowest cache methods, however usually faster than reprocessing
  23. * a complex set of instructions.
  24. *
  25. * Caching engines that use memory are considerably faster than the file based alternatives. But
  26. * memory is limited whereas disk space is plentiful. If caching large datasets it is best to use
  27. * file caching.
  28. *
  29. * ### Configuration settings
  30. *
  31. * KO7 Cache uses configuration groups to create cache instances. A configuration group can
  32. * use any supported driver, with successive groups using the same driver type if required.
  33. *
  34. * #### Configuration example
  35. *
  36. * Below is an example of a _memcache_ server configuration.
  37. *
  38. * return array(
  39. * 'memcache' => array( // Name of group
  40. * 'driver' => 'memcache', // using Memcache driver
  41. * 'servers' => array( // Available server definitions
  42. * array(
  43. * 'host' => 'localhost',
  44. * 'port' => 11211,
  45. * 'persistent' => FALSE
  46. * )
  47. * ),
  48. * 'compression' => FALSE, // Use compression?
  49. * ),
  50. * )
  51. *
  52. * In cases where only one cache group is required, set `Cache::$default` (in your bootstrap,
  53. * or by extending `KO7_Cache` class) to the name of the group, and use:
  54. *
  55. * $cache = Cache::instance(); // instead of Cache::instance('memcache')
  56. *
  57. * It will return the cache instance of the group it has been set in `Cache::$default`.
  58. *
  59. * #### General cache group configuration settings
  60. *
  61. * Below are the settings available to all types of cache driver.
  62. *
  63. * Name | Required | Description
  64. * -------------- | -------- | ---------------------------------------------------------------
  65. * driver | __YES__ | (_string_) The driver type to use
  66. *
  67. * Details of the settings specific to each driver are available within the drivers documentation.
  68. *
  69. * ### System requirements
  70. *
  71. * * KO7 3.0.x
  72. * * PHP 5.2.4 or greater
  73. *
  74. * @package KO7/Cache
  75. * @category Base
  76. * @version 2.0
  77. *
  78. * @copyright (c) 2007-2016 Kohana Team
  79. * @copyright (c) since 2016 Koseven Team
  80. * @license https://koseven.dev/LICENSE
  81. */
  82. abstract class KO7_Cache {
  83. const DEFAULT_EXPIRE = 3600;
  84. /**
  85. * @var string default driver to use
  86. */
  87. public static $default = 'file';
  88. /**
  89. * @var KO7_Cache instances
  90. */
  91. public static $instances = [];
  92. /**
  93. * Creates a singleton of a KO7 Cache group. If no group is supplied
  94. * the __default__ cache group is used.
  95. *
  96. * // Create an instance of the default group
  97. * $default_group = Cache::instance();
  98. *
  99. * // Create an instance of a group
  100. * $foo_group = Cache::instance('foo');
  101. *
  102. * // Access an instantiated group directly
  103. * $foo_group = Cache::$instances['default'];
  104. *
  105. * @param string $group the name of the cache group to use [Optional]
  106. * @return Cache
  107. * @throws Cache_Exception
  108. */
  109. public static function instance($group = NULL)
  110. {
  111. // If there is no group supplied, try to get it from the config
  112. if ($group === NULL)
  113. {
  114. $group = KO7::$config->load('cache.default');
  115. }
  116. // If there is no group supplied
  117. if ($group === NULL)
  118. {
  119. // Use the default setting
  120. $group = Cache::$default;
  121. }
  122. if (isset(Cache::$instances[$group]))
  123. {
  124. // Return the current group if initiated already
  125. return Cache::$instances[$group];
  126. }
  127. $config = KO7::$config->load('cache');
  128. if ( ! $config->offsetExists($group))
  129. {
  130. throw new Cache_Exception(
  131. 'Failed to load KO7 Cache group: :group',
  132. [':group' => $group]
  133. );
  134. }
  135. $config = $config->get($group);
  136. // Create a new cache type instance
  137. $cache_class = 'Cache_'.ucfirst($config['driver']);
  138. Cache::$instances[$group] = new $cache_class($config);
  139. // Return the instance
  140. return Cache::$instances[$group];
  141. }
  142. /**
  143. * @var Config
  144. */
  145. protected $_config = [];
  146. /**
  147. * Ensures singleton pattern is observed, loads the default expiry
  148. *
  149. * @param array $config configuration
  150. */
  151. protected function __construct(array $config)
  152. {
  153. $this->config($config);
  154. }
  155. /**
  156. * Getter and setter for the configuration. If no argument provided, the
  157. * current configuration is returned. Otherwise the configuration is set
  158. * to this class.
  159. *
  160. * // Overwrite all configuration
  161. * $cache->config(array('driver' => 'memcache', '...'));
  162. *
  163. * // Set a new configuration setting
  164. * $cache->config('servers', array(
  165. * 'foo' => 'bar',
  166. * '...'
  167. * ));
  168. *
  169. * // Get a configuration setting
  170. * $servers = $cache->config('servers);
  171. *
  172. * @param mixed key to set to array, either array or config path
  173. * @param mixed value to associate with key
  174. * @return mixed
  175. */
  176. public function config($key = NULL, $value = NULL)
  177. {
  178. if ($key === NULL)
  179. return $this->_config;
  180. if (is_array($key))
  181. {
  182. $this->_config = $key;
  183. }
  184. else
  185. {
  186. if ($value === NULL)
  187. return Arr::get($this->_config, $key);
  188. $this->_config[$key] = $value;
  189. }
  190. return $this;
  191. }
  192. /**
  193. * Overload the __clone() method to prevent cloning
  194. *
  195. * @return void
  196. * @throws Cache_Exception
  197. */
  198. final public function __clone()
  199. {
  200. throw new Cache_Exception('Cloning of KO7_Cache objects is forbidden');
  201. }
  202. /**
  203. * Retrieve a cached value entry by id.
  204. *
  205. * // Retrieve cache entry from default group
  206. * $data = Cache::instance()->get('foo');
  207. *
  208. * // Retrieve cache entry from default group and return 'bar' if miss
  209. * $data = Cache::instance()->get('foo', 'bar');
  210. *
  211. * // Retrieve cache entry from memcache group
  212. * $data = Cache::instance('memcache')->get('foo');
  213. *
  214. * @param string $id id of cache to entry
  215. * @param string $default default value to return if cache miss
  216. * @return mixed
  217. * @throws Cache_Exception
  218. */
  219. abstract public function get($id, $default = NULL);
  220. /**
  221. * Set a value to cache with id and lifetime
  222. *
  223. * $data = 'bar';
  224. *
  225. * // Set 'bar' to 'foo' in default group, using default expiry
  226. * Cache::instance()->set('foo', $data);
  227. *
  228. * // Set 'bar' to 'foo' in default group for 30 seconds
  229. * Cache::instance()->set('foo', $data, 30);
  230. *
  231. * // Set 'bar' to 'foo' in memcache group for 10 minutes
  232. * if (Cache::instance('memcache')->set('foo', $data, 600))
  233. * {
  234. * // Cache was set successfully
  235. * return
  236. * }
  237. *
  238. * @param string $id id of cache entry
  239. * @param string $data data to set to cache
  240. * @param integer $lifetime lifetime in seconds
  241. * @return boolean
  242. */
  243. abstract public function set($id, $data, $lifetime = 3600);
  244. /**
  245. * Delete a cache entry based on id
  246. *
  247. * // Delete 'foo' entry from the default group
  248. * Cache::instance()->delete('foo');
  249. *
  250. * // Delete 'foo' entry from the memcache group
  251. * Cache::instance('memcache')->delete('foo')
  252. *
  253. * @param string $id id to remove from cache
  254. * @return boolean
  255. */
  256. abstract public function delete($id);
  257. /**
  258. * Delete all cache entries.
  259. *
  260. * Beware of using this method when
  261. * using shared memory cache systems, as it will wipe every
  262. * entry within the system for all clients.
  263. *
  264. * // Delete all cache entries in the default group
  265. * Cache::instance()->delete_all();
  266. *
  267. * // Delete all cache entries in the memcache group
  268. * Cache::instance('memcache')->delete_all();
  269. *
  270. * @return boolean
  271. */
  272. abstract public function delete_all();
  273. /**
  274. * Takes the sha1 of the id and adds prefix to avoid duplicates
  275. *
  276. * The id is converted to a sha1 to prevent any issues with
  277. * id length or any special character
  278. *
  279. * // Sanitize a cache id
  280. * $id = $this->_sanitize_id($id);
  281. *
  282. * @param string $id id of cache to sanitize
  283. * @return string
  284. */
  285. protected function _sanitize_id($id)
  286. {
  287. // adding cache prefix to avoid duplicates
  288. $prefix = '';
  289. // configuration for the specific cache group
  290. if (isset($this->_config['prefix']) AND $this->_config['prefix'] !== NULL)
  291. {
  292. $prefix = $this->_config['prefix'];
  293. }
  294. // prefix general configuration cache
  295. else
  296. {
  297. $prefix = KO7::$config->load('cache.prefix');
  298. }
  299. // sha1 the id makes sure name is not too long and has not any not allowed characters
  300. return $prefix.sha1($id);
  301. }
  302. }
  303. // End KO7_Cache