Перейти до вмісту
Пошук в
  • Детальніше...
Шукати результати, які ...
Шукати результати в ...

Кэш. Class Cache. Проблема с генерацией непонятной строки


Recommended Posts

Здравствуйте, форумчане!

 

Есть файл контроллера, в котором запрашивается кэш:

$product_data = $this->cache->get('product.total.' . (int)$this->config->get('config_language_id') . '.' . (int)$this->config->get('config_store_id') . '.' . (int)$customer_group_id . '.' . $cache);

Есть системный класс Cache, в котором есть метод get.

 

 

Проблема в том, что из файла контроллера запрашивается строка вида "product.total.1.0.1.$cache" (где $cache - это некая сгенерированная строка). А в метод get класса Cache приходит непонятно почему такая строка: "product.total.1.0.1.cfcd208495d565ef66e7dff9f98764da.$cache".

 

Ссылка $this в файле контроллера ссылается на объект $registry класса Registry, в нем зарегистрирован экземпляр класса Cache. Т.е. вроде бы все нормально.

 

При этом метод set класса Cache записывает кэш как и положено - в виде файла с именем "product.total.1.0.1.$cache". Т.е. сейчас кэш для файлов "product.total.1.0.1.*" вообще не используется и CMS постоянно обращается к БД.

 

Временно метод get класса Cache изменил так:

	public function get($key) {
		if(preg_match('/^product\.total\.1\.0\.1\.cfcd208495d565ef66e7dff9f98764da.*$/', $key))
		{
			$key = str_replace('cfcd208495d565ef66e7dff9f98764da.', '', $key);
		}

	// ...

	}

Кто-нибудь с таким сталкивался и откуда и почему вставляетяс строка "cfcd208495d565ef66e7dff9f98764da" в имя файла кэша?

 

Спасибо.

Надіслати
Поділитися на інших сайтах


$cache = '1.0.1.cfcd208495d565ef66e7dff9f98764da' ;

Все правильно работает.

1. Напишите полный код класса Cache под спойлером.

2. И код контроллера, который запрашивает данные из кэша.

3. Как определили, что кэш не используется?

Надіслати
Поділитися на інших сайтах

1. Код класса Cache

<?php
class Cache { 
	private $expire = 3600; 

	public function get($key) {
		if(preg_match('/^product\.total\.1\.0\.1\.cfcd208495d565ef66e7dff9f98764da.*$/', $key))
		{
			$key = str_replace('cfcd208495d565ef66e7dff9f98764da.', '', $key);
			//echo $key , "<br/>\r\n";
		}
		$files = glob(DIR_CACHE . 'cache.' . preg_replace('/[^A-Z0-9\._-]/i', '', $key) . '.*');
		
		if ($files) {
			$cache = file_get_contents($files[0]);
			
			$data = unserialize($cache);
			
			foreach ($files as $file) {
				$time = substr(strrchr($file, '.'), 1);

      			if ($time < time()) {
					if (file_exists($file)) {
						unlink($file);
					}
      			}
    		}
			
			return $data;			
		}
	}

  	public function set($key, $value) {
    	$this->delete($key);
		
		$file = DIR_CACHE . 'cache.' . preg_replace('/[^A-Z0-9\._-]/i', '', $key) . '.' . (time() + $this->expire);
    	
		$handle = fopen($file, 'w');

    	fwrite($handle, serialize($value));
		
    	fclose($handle);
  	}
	
  	public function delete($key) {
		$files = glob(DIR_CACHE . 'cache.' . preg_replace('/[^A-Z0-9\._-]/i', '', $key) . '.*');
		
		if ($files) {
    		foreach ($files as $file) {
      			if (file_exists($file)) {
					unlink($file);
				}
    		}
		}
  	}
}
?>

 

2. Модель, не контроллер. Вот код метода:

<?php
	public function getTotalProducts($data = array()) {
		if ($this->customer->isLogged()) {
			$customer_group_id = $this->customer->getCustomerGroupId();
		} else {
			$customer_group_id = $this->config->get('config_customer_group_id');
		}	
				
		$cache = md5(http_build_query($data));
		
		$product_data = $this->cache->get('product.total.' . (int)$this->config->get('config_language_id') . '.' . (int)$this->config->get('config_store_id') . '.' . (int)$customer_group_id . '.' . $cache);
		
		if (!$product_data and $product_data === NULL) {
			
			$sql = "SELECT COUNT(DISTINCT p.product_id) AS total FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id)";
	
			if (!empty($data['filter_category_id'])) {
				$sql .= " LEFT JOIN " . DB_PREFIX . "product_to_category p2c ON (p.product_id = p2c.product_id)";			
			}
						
			$sql .= " WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'";
			
			if (!empty($data['filter_name']) || !empty($data['filter_tag'])) {
				$sql .= " AND (";
				
				if (!empty($data['filter_name'])) {					
					if (!empty($data['filter_description'])) {
						$sql .= "LCASE(pd.name) LIKE '%" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "%' OR MATCH(pd.description) AGAINST('" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "')";
					} else {
						$sql .= "LCASE(pd.name) LIKE '%" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "%'";
					}
				}
				
				if (!empty($data['filter_name']) && !empty($data['filter_tag'])) {
					$sql .= " OR ";
				}
				
				if (!empty($data['filter_tag'])) {
					$sql .= "MATCH(pd.tag) AGAINST('" . $this->db->escape(utf8_strtolower($data['filter_tag'])) . "')";
				}
			
				$sql .= ")";
				
				if (!empty($data['filter_name'])) {
					$sql .= " OR LCASE(p.model) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
				}
				
				if (!empty($data['filter_name'])) {
					$sql .= " OR LCASE(p.sku) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
				}	
				
				if (!empty($data['filter_name'])) {
					$sql .= " OR LCASE(p.upc) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
				}		

				if (!empty($data['filter_name'])) {
					$sql .= " OR LCASE(p.ean) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
				}

				if (!empty($data['filter_name'])) {
					$sql .= " OR LCASE(p.jan) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
				}
				
				if (!empty($data['filter_name'])) {
					$sql .= " OR LCASE(p.isbn) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
				}		
				
				if (!empty($data['filter_name'])) {
					$sql .= " OR LCASE(p.mpn) = '" . $this->db->escape(utf8_strtolower($data['filter_name'])) . "'";
				}				
			}
						
			if (!empty($data['filter_category_id'])) {
				if (!empty($data['filter_sub_category'])) {
					$implode_data = array();
					
					$implode_data[] = (int)$data['filter_category_id'];
					
					$this->load->model('catalog/category');
					
					$categories = $this->model_catalog_category->getCategoriesByParentId($data['filter_category_id']);
										
					foreach ($categories as $category_id) {
						$implode_data[] = (int)$category_id;
					}
								
					$sql .= " AND p2c.category_id IN (" . implode(', ', $implode_data) . ")";			
				} else {
					$sql .= " AND p2c.category_id = '" . (int)$data['filter_category_id'] . "'";
				}
			}		
			
			if (!empty($data['filter_manufacturer_id'])) {
				$sql .= " AND p.manufacturer_id = '" . (int)$data['filter_manufacturer_id'] . "'";
			}
			
			$query = $this->db->query($sql);
			
			$product_data = $query->row['total']; 
			
			$this->cache->set('product.total.' . (int)$this->config->get('config_language_id') . '.' . (int)$this->config->get('config_store_id') . '.' . (int)$customer_group_id . '.' . $cache, $product_data);
		}
		
		return $product_data;
	}

 

3. Изначальная причина была в том, что сайт работал медленно. Системный администратор, потом и я, проверил нагрузку на сервер - нагрузка на сервер действительно была очень большой (не такой, какой должна была быть при работе с кэшем). Была поставлена мне задача. Посмотрел папку с кэшем - кэш создается под одним именем, а запрашивается под другим (в следствие чего создается новый запрос к БД и сайт работает медленно, а сервер под нагрузкой).

 

---------------------------

 

Откуда инфа, что $cache = '1.0.1.cfcd208495d565ef66e7dff9f98764da' ? Эта переменная вообще по-другому формируется.

 

В модели выводил на экран передаваемый текст - был один вариант (собственно, под каким и сохранялся кэш), а в метод класса приходит уже другой (а кэша с таким именем уже нет)!

При том такой запрос кэша формируется только в этом методе и только в этой модели! Т.е. только для кэшей которые начинаются с product.total.1.0.1.*.

Надіслати
Поділитися на інших сайтах


Да, ошибся:

$cache = md5(http_build_query($data)); //cfcd208495d565ef66e7dff9f98764da

Значит имя файла кэша cache.product.total.1.0.1.cfcd208495d565ef66e7dff9f98764da.$UTC. 

if (!$product_data and $product_data === NULL) {
//замените на 
if (empty($product_data)) {

Пришлите в ЛС данные для доступа к магазину или сорцы с БД на [email protected], я посмотрю. 

Надіслати
Поділитися на інших сайтах

Пришлите в ЛС данные для доступа к магазину или сорцы с БД на [email protected], я посмотрю. 

 

К сожалению, это невозможно.

 

debug_backtrace'ом выяснил, что среди прочих вызывается файл "/vqmod/vqcache/vq2-catalog_model_catalog_product.php" и в нем вызывается тот самый метод класса, но строка к кэшу формируется уже по-другому:

// Start filter change
	    $product_data = $this->cache->get('product.total.' . (int)$this->config->get('config_language_id') . '.' . (int)$this->config->get('config_store_id') . '.' . (int)$customer_group_id . '.'.md5($filter). '.'. $cache); 
// End filter

Сравните с исходным запросом:

$product_data = $this->cache->get('product.total.' . (int)$this->config->get('config_language_id') . '.' . (int)$this->config->get('config_store_id') . '.' . (int)$customer_group_id . '.' . $cache);

 

Т.е. как раз тут и вставляется эта злополучная строка прямо посреди текста - " .md5($filter). ".

 

С vQmod никогда не работал. Как наиболее правильно исправить такую работу этого мода? Или ничего страшного, ели вмешаться в код напрямую?

Надіслати
Поділитися на інших сайтах


Проблема в файле скрипта vQmod '/vqmod/xml/vqmod_filter_products.xml' :

 

	<operation>
            <search position="replace"><![CDATA[
            $product_data = $this->cache->get('product.total.' . (int)$this->config->get('config_language_id') . '.' . (int)$this->config->get('config_store_id') . '.' . (int)$customer_group_id . '.' . $cache);
            ]]></search>
            <add><![CDATA[
// Start filter change
	    $product_data = $this->cache->get('product.total.' . (int)$this->config->get('config_language_id') . '.' . (int)$this->config->get('config_store_id') . '.' . (int)$customer_group_id . '.'.md5($filter). '.'. $cache); 
// End filter
            ]]></add>
        </operation>

 

Переменная $filter всегда имеет значение int(0), следовательно, md5(0) имеем - "cfcd208495d565ef66e7dff9f98764da".

 

Следует просто переписать замещающий код? Из знающих vQmod никто не подскажет? Нужна ли вообще переменная $filter и в каких случаях?

Надіслати
Поділитися на інших сайтах


Проблема в файле скрипта vQmod '/vqmod/xml/vqmod_filter_products.xml' :

 

	<operation>
            <search position="replace"><![CDATA[
            $product_data = $this->cache->get('product.total.' . (int)$this->config->get('config_language_id') . '.' . (int)$this->config->get('config_store_id') . '.' . (int)$customer_group_id . '.' . $cache);
            ]]></search>
            <add><![CDATA[
// Start filter change
	    $product_data = $this->cache->get('product.total.' . (int)$this->config->get('config_language_id') . '.' . (int)$this->config->get('config_store_id') . '.' . (int)$customer_group_id . '.'.md5($filter). '.'. $cache); 
// End filter
            ]]></add>
        </operation>

 

Переменная $filter всегда имеет значение int(0), следовательно, md5(0) имеем - "cfcd208495d565ef66e7dff9f98764da".

 

Следует просто переписать замещающий код? Из знающих vQmod никто не подскажет? Нужна ли вообще переменная $filter и в каких случаях?

 

Это XML файл какого-то модуля фильтра, если этот фильтр не используется на сайте, то можете просто переименовать vqmod_filter_products.xml на vqmod_filter_products.xml.bak, при обновлении страницы vqmod его не обработает и файл /vqmod/vqcache/vq2-catalog_model_catalog_product.php примет прежний вид. 

Если же этот фильтр используется, то обратитесь к его автору. Если же понадобится помощь, то я уже писал ранее свои контакты.

Надіслати
Поділитися на інших сайтах

Створіть аккаунт або увійдіть для коментування

Ви повинні бути користувачем, щоб залишити коментар

Створити обліковий запис

Зареєструйтеся для отримання облікового запису. Це просто!

Зареєструвати аккаунт

Вхід

Уже зареєстровані? Увійдіть тут.

Вхід зараз

×
×
  • Створити...

Important Information

На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність.