Оптимизация OpenCart: Исправление работы кэша с количеством продуктов для категорий

Использование кэша в OpenCart позволяет сократить количество обращений к базе данных и увеличить быстродействие магазина, однако есть некоторые нюансы в работе самого кэша.

Управление кэшем происходит в файле ./system/library/cache.php, если обратить внимание на функцию get, то видно, что результат возвращается функцией php unserialize когда файл кэша есть и null, когда его нет. Это значит, что если в кэше сохранён результат пустой выборки в одной из моделей, то при очередном запросе кэша будет возвращён ноль.

Практически во всех моделях условие проверки кэша следующее:

$product_data = $this->cache->get( ...

if (!$product_data) { ...


что в корне неверно, так как содержание кэша, например, строка s:1:"0";, может сообщить модулю об его "отсутствии" и будет выполнено повторное обращение к базе.

Если создать новые категории, то это будет хорошо заметно. Товаров нет, каждый раз запрос из базы возвращает пустой результат и сохраняет его в кэше. В этом конкретном примере необходимо открыть файл ./catalog/model/catalog/product.php найти функцию getTotalProducts и в её теле заменить условие

if (!$product_data) { ... 


на

if ($product_data === null) { ...


Теперь существование кэша будет правильно воспринято отдельно взятой функцией того или иного модуля. Исправления актуальны для всех версий OpenCart, включая последнюю v1.5.5.1.

Update

Работая с библиотекой кэша ./system/library/cache.php обратил внимание, что принцип выдачи кэшированной информации организован неверно. Модулю, запросившему кэш, может быть выдана устаревшая информация, если обратите внимание на код, то данные с файла считываются раньше проверки на время.

Дабы не создавать отдельную статью, приведу решение здесь. Функцию get() необходимо заменить на код ниже.

 public function get($key) { 
  $data = null;
  $files = glob(DIR_CACHE . 'cache.' . preg_replace('/[^A-Z0-9\._-]/i', '', $key) . '.*');
  if ($files) { 
   for ($n=0, $lenght = count($files); $n < $lenght; $n++) {    
    $file = $files[$n];
    $time = substr(strrchr($file, '.'), 1);
         if ($time < time()) {
     if (file_exists($file)) { unlink($file); } 
         } elseif (!$n) { $cache = file_get_contents($file); $data = unserialize($cache);
    }  }  }  return $data;  }


Кстати, обновлённная функция работает немного быстрее, т.к. используется цикл for next (призываю использовать в PHP вместо foreach везде) и unserialize выполняется не по умолчанию, а только если кэш не устарел.
Теги:
CACHE, GETTOTALPRODUCTS, OPENCART V.1.5+, OPTIMIZATION, UNSERIALIZE
Добавлено: 25 Февраля 2015 20:16:41 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...