1: <?php
2: /**
3: * CMemCache class file
4: *
5: * @author Qiang Xue <qiang.xue@gmail.com>
6: * @link http://www.yiiframework.com/
7: * @copyright 2008-2013 Yii Software LLC
8: * @license http://www.yiiframework.com/license/
9: */
10:
11: /**
12: * CMemCache implements a cache application component based on {@link http://memcached.org/ memcached}.
13: *
14: * CMemCache can be configured with a list of memcache servers by settings
15: * its {@link setServers servers} property. By default, CMemCache assumes
16: * there is a memcache server running on localhost at port 11211.
17: *
18: * See {@link CCache} manual for common cache operations that are supported by CMemCache.
19: *
20: * Note, there is no security measure to protected data in memcache.
21: * All data in memcache can be accessed by any process running in the system.
22: *
23: * To use CMemCache as the cache application component, configure the application as follows,
24: * <pre>
25: * array(
26: * 'components'=>array(
27: * 'cache'=>array(
28: * 'class'=>'CMemCache',
29: * 'servers'=>array(
30: * array(
31: * 'host'=>'server1',
32: * 'port'=>11211,
33: * 'weight'=>60,
34: * ),
35: * array(
36: * 'host'=>'server2',
37: * 'port'=>11211,
38: * 'weight'=>40,
39: * ),
40: * ),
41: * ),
42: * ),
43: * )
44: * </pre>
45: * In the above, two memcache servers are used: server1 and server2.
46: * You can configure more properties of every server, including:
47: * host, port, persistent, weight, timeout, retryInterval, status.
48: * See {@link http://www.php.net/manual/en/function.memcache-addserver.php}
49: * for more details.
50: *
51: * CMemCache can also be used with {@link http://pecl.php.net/package/memcached memcached}.
52: * To do so, set {@link useMemcached} to be true.
53: *
54: * @property mixed $memCache The memcache instance (or memcached if {@link useMemcached} is true) used by this component.
55: * @property array $servers List of memcache server configurations. Each element is a {@link CMemCacheServerConfiguration}.
56: *
57: * @author Qiang Xue <qiang.xue@gmail.com>
58: * @package system.caching
59: * @since 1.0
60: */
61: class CMemCache extends CCache
62: {
63: /**
64: * @var boolean whether to use memcached or memcache as the underlying caching extension.
65: * If true {@link http://pecl.php.net/package/memcached memcached} will be used.
66: * If false {@link http://pecl.php.net/package/memcache memcache}. will be used.
67: * Defaults to false.
68: */
69: public $useMemcached=false;
70: /**
71: * @var Memcache the Memcache instance
72: */
73: private $_cache=null;
74: /**
75: * @var array list of memcache server configurations
76: */
77: private $_servers=array();
78:
79: /**
80: * Initializes this application component.
81: * This method is required by the {@link IApplicationComponent} interface.
82: * It creates the memcache instance and adds memcache servers.
83: * @throws CException if memcache extension is not loaded
84: */
85: public function init()
86: {
87: parent::init();
88: $servers=$this->getServers();
89: $cache=$this->getMemCache();
90: if(count($servers))
91: {
92: foreach($servers as $server)
93: {
94: if($this->useMemcached)
95: $cache->addServer($server->host,$server->port,$server->weight);
96: else
97: $cache->addServer($server->host,$server->port,$server->persistent,$server->weight,$server->timeout,$server->retryInterval,$server->status);
98: }
99: }
100: else
101: $cache->addServer('localhost',11211);
102: }
103:
104: /**
105: * @throws CException if extension isn't loaded
106: * @return Memcache|Memcached the memcache instance (or memcached if {@link useMemcached} is true) used by this component.
107: */
108: public function getMemCache()
109: {
110: if($this->_cache!==null)
111: return $this->_cache;
112: else
113: {
114: $extension=$this->useMemcached ? 'memcached' : 'memcache';
115: if(!extension_loaded($extension))
116: throw new CException(Yii::t('yii',"CMemCache requires PHP {extension} extension to be loaded.",
117: array('{extension}'=>$extension)));
118: return $this->_cache=$this->useMemcached ? new Memcached : new Memcache;
119: }
120: }
121:
122: /**
123: * @return array list of memcache server configurations. Each element is a {@link CMemCacheServerConfiguration}.
124: */
125: public function getServers()
126: {
127: return $this->_servers;
128: }
129:
130: /**
131: * @param array $config list of memcache server configurations. Each element must be an array
132: * with the following keys: host, port, persistent, weight, timeout, retryInterval, status.
133: * @see http://www.php.net/manual/en/function.Memcache-addServer.php
134: */
135: public function setServers($config)
136: {
137: foreach($config as $c)
138: $this->_servers[]=new CMemCacheServerConfiguration($c);
139: }
140:
141: /**
142: * Retrieves a value from cache with a specified key.
143: * This is the implementation of the method declared in the parent class.
144: * @param string $key a unique key identifying the cached value
145: * @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
146: */
147: protected function getValue($key)
148: {
149: return $this->_cache->get($key);
150: }
151:
152: /**
153: * Retrieves multiple values from cache with the specified keys.
154: * @param array $keys a list of keys identifying the cached values
155: * @return array a list of cached values indexed by the keys
156: */
157: protected function getValues($keys)
158: {
159: return $this->useMemcached ? $this->_cache->getMulti($keys) : $this->_cache->get($keys);
160: }
161:
162: /**
163: * Stores a value identified by a key in cache.
164: * This is the implementation of the method declared in the parent class.
165: *
166: * @param string $key the key identifying the value to be cached
167: * @param string $value the value to be cached
168: * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
169: * @return boolean true if the value is successfully stored into cache, false otherwise
170: */
171: protected function setValue($key,$value,$expire)
172: {
173: if($expire>0)
174: $expire+=time();
175: else
176: $expire=0;
177:
178: return $this->useMemcached ? $this->_cache->set($key,$value,$expire) : $this->_cache->set($key,$value,0,$expire);
179: }
180:
181: /**
182: * Stores a value identified by a key into cache if the cache does not contain this key.
183: * This is the implementation of the method declared in the parent class.
184: *
185: * @param string $key the key identifying the value to be cached
186: * @param string $value the value to be cached
187: * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
188: * @return boolean true if the value is successfully stored into cache, false otherwise
189: */
190: protected function addValue($key,$value,$expire)
191: {
192: if($expire>0)
193: $expire+=time();
194: else
195: $expire=0;
196:
197: return $this->useMemcached ? $this->_cache->add($key,$value,$expire) : $this->_cache->add($key,$value,0,$expire);
198: }
199:
200: /**
201: * Deletes a value with the specified key from cache
202: * This is the implementation of the method declared in the parent class.
203: * @param string $key the key of the value to be deleted
204: * @return boolean if no error happens during deletion
205: */
206: protected function deleteValue($key)
207: {
208: return $this->_cache->delete($key, 0);
209: }
210:
211: /**
212: * Deletes all values from cache.
213: * This is the implementation of the method declared in the parent class.
214: * @return boolean whether the flush operation was successful.
215: * @since 1.1.5
216: */
217: protected function flushValues()
218: {
219: return $this->_cache->flush();
220: }
221: }
222:
223: /**
224: * CMemCacheServerConfiguration represents the configuration data for a single memcache server.
225: *
226: * See {@link http://www.php.net/manual/en/function.Memcache-addServer.php}
227: * for detailed explanation of each configuration property.
228: *
229: * @author Qiang Xue <qiang.xue@gmail.com>
230: * @package system.caching
231: * @since 1.0
232: */
233: class CMemCacheServerConfiguration extends CComponent
234: {
235: /**
236: * @var string memcache server hostname or IP address
237: */
238: public $host;
239: /**
240: * @var integer memcache server port
241: */
242: public $port=11211;
243: /**
244: * @var boolean whether to use a persistent connection
245: */
246: public $persistent=true;
247: /**
248: * @var integer probability of using this server among all servers.
249: */
250: public $weight=1;
251: /**
252: * @var integer value in seconds which will be used for connecting to the server
253: */
254: public $timeout=15;
255: /**
256: * @var integer how often a failed server will be retried (in seconds)
257: */
258: public $retryInterval=15;
259: /**
260: * @var boolean if the server should be flagged as online upon a failure
261: */
262: public $status=true;
263:
264: /**
265: * Constructor.
266: * @param array $config list of memcache server configurations.
267: * @throws CException if the configuration is not an array
268: */
269: public function __construct($config)
270: {
271: if(is_array($config))
272: {
273: foreach($config as $key=>$value)
274: $this->$key=$value;
275: if($this->host===null)
276: throw new CException(Yii::t('yii','CMemCache server configuration must have "host" value.'));
277: }
278: else
279: throw new CException(Yii::t('yii','CMemCache server configuration must be an array.'));
280: }
281: }
282: