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