QueryCacher.php 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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 3.0.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Datasource;
  16. use Cake\Cache\Cache;
  17. use Cake\Cache\CacheEngine;
  18. use RuntimeException;
  19. use Traversable;
  20. /**
  21. * Handles caching queries and loading results from the cache.
  22. *
  23. * Used by Cake\Datasource\QueryTrait internally.
  24. *
  25. * @see \Cake\Datasource\QueryTrait::cache() for the public interface.
  26. */
  27. class QueryCacher {
  28. /**
  29. * Constructor.
  30. *
  31. * @param string|\Closure $key The key or function to generate a key.
  32. * @param string|CacheEngine $config The cache config name or cache engine instance.
  33. * @throws RuntimeException
  34. */
  35. public function __construct($key, $config) {
  36. if (!is_string($key) && !is_callable($key)) {
  37. throw new RuntimeException('Cache keys must be strings or callables.');
  38. }
  39. $this->_key = $key;
  40. if (!is_string($config) && !($config instanceof CacheEngine)) {
  41. throw new RuntimeException('Cache configs must be strings or CacheEngine instances.');
  42. }
  43. $this->_config = $config;
  44. }
  45. /**
  46. * Load the cached results from the cache or run the query.
  47. *
  48. * @param object $query The query the cache read is for.
  49. * @return \Cake\ORM\ResultSet|null Either the cached results or null.
  50. */
  51. public function fetch($query) {
  52. $key = $this->_resolveKey($query);
  53. $storage = $this->_resolveCacher();
  54. $result = $storage->read($key);
  55. if (empty($result)) {
  56. return null;
  57. }
  58. return $result;
  59. }
  60. /**
  61. * Store the result set into the cache.
  62. *
  63. * @param object $query The query the cache read is for.
  64. * @param \Traversable $results The result set to store.
  65. * @return void
  66. */
  67. public function store($query, Traversable $results) {
  68. $key = $this->_resolveKey($query);
  69. $storage = $this->_resolveCacher();
  70. return $storage->write($key, $results);
  71. }
  72. /**
  73. * Get/generate the cache key.
  74. *
  75. * @param object $query The query to generate a key for.
  76. * @return string
  77. * @throws \RuntimeException
  78. */
  79. protected function _resolveKey($query) {
  80. if (is_string($this->_key)) {
  81. return $this->_key;
  82. }
  83. $func = $this->_key;
  84. $key = $func($query);
  85. if (!is_string($key)) {
  86. $msg = sprintf('Cache key functions must return a string. Got %s.', var_export($key, true));
  87. throw new RuntimeException($msg);
  88. }
  89. return $key;
  90. }
  91. /**
  92. * Get the cache engine.
  93. *
  94. * @return \Cake\Cache\CacheEngine
  95. */
  96. protected function _resolveCacher() {
  97. if (is_string($this->_config)) {
  98. return Cache::engine($this->_config);
  99. }
  100. return $this->_config;
  101. }
  102. }