Совсем недавно стала задача организовать кэширование данных. И получилась весьма удобная вещь. Реализацию смотри под хабракатом…
Описанный ниже абстрактный класс кладем к нашим моделям в папку Cache. В моём случае это /Default/Models/Cache/Abstract.php
Описанный ниже абстрактный класс кладем к нашим моделям в папку Cache. В моём случае это /Default/Models/Cache/Abstract.php
abstract class Default_Models_Cache_Abstract
{
protected static $_cache = null;
protected static $_staticCache = null;
protected static $_tags = null;
protected static $_className = null;
protected static $_frontendName = 'Class';
protected static $_backendName = 'File';
protected static $_frontendOptions = array();
protected static $_backendOptions = array();
public function __construct()
{
self::_init();
}
public function __call($name, $arguments)
{
return self::_call($name, $arguments);
}
public static function __callStatic($name, $arguments)
{
return self::_call($name, $arguments, true);
}
protected static function _initConfig()
{
static $inited = null;
if (null === $inited) {
if (null === static::$_className) {
throw new Exception("You must provide a protected static"
. " \$_className = ...; statement in your class!");
}
self::$_backendName = 'File';
self::$_frontendName = 'class';
self::$_frontendOptions = array();
self::$_backendOptions = array();
$inited = true;
}
}
protected static function _init($useStatic = false)
{
$ref = null;
if ($useStatic && null === self::$_staticCache) {
$ref = static::$_className;
} elseif (null === self::$_cache) {
if (!class_exists(static::$_className)) {
require_once 'Zend/Loader.php';
Zend_Loader::loadClass(static::$_className);
}
$ref = new static::$_className;
}
if (null !== $ref) {
self::_initConfig();
self::$_tags = array(static::$_className);
self::$_frontendOptions['cached_entity'] = $ref;
$cache = Zend_Cache::factory(
self::$_frontendName,
self::$_backendName,
self::$_frontendOptions,
self::$_backendOptions
);
if ($useStatic) {
self::$_staticCache = $cache;
} else {
self::$_cache = $cache;
}
}
}
protected static function _generateId($methodName, $arguments)
{
return sha1($methodName . print_r($arguments, true));
}
protected static function _call($name, $arguments, $useStatic = false)
{
self::_init($useStatic);
$id = self::_generateId($name, $arguments);
if ($useStatic) {
$cache = self::$_staticCache;
} else {
$cache = self::$_cache;
}
if (!($result = $cache->load($id))) {
$result = $cache->__call($name, $arguments);
$cache->save(
$result,
$id,
self::$_tags
);
}
return $result;
}
public function cleanCache()
{
$ids = self::$_cache->getIdsMatchingTags();
foreach($ids as $id) {
self::$_cache->remove($id);
}
self::$_cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, self::$_tags);
}
}
Для его работы необходимо иметь рабочую модель, например Default_Models_Products.
В папке Cache, относительно файла нашей модели, создаем класс Default_Models_Cache_Products с одним свойством:
class Default_Models_Cache_Products extends Default_Models_Cache_Abstract
{
protected static $_className = 'Default_Models_Products';
}
Все обращения к классу Default_Models_Products заменяем на Default_Models_Cache_Products, работаем с ним также как и с Default_Models_Products.
Например, в нашей моделе реализован метод getList.
class Default_Models_Products
{
...
public function getList()
{
$productsTable = new Default_Models_Table_Products;
return $productsTable->fetchAll()->toArray();
}
Получить данные мы можем следующим образом:
$productsModel = new Default_Models_Cache_Products();
$productList = $productsModel->getList();
Реализована также возможность вызова статических методов. Если метод getList является статическим, то вызвать его можно будет так:
$productList = Default_Models_Cache_Products::getList();
Очистку кэша можно произвести вызвав cleanCache(), в данном случае будет произведена очистка относящегося только к данной моделе, что может оказаться весьма полезным. Дабы не очищать весь кэш.
Про задание параметров $_frontendOptions и $_backendOptions можно почитать тут и тут
Получившийся класс весьма универсален и подойдет не только для моделей.