MemCache.php 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\caching;
  8. use yii\base\InvalidConfigException;
  9. /**
  10. * MemCache implements a cache application component based on [memcache](http://pecl.php.net/package/memcache)
  11. * and [memcached](http://pecl.php.net/package/memcached).
  12. *
  13. * MemCache supports both [memcache](http://pecl.php.net/package/memcache) and
  14. * [memcached](http://pecl.php.net/package/memcached). By setting [[useMemcached]] to be true or false,
  15. * one can let MemCache to use either memcached or memcache, respectively.
  16. *
  17. * MemCache can be configured with a list of memcache servers by settings its [[servers]] property.
  18. * By default, MemCache assumes there is a memcache server running on localhost at port 11211.
  19. *
  20. * See [[Cache]] for common cache operations that MemCache supports.
  21. *
  22. * Note, there is no security measure to protected data in memcache.
  23. * All data in memcache can be accessed by any process running in the system.
  24. *
  25. * To use MemCache as the cache application component, configure the application as follows,
  26. *
  27. * ~~~
  28. * [
  29. * 'components' => [
  30. * 'cache' => [
  31. * 'class' => 'yii\caching\MemCache',
  32. * 'servers' => [
  33. * [
  34. * 'host' => 'server1',
  35. * 'port' => 11211,
  36. * 'weight' => 60,
  37. * ],
  38. * [
  39. * 'host' => 'server2',
  40. * 'port' => 11211,
  41. * 'weight' => 40,
  42. * ],
  43. * ],
  44. * ],
  45. * ],
  46. * ]
  47. * ~~~
  48. *
  49. * In the above, two memcache servers are used: server1 and server2. You can configure more properties of
  50. * each server, such as `persistent`, `weight`, `timeout`. Please see [[MemCacheServer]] for available options.
  51. *
  52. * @property \Memcache|\Memcached $memcache The memcache (or memcached) object used by this cache component.
  53. * This property is read-only.
  54. * @property MemCacheServer[] $servers List of memcache server configurations. Note that the type of this
  55. * property differs in getter and setter. See [[getServers()]] and [[setServers()]] for details.
  56. *
  57. * @author Qiang Xue <[email protected]>
  58. * @since 2.0
  59. */
  60. class MemCache extends Cache
  61. {
  62. /**
  63. * @var boolean whether to use memcached or memcache as the underlying caching extension.
  64. * If true, [memcached](http://pecl.php.net/package/memcached) will be used.
  65. * If false, [memcache](http://pecl.php.net/package/memcache) will be used.
  66. * Defaults to false.
  67. */
  68. public $useMemcached = false;
  69. /**
  70. * @var \Memcache|\Memcached the Memcache instance
  71. */
  72. private $_cache = null;
  73. /**
  74. * @var array list of memcache server configurations
  75. */
  76. private $_servers = [];
  77. /**
  78. * Initializes this application component.
  79. * It creates the memcache instance and adds memcache servers.
  80. */
  81. public function init()
  82. {
  83. parent::init();
  84. $servers = $this->getServers();
  85. $cache = $this->getMemCache();
  86. if (empty($servers)) {
  87. $cache->addServer('127.0.0.1', 11211);
  88. } else {
  89. if (!$this->useMemcached) {
  90. // different version of memcache may have different number of parameters for the addServer method.
  91. $class = new \ReflectionClass($cache);
  92. $paramCount = $class->getMethod('addServer')->getNumberOfParameters();
  93. }
  94. foreach ($servers as $server) {
  95. if ($server->host === null) {
  96. throw new InvalidConfigException("The 'host' property must be specified for every memcache server.");
  97. }
  98. if ($this->useMemcached) {
  99. $cache->addServer($server->host, $server->port, $server->weight);
  100. } else {
  101. // $timeout is used for memcache versions that do not have timeoutms parameter
  102. $timeout = (int) ($server->timeout / 1000) + (($server->timeout % 1000 > 0) ? 1 : 0);
  103. if ($paramCount === 9) {
  104. $cache->addServer(
  105. $server->host, $server->port, $server->persistent,
  106. $server->weight, $timeout, $server->retryInterval,
  107. $server->status, $server->failureCallback, $server->timeout
  108. );
  109. } else {
  110. $cache->addServer(
  111. $server->host, $server->port, $server->persistent,
  112. $server->weight, $timeout, $server->retryInterval,
  113. $server->status, $server->failureCallback
  114. );
  115. }
  116. }
  117. }
  118. }
  119. }
  120. /**
  121. * Returns the underlying memcache (or memcached) object.
  122. * @return \Memcache|\Memcached the memcache (or memcached) object used by this cache component.
  123. * @throws InvalidConfigException if memcache or memcached extension is not loaded
  124. */
  125. public function getMemcache()
  126. {
  127. if ($this->_cache === null) {
  128. $extension = $this->useMemcached ? 'memcached' : 'memcache';
  129. if (!extension_loaded($extension)) {
  130. throw new InvalidConfigException("MemCache requires PHP $extension extension to be loaded.");
  131. }
  132. $this->_cache = $this->useMemcached ? new \Memcached : new \Memcache;
  133. }
  134. return $this->_cache;
  135. }
  136. /**
  137. * Returns the memcache server configurations.
  138. * @return MemCacheServer[] list of memcache server configurations.
  139. */
  140. public function getServers()
  141. {
  142. return $this->_servers;
  143. }
  144. /**
  145. * @param array $config list of memcache server configurations. Each element must be an array
  146. * with the following keys: host, port, persistent, weight, timeout, retryInterval, status.
  147. * @see http://www.php.net/manual/en/function.Memcache-addServer.php
  148. */
  149. public function setServers($config)
  150. {
  151. foreach ($config as $c) {
  152. $this->_servers[] = new MemCacheServer($c);
  153. }
  154. }
  155. /**
  156. * Retrieves a value from cache with a specified key.
  157. * This is the implementation of the method declared in the parent class.
  158. * @param string $key a unique key identifying the cached value
  159. * @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
  160. */
  161. protected function getValue($key)
  162. {
  163. return $this->_cache->get($key);
  164. }
  165. /**
  166. * Retrieves multiple values from cache with the specified keys.
  167. * @param array $keys a list of keys identifying the cached values
  168. * @return array a list of cached values indexed by the keys
  169. */
  170. protected function getValues($keys)
  171. {
  172. return $this->useMemcached ? $this->_cache->getMulti($keys) : $this->_cache->get($keys);
  173. }
  174. /**
  175. * Stores a value identified by a key in cache.
  176. * This is the implementation of the method declared in the parent class.
  177. *
  178. * @param string $key the key identifying the value to be cached
  179. * @param string $value the value to be cached
  180. * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
  181. * @return boolean true if the value is successfully stored into cache, false otherwise
  182. */
  183. protected function setValue($key, $value, $expire)
  184. {
  185. if ($expire > 0) {
  186. $expire += time();
  187. } else {
  188. $expire = 0;
  189. }
  190. return $this->useMemcached ? $this->_cache->set($key, $value, $expire) : $this->_cache->set($key, $value, 0, $expire);
  191. }
  192. /**
  193. * Stores multiple key-value pairs in cache.
  194. * @param array $data array where key corresponds to cache key while value is the value stored
  195. * @param integer $expire the number of seconds in which the cached values will expire. 0 means never expire.
  196. * @return array array of failed keys. Always empty in case of using memcached.
  197. */
  198. protected function setValues($data, $expire)
  199. {
  200. if ($this->useMemcached) {
  201. if ($expire > 0) {
  202. $expire += time();
  203. } else {
  204. $expire = 0;
  205. }
  206. $this->_cache->setMulti($data, $expire);
  207. return [];
  208. } else {
  209. return parent::setValues($data, $expire);
  210. }
  211. }
  212. /**
  213. * Stores a value identified by a key into cache if the cache does not contain this key.
  214. * This is the implementation of the method declared in the parent class.
  215. *
  216. * @param string $key the key identifying the value to be cached
  217. * @param string $value the value to be cached
  218. * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
  219. * @return boolean true if the value is successfully stored into cache, false otherwise
  220. */
  221. protected function addValue($key, $value, $expire)
  222. {
  223. if ($expire > 0) {
  224. $expire += time();
  225. } else {
  226. $expire = 0;
  227. }
  228. return $this->useMemcached ? $this->_cache->add($key, $value, $expire) : $this->_cache->add($key, $value, 0, $expire);
  229. }
  230. /**
  231. * Deletes a value with the specified key from cache
  232. * This is the implementation of the method declared in the parent class.
  233. * @param string $key the key of the value to be deleted
  234. * @return boolean if no error happens during deletion
  235. */
  236. protected function deleteValue($key)
  237. {
  238. return $this->_cache->delete($key, 0);
  239. }
  240. /**
  241. * Deletes all values from cache.
  242. * This is the implementation of the method declared in the parent class.
  243. * @return boolean whether the flush operation was successful.
  244. */
  245. protected function flushValues()
  246. {
  247. return $this->_cache->flush();
  248. }
  249. }