Cache.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 1.2.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Cache;
  16. use Cake\Cache\Engine\NullEngine;
  17. use Cake\Core\Error\Exception;
  18. use Cake\Core\StaticConfigTrait;
  19. /**
  20. * Cache provides a consistent interface to Caching in your application. It allows you
  21. * to use several different Cache engines, without coupling your application to a specific
  22. * implementation. It also allows you to change out cache storage or configuration without effecting
  23. * the rest of your application.
  24. *
  25. * ### Configuring Cache engines
  26. *
  27. * You can configure Cache engines in your application's `Config/cache.php` file.
  28. * A sample configuration would be:
  29. *
  30. * {{{
  31. * Cache::config('shared', [
  32. * 'className' => 'Cake\Cache\Engine\ApcEngine',
  33. * 'prefix' => 'my_app_'
  34. * ]);
  35. * }}}
  36. *
  37. * This would configure an APC cache engine to the 'shared' alias. You could then read and write
  38. * to that cache alias by using it for the `$config` parameter in the various Cache methods.
  39. *
  40. * In general all Cache operations are supported by all cache engines.
  41. * However, Cache::increment() and Cache::decrement() are not supported by File caching.
  42. *
  43. * There are 5 built-in caching engines:
  44. *
  45. * - `FileEngine` - Uses simple files to store content. Poor performance, but good for
  46. * storing large objects, or things that are not IO sensitive. Well suited to development
  47. * as it is an easy cache to inspect and manually flush.
  48. * - `ApcEngine` - Uses the APC object cache, one of the fastest caching engines.
  49. * - `MemcacheEngine` - Uses the PECL::Memcache extension and Memcached for storage.
  50. * Fast reads/writes, and benefits from memcache being distributed.
  51. * - `XcacheEngine` - Uses the Xcache extension, an alternative to APC.
  52. * - `WincacheEngine` - Uses Windows Cache Extension for PHP. Supports wincache 1.1.0 and higher.
  53. * This engine is recommended to people deploying on windows with IIS.
  54. * - `RedisEngine` - Uses redis and php-redis extension to store cache data.
  55. *
  56. * See Cache engine documentation for expected configuration keys.
  57. *
  58. * @see config/app.php for configuration settings
  59. * @param string $name Name of the configuration
  60. * @param array $config Optional associative array of settings passed to the engine
  61. * @return array [engine, settings] on success, false on failure
  62. * @throws \Cake\Core\Error\Exception
  63. */
  64. class Cache {
  65. use StaticConfigTrait;
  66. /**
  67. * Flag for tracking whether or not caching is enabled.
  68. *
  69. * @var bool
  70. */
  71. protected static $_enabled = true;
  72. /**
  73. * Group to Config mapping
  74. *
  75. * @var array
  76. */
  77. protected static $_groups = [];
  78. /**
  79. * Whether to reset the settings with the next call to Cache::set();
  80. *
  81. * @var array
  82. */
  83. protected static $_reset = false;
  84. /**
  85. * Cache Registry used for creating and using cache adapters.
  86. *
  87. * @var \Cake\Cache\CacheRegistry
  88. */
  89. protected static $_registry;
  90. /**
  91. * Finds and builds the instance of the required engine class.
  92. *
  93. * @param string $name Name of the config array that needs an engine instance built
  94. * @return void
  95. * @throws \Cake\Core\Error\Exception When a cache engine cannot be created.
  96. */
  97. protected static function _buildEngine($name) {
  98. if (empty(static::$_registry)) {
  99. static::$_registry = new CacheRegistry();
  100. }
  101. if (empty(static::$_config[$name]['className'])) {
  102. throw new Exception(sprintf('The "%s" cache configuration does not exist.', $name));
  103. }
  104. $config = static::$_config[$name];
  105. static::$_registry->load($name, $config);
  106. if (!empty($config['groups'])) {
  107. foreach ($config['groups'] as $group) {
  108. static::$_groups[$group][] = $name;
  109. static::$_groups[$group] = array_unique(static::$_groups[$group]);
  110. sort(static::$_groups[$group]);
  111. }
  112. }
  113. }
  114. /**
  115. * Fetch the engine attached to a specific configuration name.
  116. *
  117. * If the cache engine & configuration are missing an error will be
  118. * triggered.
  119. *
  120. * @param string $config The configuration name you want an engine for.
  121. * @return \Cake\Cache\CacheEngine When caching is disabled a null engine will be returned.
  122. */
  123. public static function engine($config) {
  124. if (!static::$_enabled) {
  125. return new NullEngine();
  126. }
  127. if (isset(static::$_registry->{$config})) {
  128. return static::$_registry->{$config};
  129. }
  130. static::_buildEngine($config);
  131. return static::$_registry->{$config};
  132. }
  133. /**
  134. * Garbage collection
  135. *
  136. * Permanently remove all expired and deleted data
  137. *
  138. * @param string $config [optional] The config name you wish to have garbage collected. Defaults to 'default'
  139. * @param int $expires [optional] An expires timestamp. Defaults to NULL
  140. * @return void
  141. */
  142. public static function gc($config = 'default', $expires = null) {
  143. $engine = static::engine($config);
  144. $engine->gc($expires);
  145. }
  146. /**
  147. * Write data for key into cache.
  148. *
  149. * ### Usage:
  150. *
  151. * Writing to the active cache config:
  152. *
  153. * `Cache::write('cached_data', $data);`
  154. *
  155. * Writing to a specific cache config:
  156. *
  157. * `Cache::write('cached_data', $data, 'long_term');`
  158. *
  159. * @param string $key Identifier for the data
  160. * @param mixed $value Data to be cached - anything except a resource
  161. * @param string $config Optional string configuration name to write to. Defaults to 'default'
  162. * @return bool True if the data was successfully cached, false on failure
  163. */
  164. public static function write($key, $value, $config = 'default') {
  165. $engine = static::engine($config);
  166. if (is_resource($value)) {
  167. return false;
  168. }
  169. $success = $engine->write($key, $value);
  170. if ($success === false && $value !== '') {
  171. trigger_error(
  172. sprintf(
  173. "%s cache was unable to write '%s' to %s cache",
  174. $config,
  175. $key,
  176. get_class($engine)
  177. ),
  178. E_USER_WARNING
  179. );
  180. }
  181. return $success;
  182. }
  183. /**
  184. * Write data for many keys into cache.
  185. *
  186. * ### Usage:
  187. *
  188. * Writing to the active cache config:
  189. *
  190. * `Cache::writeMany(['cached_data_1' => 'data 1', 'cached_data_2' => 'data 2']);`
  191. *
  192. * Writing to a specific cache config:
  193. *
  194. * `Cache::writeMany(['cached_data_1' => 'data 1', 'cached_data_2' => 'data 2'], 'long_term');`
  195. *
  196. * @param array $data An array of data to be stored in the cache
  197. * @param string $config Optional string configuration name to write to. Defaults to 'default'
  198. * @return array of bools for each key provided, indicating true for success or false for fail
  199. * @throws Cake\Core\Error\Exception
  200. */
  201. public static function writeMany($data, $config = 'default') {
  202. $engine = static::engine($config);
  203. $return = $engine->writeMany($data);
  204. foreach ($return as $key => $success) {
  205. if ($success === false && !empty($data[$key])) {
  206. throw new Exception(sprintf(
  207. '%s cache was unable to write \'%s\' to %s cache',
  208. $config,
  209. $key,
  210. get_class($engine)
  211. ));
  212. }
  213. }
  214. return $return;
  215. }
  216. /**
  217. * Read a key from the cache.
  218. *
  219. * ### Usage:
  220. *
  221. * Reading from the active cache configuration.
  222. *
  223. * `Cache::read('my_data');`
  224. *
  225. * Reading from a specific cache configuration.
  226. *
  227. * `Cache::read('my_data', 'long_term');`
  228. *
  229. * @param string $key Identifier for the data
  230. * @param string $config optional name of the configuration to use. Defaults to 'default'
  231. * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
  232. */
  233. public static function read($key, $config = 'default') {
  234. $engine = static::engine($config);
  235. return $engine->read($key);
  236. }
  237. /**
  238. * Read multiple keys from the cache.
  239. *
  240. * ### Usage:
  241. *
  242. * Reading multiple keys from the active cache configuration.
  243. *
  244. * `Cache::readMany(['my_data_1', 'my_data_2]);`
  245. *
  246. * Reading from a specific cache configuration.
  247. *
  248. * `Cache::readMany(['my_data_1', 'my_data_2], 'long_term');`
  249. *
  250. * @param array $keys an array of keys to fetch from the cache
  251. * @param string $config optional name of the configuration to use. Defaults to 'default'
  252. * @return array An array containing, for each of the given $keys, the cached data or false if cached data could not be
  253. * retreived
  254. */
  255. public static function readMany($keys, $config = 'default') {
  256. $engine = static::engine($config);
  257. return $engine->readMany($keys);
  258. }
  259. /**
  260. * Increment a number under the key and return incremented value.
  261. *
  262. * @param string $key Identifier for the data
  263. * @param int $offset How much to add
  264. * @param string $config Optional string configuration name. Defaults to 'default'
  265. * @return mixed new value, or false if the data doesn't exist, is not integer,
  266. * or if there was an error fetching it.
  267. */
  268. public static function increment($key, $offset = 1, $config = 'default') {
  269. $engine = static::engine($config);
  270. if (!is_int($offset) || $offset < 0) {
  271. return false;
  272. }
  273. return $engine->increment($key, $offset);
  274. }
  275. /**
  276. * Decrement a number under the key and return decremented value.
  277. *
  278. * @param string $key Identifier for the data
  279. * @param int $offset How much to subtract
  280. * @param string $config Optional string configuration name. Defaults to 'default'
  281. * @return mixed new value, or false if the data doesn't exist, is not integer,
  282. * or if there was an error fetching it
  283. */
  284. public static function decrement($key, $offset = 1, $config = 'default') {
  285. $engine = static::engine($config);
  286. if (!is_int($offset) || $offset < 0) {
  287. return false;
  288. }
  289. return $engine->decrement($key, $offset);
  290. }
  291. /**
  292. * Delete a key from the cache.
  293. *
  294. * ### Usage:
  295. *
  296. * Deleting from the active cache configuration.
  297. *
  298. * `Cache::delete('my_data');`
  299. *
  300. * Deleting from a specific cache configuration.
  301. *
  302. * `Cache::delete('my_data', 'long_term');`
  303. *
  304. * @param string $key Identifier for the data
  305. * @param string $config name of the configuration to use. Defaults to 'default'
  306. * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
  307. */
  308. public static function delete($key, $config = 'default') {
  309. $engine = static::engine($config);
  310. return $engine->delete($key);
  311. }
  312. /**
  313. * Delete many keys from the cache.
  314. *
  315. * ### Usage:
  316. *
  317. * Deleting multiple keys from the active cache configuration.
  318. *
  319. * `Cache::deleteMany(['my_data_1', 'my_data_2']);`
  320. *
  321. * Deleting from a specific cache configuration.
  322. *
  323. * `Cache::deleteMany(['my_data_1', 'my_data_2], 'long_term');`
  324. *
  325. * @param array $keys Array of cache keys to be deleted
  326. * @param string $config name of the configuration to use. Defaults to 'default'
  327. * @return array of boolean values that are true if the value was successfully deleted, false if it didn't exist or
  328. * couldn't be removed
  329. */
  330. public static function deleteMany($keys, $config = 'default') {
  331. $engine = static::engine($config);
  332. return $engine->deleteMany($keys);
  333. }
  334. /**
  335. * Delete all keys from the cache.
  336. *
  337. * @param bool $check if true will check expiration, otherwise delete all
  338. * @param string $config name of the configuration to use. Defaults to 'default'
  339. * @return bool True if the cache was successfully cleared, false otherwise
  340. */
  341. public static function clear($check = false, $config = 'default') {
  342. $engine = static::engine($config);
  343. return $engine->clear($check);
  344. }
  345. /**
  346. * Delete all keys from the cache belonging to the same group.
  347. *
  348. * @param string $group name of the group to be cleared
  349. * @param string $config name of the configuration to use. Defaults to 'default'
  350. * @return bool True if the cache group was successfully cleared, false otherwise
  351. */
  352. public static function clearGroup($group, $config = 'default') {
  353. $engine = static::engine($config);
  354. return $engine->clearGroup($group);
  355. }
  356. /**
  357. * Retrieve group names to config mapping.
  358. *
  359. * {{{
  360. * Cache::config('daily', ['duration' => '1 day', 'groups' => ['posts']]);
  361. * Cache::config('weekly', ['duration' => '1 week', 'groups' => ['posts', 'archive']]);
  362. * $configs = Cache::groupConfigs('posts');
  363. * }}}
  364. *
  365. * $config will equal to `['posts' => ['daily', 'weekly']]`
  366. *
  367. * @param string $group group name or null to retrieve all group mappings
  368. * @return array map of group and all configuration that has the same group
  369. * @throws \Cake\Core\Error\Exception
  370. */
  371. public static function groupConfigs($group = null) {
  372. if ($group === null) {
  373. return static::$_groups;
  374. }
  375. if (isset(self::$_groups[$group])) {
  376. return [$group => self::$_groups[$group]];
  377. }
  378. throw new Exception(sprintf('Invalid cache group %s', $group));
  379. }
  380. /**
  381. * Re-enable caching.
  382. *
  383. * If caching has been disabled with Cache::disable() this method will reverse that effect.
  384. *
  385. * @return void
  386. */
  387. public static function enable() {
  388. static::$_enabled = true;
  389. }
  390. /**
  391. * Disable caching.
  392. *
  393. * When disabled all cache operations will return null.
  394. *
  395. * @return void
  396. */
  397. public static function disable() {
  398. static::$_enabled = false;
  399. }
  400. /**
  401. * Check whether or not caching is enabled.
  402. *
  403. * @return bool
  404. */
  405. public static function enabled() {
  406. return static::$_enabled;
  407. }
  408. /**
  409. * Provides the ability to easily do read-through caching.
  410. *
  411. * When called if the $key is not set in $config, the $callable function
  412. * will be invoked. The results will then be stored into the cache config
  413. * at key.
  414. *
  415. * Examples:
  416. *
  417. * Using a Closure to provide data, assume `$this` is a Table object:
  418. *
  419. * {{{
  420. * $results = Cache::remember('all_articles', function() {
  421. * return $this->find('all');
  422. * });
  423. * }}}
  424. *
  425. * @param string $key The cache key to read/store data at.
  426. * @param callable $callable The callable that provides data in the case when
  427. * the cache key is empty. Can be any callable type supported by your PHP.
  428. * @param string $config The cache configuration to use for this operation.
  429. * Defaults to default.
  430. * @return mixed If the key is found: the cached data, false if the data
  431. * missing/expired, or an error. If the key is not found: boolean of the
  432. * success of the write
  433. */
  434. public static function remember($key, $callable, $config = 'default') {
  435. $existing = self::read($key, $config);
  436. if ($existing !== false) {
  437. return $existing;
  438. }
  439. $results = call_user_func($callable);
  440. self::write($key, $results, $config);
  441. return $results;
  442. }
  443. }