[ Pobierz całość w formacie PDF ]
.Also, if the complexity of the cache mechanism increases too much, its value isnullified.As with most things, picking the areas that give the greatest gains for theleast cost is a sound approach.Having said that, the complexity of the cache mechanisms described so far is notincreased much by making them more general.So, it is well worthwhile havinga general cache facility that can be used by any part of the CMS or any extensionwherever it seems appropriate.The general cache interface is described in thenext section.Framework SolutionWhile the motivation for a cache tends to go from the requirement down into themechanisms, it is easier to explain the workings of cache by starting at the bottom.[ 172 ]Chapter 8Abstract Cache ClassWe start with an abstract cache class.Although it cannot be instantiated, it providesthe actual mechanisms.Since it is quite short, it can be presented in full here:abstract class aliroBasicCache{protected $basepath = '';protected $sizelimit = 0;protected $timeout = 0;public function __construct(){$this->basepath = criticalInfo::getInstance()->absolute_path.'/cache/';}abstract protected function getCachePath($name);public function store ($object, $cachename=''){$path = $this->getCachePath($cachename ?$cachename : get_class($object));$object->aliroCacheTimer = time();$s = serialize($object);$s.= md5($s);if (strlen($s) > $this->sizelimit) return false;if (file_put_contents($path, $s, LOCK_EX)) return true;else return false;}public function retrieve ($class, $time_limit = 0){$path = $this->getCachePath($class);$string = file_exists($path) ? file_get_contents($path) : null;$s = substr($string, 0, -32);$object = ($s AND (md5($s) == substr($string, -32))) ?unserialize($s) : null;$time_limit = $time_limit ? $time_limit : $this->timeout;if (is_object($object) AND (time() - @$object->aliroCacheTimer)> $time_limit) $object = null;return $object;}}The constructor simply establishes the location of the general cache directory.Thenthere are two methods: one for storing to the cache, and another for retrieving fromthe cache.[ 173 ]Caches and HandlersWhen storing, the actual path including file name has to be figured out.This relieson the subclass providing a method getCachePath, something we can enforce bydeclaring the method here as abstract.The name of a cache can be supplied as aparameter, but if it is not, the default is to take the name of the class of the objectbeing stored.The object to be stored has the property aliroCacheTimer set to the current time,so that we will know when the data in this cache has expired.The object is thenserialized, and its own MD5 hash concatenated on to the end of the serialized objectfor validation.If the resulting data is too large (the size limit is set to a non-zerovalue in the subclass) and the store method returns false as an indication of failure.Finally, an attempt is made to store the data to the path figured out earlier, using filelocking to try to prevent data corruption in the event of two web server processeswriting to the cache at the same time.The result of the write is returned as the resultof the store operation.The retrieve method does much the same in reverse.An attempt is made to readthe cache data if the file exists; the MD5 hash is checked against the retrieved data,and if all is well so far, the object is reconstituted using PHP's unserialize.Testing the expiry of cache data is done in relation to either the passed $time_limitparameter, or to the object property $timeout, which is set to zero here simply toensure that it has a value.Normally, it will be given a non-zero value in the subclassthat extends this abstract class.If the stored data fails to pass the timeout test, thenthe retrieved object is made null.Singleton Object Cache ManagerWith the basic functionality established, we can build a singleton class that is able toprovide a cache service for handlers.It goes like this:class aliroSingletonObjectCache extends aliroBasicCache{protected static $instance = __CLASS__;protected $timeout = _ALIRO_OBJECT_CACHE_TIME_LIMIT;protected $sizelimit = _ALIRO_OBJECT_CACHE_SIZE_LIMIT;public static function getInstance(){return is_object(self::$instance) ? self::$instance :(self::$instance = new self::$instance);}protected function getCachePath($name){[ 174 ]Chapter 8return $this->basepath.'singleton/'
[ Pobierz całość w formacie PDF ]