You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							352 lines
						
					
					
						
							13 KiB
						
					
					
				
			
		
		
	
	
							352 lines
						
					
					
						
							13 KiB
						
					
					
				<?php | 
						|
/** | 
						|
 * @link http://www.yiiframework.com/ | 
						|
 * @copyright Copyright (c) 2008 Yii Software LLC | 
						|
 * @license http://www.yiiframework.com/license/ | 
						|
 */ | 
						|
 | 
						|
namespace yii\caching; | 
						|
 | 
						|
use yii\base\Component; | 
						|
use yii\helpers\StringHelper; | 
						|
 | 
						|
/** | 
						|
 * Cache is the base class for cache classes supporting different cache storage implementation. | 
						|
 * | 
						|
 * A data item can be stored in cache by calling [[set()]] and be retrieved back | 
						|
 * later (in the same or different request) by [[get()]]. In both operations, | 
						|
 * a key identifying the data item is required. An expiration time and/or a [[Dependency|dependency]] | 
						|
 * can also be specified when calling [[set()]]. If the data item expires or the dependency | 
						|
 * changes at the time of calling [[get()]], the cache will return no data. | 
						|
 * | 
						|
 * A typical usage pattern of cache is like the following: | 
						|
 * | 
						|
 * ~~~ | 
						|
 * $key = 'demo'; | 
						|
 * $data = $cache->get($key); | 
						|
 * if ($data === false) { | 
						|
 *     // ...generate $data here... | 
						|
 *     $cache->set($key, $data, $expire, $dependency); | 
						|
 * } | 
						|
 * ~~~ | 
						|
 * | 
						|
 * Because Cache implements the ArrayAccess interface, it can be used like an array. For example, | 
						|
 * | 
						|
 * ~~~ | 
						|
 * $cache['foo'] = 'some data'; | 
						|
 * echo $cache['foo']; | 
						|
 * ~~~ | 
						|
 * | 
						|
 * Derived classes should implement the following methods: | 
						|
 * | 
						|
 * - [[getValue()]]: retrieve the value with a key (if any) from cache | 
						|
 * - [[setValue()]]: store the value with a key into cache | 
						|
 * - [[addValue()]]: store the value only if the cache does not have this key before | 
						|
 * - [[deleteValue()]]: delete the value with the specified key from cache | 
						|
 * - [[flushValues()]]: delete all values from cache | 
						|
 * | 
						|
 * | 
						|
 * @author Qiang Xue <qiang.xue@gmail.com> | 
						|
 * @since 2.0 | 
						|
 */ | 
						|
abstract class Cache extends Component implements \ArrayAccess | 
						|
{ | 
						|
	/** | 
						|
	 * @var string a string prefixed to every cache key so that it is unique. Defaults to null, meaning using | 
						|
	 * the value of [[Application::id]] as the key prefix. You may set this property to be an empty string | 
						|
	 * if you don't want to use key prefix. It is recommended that you explicitly set this property to some | 
						|
	 * static value if the cached data needs to be shared among multiple applications. | 
						|
	 */ | 
						|
	public $keyPrefix; | 
						|
	/** | 
						|
	 * @var array|boolean the functions used to serialize and unserialize cached data. Defaults to null, meaning | 
						|
	 * using the default PHP `serialize()` and `unserialize()` functions. If you want to use some more efficient | 
						|
	 * serializer (e.g. [igbinary](http://pecl.php.net/package/igbinary)), you may configure this property with | 
						|
	 * a two-element array. The first element specifies the serialization function, and the second the deserialization | 
						|
	 * function. If this property is set false, data will be directly sent to and retrieved from the underlying | 
						|
	 * cache component without any serialization or deserialization. You should not turn off serialization if | 
						|
	 * you are using [[Dependency|cache dependency]], because it relies on data serialization. | 
						|
	 */ | 
						|
	public $serializer; | 
						|
 | 
						|
 | 
						|
	/** | 
						|
	 * Initializes the application component. | 
						|
	 * This method overrides the parent implementation by setting default cache key prefix. | 
						|
	 */ | 
						|
	public function init() | 
						|
	{ | 
						|
		parent::init(); | 
						|
		if ($this->keyPrefix === null) { | 
						|
			$this->keyPrefix = \Yii::$app->id; | 
						|
		} | 
						|
	} | 
						|
 | 
						|
	/** | 
						|
	 * Builds a normalized cache key from a given key. | 
						|
	 * | 
						|
	 * The generated key contains letters and digits only, and its length is no more than 32. | 
						|
	 *  | 
						|
	 * If the given key is a string containing alphanumeric characters only and no more than 32 characters, | 
						|
	 * then the key will be returned back without change. Otherwise, a normalized key | 
						|
	 * is generated by serializing the given key and applying MD5 hashing. | 
						|
	 *  | 
						|
	 * The following example builds a cache key using three parameters: | 
						|
	 * | 
						|
	 * ~~~ | 
						|
	 * $key = $cache->buildKey(array($className, $method, $id)); | 
						|
	 * ~~~ | 
						|
	 * | 
						|
	 * @param array|string $key the key to be normalized | 
						|
	 * @return string the generated cache key | 
						|
	 */ | 
						|
	public function buildKey($key) | 
						|
	{ | 
						|
		if (is_string($key)) { | 
						|
			return ctype_alnum($key) && StringHelper::strlen($key) <= 32 ? $key : md5($key); | 
						|
		} else { | 
						|
			return md5(json_encode($key)); | 
						|
		} | 
						|
	} | 
						|
 | 
						|
	/** | 
						|
	 * Retrieves a value from cache with a specified key. | 
						|
	 * @param string $key a key identifying the cached value | 
						|
	 * @return mixed the value stored in cache, false if the value is not in the cache, expired, | 
						|
	 * or the dependency associated with the cached data has changed. | 
						|
	 */ | 
						|
	public function get($key) | 
						|
	{ | 
						|
		$key = $this->keyPrefix . $this->buildKey($key); | 
						|
		$value = $this->getValue($key); | 
						|
		if ($value === false || $this->serializer === false) { | 
						|
			return $value; | 
						|
		} elseif ($this->serializer === null) { | 
						|
			$value = unserialize($value); | 
						|
		} else { | 
						|
			$value = call_user_func($this->serializer[1], $value); | 
						|
		} | 
						|
		if (is_array($value) && !($value[1] instanceof Dependency && $value[1]->getHasChanged())) { | 
						|
			return $value[0]; | 
						|
		} else { | 
						|
			return false; | 
						|
		} | 
						|
	} | 
						|
 | 
						|
	/** | 
						|
	 * Retrieves multiple values from cache with the specified keys. | 
						|
	 * Some caches (such as memcache, apc) allow retrieving multiple cached values at the same time, | 
						|
	 * which may improve the performance. In case a cache does not support this feature natively, | 
						|
	 * this method will try to simulate it. | 
						|
	 * @param array $keys list of keys identifying the cached values | 
						|
	 * @return array list of cached values corresponding to the specified keys. The array | 
						|
	 * is returned in terms of (key, value) pairs. | 
						|
	 * If a value is not cached or expired, the corresponding array value will be false. | 
						|
	 */ | 
						|
	public function mget($keys) | 
						|
	{ | 
						|
		$keyMap = array(); | 
						|
		foreach ($keys as $key) { | 
						|
			$keyMap[$key] = $this->keyPrefix . $this->buildKey($key); | 
						|
		} | 
						|
		$values = $this->getValues(array_values($keyMap)); | 
						|
		$results = array(); | 
						|
		foreach ($keyMap as $key => $newKey) { | 
						|
			$results[$key] = false; | 
						|
			if (isset($values[$newKey])) { | 
						|
				if ($this->serializer === false) { | 
						|
					$results[$key] = $values[$newKey]; | 
						|
				} else { | 
						|
					$value = $this->serializer === null ? unserialize($values[$newKey]) | 
						|
							: call_user_func($this->serializer[1], $values[$newKey]); | 
						|
 | 
						|
					if (is_array($value) && !($value[1] instanceof Dependency && $value[1]->getHasChanged())) { | 
						|
						$results[$key] = $value[0]; | 
						|
					} | 
						|
				} | 
						|
			} | 
						|
		} | 
						|
		return $results; | 
						|
	} | 
						|
 | 
						|
	/** | 
						|
	 * Stores a value identified by a key into cache. | 
						|
	 * If the cache already contains such a key, the existing value and | 
						|
	 * expiration time will be replaced with the new ones, respectively. | 
						|
	 * | 
						|
	 * @param string $key the key identifying the value to be cached | 
						|
	 * @param mixed $value the value to be cached | 
						|
	 * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire. | 
						|
	 * @param Dependency $dependency dependency of the cached item. If the dependency changes, | 
						|
	 * the corresponding value in the cache will be invalidated when it is fetched via [[get()]]. | 
						|
	 * This parameter is ignored if [[serializer]] is false. | 
						|
	 * @return boolean whether the value is successfully stored into cache | 
						|
	 */ | 
						|
	public function set($key, $value, $expire = 0, $dependency = null) | 
						|
	{ | 
						|
		if ($dependency !== null && $this->serializer !== false) { | 
						|
			$dependency->evaluateDependency(); | 
						|
		} | 
						|
		if ($this->serializer === null) { | 
						|
			$value = serialize(array($value, $dependency)); | 
						|
		} elseif ($this->serializer !== false) { | 
						|
			$value = call_user_func($this->serializer[0], array($value, $dependency)); | 
						|
		} | 
						|
		$key = $this->keyPrefix . $this->buildKey($key); | 
						|
		return $this->setValue($key, $value, $expire); | 
						|
	} | 
						|
 | 
						|
	/** | 
						|
	 * Stores a value identified by a key into cache if the cache does not contain this key. | 
						|
	 * Nothing will be done if the cache already contains the key. | 
						|
	 * @param string $key the key identifying the value to be cached | 
						|
	 * @param mixed $value the value to be cached | 
						|
	 * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire. | 
						|
	 * @param Dependency $dependency dependency of the cached item. If the dependency changes, | 
						|
	 * the corresponding value in the cache will be invalidated when it is fetched via [[get()]]. | 
						|
	 * This parameter is ignored if [[serializer]] is false. | 
						|
	 * @return boolean whether the value is successfully stored into cache | 
						|
	 */ | 
						|
	public function add($key, $value, $expire = 0, $dependency = null) | 
						|
	{ | 
						|
		if ($dependency !== null && $this->serializer !== false) { | 
						|
			$dependency->evaluateDependency(); | 
						|
		} | 
						|
		if ($this->serializer === null) { | 
						|
			$value = serialize(array($value, $dependency)); | 
						|
		} elseif ($this->serializer !== false) { | 
						|
			$value = call_user_func($this->serializer[0], array($value, $dependency)); | 
						|
		} | 
						|
		$key = $this->keyPrefix . $this->buildKey($key); | 
						|
		return $this->addValue($key, $value, $expire); | 
						|
	} | 
						|
 | 
						|
	/** | 
						|
	 * Deletes a value with the specified key from cache | 
						|
	 * @param string $key the key of the value to be deleted | 
						|
	 * @return boolean if no error happens during deletion | 
						|
	 */ | 
						|
	public function delete($key) | 
						|
	{ | 
						|
		$key = $this->keyPrefix . $this->buildKey($key); | 
						|
		return $this->deleteValue($key); | 
						|
	} | 
						|
 | 
						|
	/** | 
						|
	 * Deletes all values from cache. | 
						|
	 * Be careful of performing this operation if the cache is shared among multiple applications. | 
						|
	 * @return boolean whether the flush operation was successful. | 
						|
	 */ | 
						|
	public function flush() | 
						|
	{ | 
						|
		return $this->flushValues(); | 
						|
	} | 
						|
 | 
						|
	/** | 
						|
	 * Retrieves a value from cache with a specified key. | 
						|
	 * This method should be implemented by child classes to retrieve the data | 
						|
	 * from specific cache storage. | 
						|
	 * @param string $key a unique key identifying the cached value | 
						|
	 * @return string|boolean the value stored in cache, false if the value is not in the cache or expired. | 
						|
	 */ | 
						|
	abstract protected function getValue($key); | 
						|
 | 
						|
	/** | 
						|
	 * Stores a value identified by a key in cache. | 
						|
	 * This method should be implemented by child classes to store the data | 
						|
	 * in specific cache storage. | 
						|
	 * @param string $key the key identifying the value to be cached | 
						|
	 * @param string $value the value to be cached | 
						|
	 * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire. | 
						|
	 * @return boolean true if the value is successfully stored into cache, false otherwise | 
						|
	 */ | 
						|
	abstract protected function setValue($key, $value, $expire); | 
						|
 | 
						|
	/** | 
						|
	 * Stores a value identified by a key into cache if the cache does not contain this key. | 
						|
	 * This method should be implemented by child classes to store the data | 
						|
	 * in specific cache storage. | 
						|
	 * @param string $key the key identifying the value to be cached | 
						|
	 * @param string $value the value to be cached | 
						|
	 * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire. | 
						|
	 * @return boolean true if the value is successfully stored into cache, false otherwise | 
						|
	 */ | 
						|
	abstract protected function addValue($key, $value, $expire); | 
						|
 | 
						|
	/** | 
						|
	 * Deletes a value with the specified key from cache | 
						|
	 * This method should be implemented by child classes to delete the data from actual cache storage. | 
						|
	 * @param string $key the key of the value to be deleted | 
						|
	 * @return boolean if no error happens during deletion | 
						|
	 */ | 
						|
	abstract protected function deleteValue($key); | 
						|
 | 
						|
	/** | 
						|
	 * Deletes all values from cache. | 
						|
	 * Child classes may implement this method to realize the flush operation. | 
						|
	 * @return boolean whether the flush operation was successful. | 
						|
	 */ | 
						|
	abstract protected function flushValues(); | 
						|
 | 
						|
	/** | 
						|
	 * Retrieves multiple values from cache with the specified keys. | 
						|
	 * The default implementation calls [[getValue()]] multiple times to retrieve | 
						|
	 * the cached values one by one. If the underlying cache storage supports multiget, | 
						|
	 * this method should be overridden to exploit that feature. | 
						|
	 * @param array $keys a list of keys identifying the cached values | 
						|
	 * @return array a list of cached values indexed by the keys | 
						|
	 */ | 
						|
	protected function getValues($keys) | 
						|
	{ | 
						|
		$results = array(); | 
						|
		foreach ($keys as $key) { | 
						|
			$results[$key] = $this->getValue($key); | 
						|
		} | 
						|
		return $results; | 
						|
	} | 
						|
 | 
						|
	/** | 
						|
	 * Returns whether there is a cache entry with a specified key. | 
						|
	 * This method is required by the interface ArrayAccess. | 
						|
	 * @param string $key a key identifying the cached value | 
						|
	 * @return boolean | 
						|
	 */ | 
						|
	public function offsetExists($key) | 
						|
	{ | 
						|
		return $this->get($key) !== false; | 
						|
	} | 
						|
 | 
						|
	/** | 
						|
	 * Retrieves the value from cache with a specified key. | 
						|
	 * This method is required by the interface ArrayAccess. | 
						|
	 * @param string $key a key identifying the cached value | 
						|
	 * @return mixed the value stored in cache, false if the value is not in the cache or expired. | 
						|
	 */ | 
						|
	public function offsetGet($key) | 
						|
	{ | 
						|
		return $this->get($key); | 
						|
	} | 
						|
 | 
						|
	/** | 
						|
	 * Stores the value identified by a key into cache. | 
						|
	 * If the cache already contains such a key, the existing value will be | 
						|
	 * replaced with the new ones. To add expiration and dependencies, use the [[set()]] method. | 
						|
	 * This method is required by the interface ArrayAccess. | 
						|
	 * @param string $key the key identifying the value to be cached | 
						|
	 * @param mixed $value the value to be cached | 
						|
	 */ | 
						|
	public function offsetSet($key, $value) | 
						|
	{ | 
						|
		$this->set($key, $value); | 
						|
	} | 
						|
 | 
						|
	/** | 
						|
	 * Deletes the value with the specified key from cache | 
						|
	 * This method is required by the interface ArrayAccess. | 
						|
	 * @param string $key the key of the value to be deleted | 
						|
	 */ | 
						|
	public function offsetUnset($key) | 
						|
	{ | 
						|
		$this->delete($key); | 
						|
	} | 
						|
}
 | 
						|
 |