Как стать автором
Обновить

Интересный подход для кэширования моделей

Время на прочтение 3 мин
Количество просмотров 1.6K
На днях я получил задание реализовать кэширование в моделях. В обсуждениях с коллегами родилась довольно интересная, на мой взгляд, идея, которую я бы хотел выставить на ваш суд.

Реализация идеи на Zend Framework:
1. Все модели наследуются от нашего класса My_Db_Table_Abstract:
class My_Model_ModuleSettings extends My_Db_Table_Abstract

2. Который в свою очередь наследуется от Zend_Db_Table_Abstract:
class My_Db_Table_Abstract extends Zend_Db_Table_Abstract

3. В базовом для всех моделей классе My_Db_Table_Abstract описываем магический метод __call():
public function __call($name, $arguments)
{
  /** If call cached method */
  if (preg_match('/^cached_(.+)$/', $name, $methodName)&&method_exists($this,$methodName[1])) {
    /** Get cache instance */
    $cache = My_Cache::getInstance();
    /** Get arguments hash */      
    $argHash = md5(print_r($arguments, true));      
    /** Get model class name */
    $className = get_class($this);
    /** If method result don't cached */
    if (!$result = $cache->load('model_'.$className.'_'.$methodName[1].'_'.$argHash)) {
      $result = call_user_method_array($methodName[1], $this, $arguments);
      $cache->save($result,
                   'model_'.$className.'_'.$methodName[1].'_'.$argHash,
                   array('model',$className,$methodName[1]));
    }
    return $result;
  } else {
    /** Generate exception */
    throw new Exception('Call to undefined method '.$name);
  }
}


Теперь у нас появилась возможность использовать методы моделей двумя способами:
1. Не кэшируя, просто обратившись к методу:
$result = $this->_life->getAll('Now!!');

2. Кэшируя, дописав к имени метода префикс «cached_»:
$result = $this->_life->cached_getAll('Now!!');


Во втором случае, обращаясь к несуществующему методу, срабатывает метод __call(), в котором проверяется наличие закэшированного результата. Если результат выполнения метода закеширован — используется кэш, если нет — вызывается метод и полученный результат кэшируется.

Некоторые нюансы:
1. Для того чтобы кэш результата выполнения метода был разный при отличающихся параметрах метода я сделал хеширование параметров:
$argHash = md5(print_r($arguments));
Это, пожалуй, самый неоднозначный момент, т.к. я не могу точно сказать, как это может повлиять на производительность (при тестировании увеличение нагрузки замечено не было). При этом можно использовать разные функции хеширования(md5(),sha1()..) и разные способы приведения массива переменных к строковому типу (print_r(), var_dump(), implode()).

2. Имя кэшируемого файла имеет вид model_ИмяКласса_ИмяМетода_ХэшПараметров, исключая возможность совпадения.

3. Кэш помечается тегами 'model', 'className' и 'methodName', которые позволяют легко манипулировать очисткой. Вот для примера очистка кэша всех методов модели My_Model_ModuleSettings:
$cache->clean(
  Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG,
  array('My_Model_ModuleSettings')
);


Очень хотелось бы услышать ваши комментарии… Какие вы видите недостатки этого способа? Имеет ли он право на жизнь?
Теги:
Хабы:
+11
Комментарии 55
Комментарии Комментарии 55

Публикации

Истории

Ближайшие события

PG Bootcamp 2024
Дата 16 апреля
Время 09:30 – 21:00
Место
Минск Онлайн
EvaConf 2024
Дата 16 апреля
Время 11:00 – 16:00
Место
Москва Онлайн
Weekend Offer в AliExpress
Дата 20 – 21 апреля
Время 10:00 – 20:00
Место
Онлайн