Фильтр MEGA FILTER PRO. Управление опциями в opencart.

Постановка задачи:

Входные данные:

  1. В интернет магазине имеются несколько групп опций цветов
  2. CMS интернет магазина - opencart 1.5 или 2.0
  3. Установлен фильтр товаров MEGA FILTER PRO
Требуется сделать:

  • чтобы в фильтре отображались цвета только в одной группе.  Или же группы опций объединить в другом порядке для опций фильтра. Например в интернет магазине применяются опции в нескольких группах в соответсвии с брендами (производители), для фильтра эти группы будут объединены в одну группу.
  • имена цветов, отображаемые в фильтре отображались в другом виде... замена названия
  • была возможность отобразить группу фильтра в которой можно было бы отобразить наиболее востребованные цвета (товары с популярным цветом) из разных групп опций интернет магазина. Это необходимо в первую очередь для повышения юзабилити и конверсии

 Решение задачи:

Есть только три варианта решения задачи. 

  1. доработать сам фильтр MEGA, чтобы после выборки опций, данные из базы были переформатированы соответствующим образом
  2. изменить структуру опций в самой базе
  3. использовать возможности фильтра МЕГА и встроенных ресурсов opencart для фильтрации данных. А именно фильтры (таблица product_filter) 
Выбираем 3-й вариант, поскольку только он позволяет нам создать группу фильтра  популярные цвета. Кроме того при программировании, установке фильтра на заказ, желательно  не изменять устоявшуюся структуру опций.

Итак. Во-первых нам понадобится таблица перекодировки (замены названий) цветов. Ее мы создадим в отдельной таблице. Таблицу назовем mod_mega_option. Учитывая, что данную операцию придется проводить многократно, мы сведем ее соответственно в скрипт, который можно будет запускать по таймеру cron автоматически.

Скрипты php мы разместим в корневой папке seo. Это позволит при установке данного сервиса, просто скопировать папку в корневой каталог.

Для полноценной работы с базой интернет магазина нам понадобится конфигурационный файл, класс для работы с базой и другие необходимые константы и переменные. Зададим инициализацию скрипта:

<?phpsession_start();define('LIVE_SITE', "http://".$_SERVER['HTTP_HOST']);    define('ADR_SITE', $_SERVER['DOCUMENT_ROOT']);  define('ADR_LOG',$_SERVER['DOCUMENT_ROOT']."/seo/logs");                                                    require_once(ADR_SITE.'/seo/classes/mysql.class.php');require_once(ADR_SITE.'/config.php');db_connect(DB_HOSTNAME,DB_USERNAME,DB_PASSWORD) or die (db_error());db_select_db(DB_DATABASE) or die (db_error());?>


 Выгрузка списка опций в таблицу mod_mega_option:

Составим оператор SQL создания таблицы с определением необходимых нам полей:

CREATE TABLE `mod_mega_option` IF NOT EXISTS(  `mod_option_id` int(11) NOT NULL,  `option_value_id` int(11) NOT NULL,  `name` varchar(128) NOT NULL,  `name_filter` varchar(128) NOT NULL   `hit' int(8) NOT NULL,) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Здесь первые 3 поля не требуют пояснения. Поле name_filter - название опции (цвета в нашем случае) которое будет отображаться в фильтре. Поле hit нам необходимо для предварительного расчета спроса  (популярность) на данный цвет. Заметим, что второе поле ссылается на соответствующую опцию. 

Добавим в наш скрипт создание таблицы и выполним  наш скрипт. 

db_select_db(DB_DATABASE) or die (db_error());db_query("CREATE TABLE IF NOT EXISTS ".DB_PREFIX."mod_mega_option (mega_option_id int(11) NOT NULL, option_value_id int(11) NOT NULL, name varchar(128) NOT NULL, name_filter varchar(128) NOT NULL, status tinyint(1) NOT NULL '0', hit int(8) NOT NULL'0') ENGINE=MyISAM DEFAULT CHARSET=utf8;") or die (db_error());
Таблица создана. 
Следующий шаг, нам необходимо перегрузить в нашу таблицу опции и заполнить поле hit

Мы могли бы выбирать из таблицы базы магазина option_value_description только те поля, которых нет в нашей таблице, синхронизируясь по полю  option_value_id. Но предположим администраторы (менеджеры) изменили название опции или вовсе удалили ее. Значит необходимо полностью обновлять таблицу, а также проверять на существование опции.  

Для проверки существования опции, добавим поле status. Перед обновлением таблицы будем выключать все опции в нашей таблице, а затем включать найденные или добавленные. После обновления, удалим опции в нашей таблице у которых статус равен нулю.

Создание таблицы с полем status:

db_query("CREATE TABLE IF NOT EXISTS ".DB_PREFIX."mod_mega_option (mega_option_id int(11) NOT NULL AUTO_INCREMENT, option_value_id int(11) NOT NULL, name varchar(128) NOT NULL, name_filter varchar(128) NOT NULL, status tinyint(1) NOT NULL DEFAULT '0', hit int(8) NOT NULL, primary key (mega_option_id, option_value_id))  ENGINE=MyISAM DEFAULT CHARSET=utf8;") or die (db_error());
Заполним нашу таблицу опциями. Для удобства группы опций из магазина, которые необходимо объединить в фильтре,  мы добавим в строку запроса:
$option_id = $_GET['option_id'];
echo $option_id; 
$q_option = db_query("SELECT *  FROM ".DB_PREFIX."option_value_description WHERE option_id IN ('".$option_id."')");
	while($row_temp = db_get_row($q_option)) {
		$option_value_id =  $row_temp['option_value_id'];
		$option_id =  $row_temp['option_id'];
		$option_value_name =  $row_temp['name'];		
		//проверим есть ли в нашей таблице такая опция
		$q_option_mega = db_query("SELECT *  FROM ".DB_PREFIX."mod_mega_option WHERE option_value_id = '".(int)$option_value_id ."'");
		if(db_get_row($q_option_mega)) {			
			db_query("UPDATE ".DB_PREFIX."mod_mega_option SET status = 1, name = '".$option_value_name."' WHERE option_value_id = '".(int)$option_value_id ."'");
		} else {
			db_query("INSERT INTO ".DB_PREFIX."mod_mega_option SET option_value_id = '".$option_value_id."', option_id = '".$option_id."',status = 1, name = '".$option_value_name."', name_filter = '".$option_value_name."';");			
		}
	} 
В итоге опции из групп перечисленных в запросе будут записаны в нашу таблицу. По умолчанию поле name_filter мы также заполним названием опции из магазина, поскольку большая часть опций, или даже все могут совпадать с требуемым названием в фильтре. 

Создание фильтров opencart:

На этом этапе мы заполним фильтр опенкарт(таблица базы filter) из нашей таблицы значением поля name_filter. Так как мы хотим избежать повторения имен в фильтре mega, то мы будем проверять наличие совпадающих имен при добавлении в фильтр значения.

Через админку opencart создадим группу фильтра - Цвет. Эта группа и будет выдаваться в фильтре mega. Предположим что у нее код (идентификатор группы в таблице базы) = 1. В будущем желательно синхронизироваться по цвету.

Добавим в таблицу filter базы наши опции по группе Цвет с кодом = 1:

 //сформируем таблицу фильтра по группе цвет
$q_option = db_query("SELECT *  FROM ".DB_PREFIX."mod_mega_option WHERE option_id IN ('".$option_id."')");
	while($row_temp = db_get_row($q_option)) {
		$mega_option_id =  $row_temp['mega_option_id'];
		$name_filter =  $row_temp['name_filter'];		
		//проверим есть ли в таблице filter такая опция
		$q_option_filter = db_query("SELECT *  FROM ".DB_PREFIX."filter_description WHERE name = '".$name_filter."'");
		if(db_get_row($q_option_filter)) {			
		} else {
			db_query("INSERT INTO ".DB_PREFIX."filter SET filter_group_id = 1, sort_order = 100 ");		
			//получим последний id
			$query = db_query("SELECT LAST_INSERT_ID() AS liid;");
			$row_filter_id = db_get_row($query);
			$filter_id = $row_filter_id['liid'];			
			db_query("INSERT INTO ".DB_PREFIX."filter_description SET filter_id = '".$filter_id."', filter_group_id = 1, language_id = 1, name = '".$name_filter."'");			
		}
	}

В дальнейшем мы добавим также предварительное удаление фильтра по выбранной группе.

Мы сформировали фильтры с новым названием опций. Но теперь нам необходимо добавить эти фильтры к товарам.

Добавление фильтров в товары:

На этом этапе мы добавим созданные фильтры группы Цвет к товарам (таблица product_filter). Это возможно, если мы будем анализировать таблицу product_option_value и ко всем товарам, у которых поле option_value_id совпадет с нашей базой, добавим соответствующие по цвету фильтры:

//сформируем таблицу фильтра по группе цвет и добавим фильтры в товары
db_query("DELETE FROM ".DB_PREFIX."filter WHERE filter_group_id = 1 ");	
db_query("DELETE FROM ".DB_PREFIX."filter_description WHERE filter_group_id = 1 ");	
$q_option = db_query("SELECT *  FROM ".DB_PREFIX."mod_mega_option WHERE option_id IN ('".$option_id."')");
	while($row_temp = db_get_row($q_option)) {
		$mega_option_id =  $row_temp['mega_option_id'];
		$name_filter =  $row_temp['name_filter'];	
		$option_value_id = $row_temp['option_value_id']; 	
		//проверим есть ли в таблице filter такая опция
		$q_option_filter = db_query("SELECT *  FROM ".DB_PREFIX."filter_description WHERE name = '".$name_filter."'");
		if(db_get_row($q_option_filter)) {	
			//получим id 
			$row_option_filter = db_get_row($q_option_filter);
			$filter_id = $row_option_filter['filter_id'];
		} else {
			db_query("INSERT INTO ".DB_PREFIX."filter SET filter_group_id = 1, sort_order = 100 ");		
			//получим последний id
			$query = db_query("SELECT LAST_INSERT_ID() AS liid;");
			$row_filter_id = db_get_row($query);
			$filter_id = $row_filter_id['liid'];			
			db_query("INSERT INTO ".DB_PREFIX."filter_description SET filter_id = '".$filter_id."', filter_group_id = 1, language_id = 1, name = '".$name_filter."'");			
		}	
		//Добавим фильтр к товару у которых есть соответствующая опция. 
		echo $name_filter."<br>";
		$q_product = db_query("SELECT *  FROM ".DB_PREFIX."product_option_value pov LEFT JOIN ".DB_PREFIX."product_description pd ON (pov.product_id = pd.product_id) WHERE option_value_id = '".(int)$option_value_id."'");
		while($row_product_temp = db_get_row($q_product)) {
				echo "  ".$row_product_temp['name']."<br>"; 
				db_query("INSERT IGNORE INTO ".DB_PREFIX."product_filter SET product_id = '".(int)$row_product_temp['product_id']."', filter_id = '".(int)$filter_id."'");	
		}
	}	
Задача решена!!!
В фильтре MEGA FILTER PRO появилась группа цвет, в которой объединены несколько групп  опций с цветами.
Понятно то данный механизм применим не только для фильтра мега, но и для любого фильтра, в том числе и для встроенного фильтра в opencart.
В следующей статье мы доработаем наш скрипт для более общих решений - объединение любых опций и сервисные модули для редактирования таблиц с именами.