Тут же я. Извиняюсь за опоздание, но я решил сделать полноценный модуль и не с фиксированными опциями, как у меня в примерах, а изменяемыми / дополняемыми из админки. При чем в базу данных для этого лезть не надо. Всё автоматизированно. И еще, сюда же включил AJAX листалку в категории и AJAX сортировку. Всё это активируется после первого изменения параметров фильтра со стороны пользователя за время нахождения в категории.
Опишу ф-ции модуля Opencart Product Filter 1.0 :-) :
добавление опций фильтра и значений к ним
указание сортировки опций
указание одной или нескольких категорий, в которых будет действовать данная опция
поддержка мультиязычности
указание опций фильтра на странице редактирования товара. В зависимости от выбранных категорий, во вкладку Опции фильтра будут подгружаться на лету опции этой категории.
AJAX подгрузка товаров категории при изменении состояния фильтра.
Индикатор активности фильтра (громко сказано, просто jQuery анимация при любых действиях с input'ами фильтра).
Если что, пишите в асю, сюда редко захожу.
Буду рад выслушать замечания или предложения.
В следующей версии хочу сделать еще несколько типов полей фильтра: слайдер, слайдер-диапазон, текстовое поле.
Перейдем к установке:
Если у вас чистая система и вы еще ничего в её коде не изменяли, то качайте архив Openstore_module_product_filter_1.0_(clean_install).rar и просто извлеките файлы в корень с заменой и выполните запрос в базу данных
CREATE TABLE IF NOT EXISTS `category_option` ( `option_id` int(10) NOT NULL AUTO_INCREMENT, `type` int(1) DEFAULT '0', `sort_order` int(10) DEFAULT '0', PRIMARY KEY (`option_id`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;CREATE TABLE IF NOT EXISTS `category_option_description` ( `option_id` int(10) NOT NULL DEFAULT '0', `language_id` int(10) NOT NULL DEFAULT '0', `name` varchar(127) DEFAULT NULL, PRIMARY KEY (`option_id`,`language_id`), KEY `name` (`name`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;CREATE TABLE IF NOT EXISTS `category_option_to_category` ( `option_id` int(11) NOT NULL, `category_id` int(11) NOT NULL, PRIMARY KEY (`category_id`,`option_id`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;CREATE TABLE IF NOT EXISTS `category_option_value` ( `value_id` int(10) NOT NULL AUTO_INCREMENT, `option_id` int(10) DEFAULT '0', PRIMARY KEY (`value_id`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;CREATE TABLE IF NOT EXISTS `category_option_value_description` ( `value_id` int(10) NOT NULL DEFAULT '0', `language_id` int(10) NOT NULL DEFAULT '0', `option_id` int(10) NOT NULL DEFAULT '0', `name` varchar(127) DEFAULT NULL, PRIMARY KEY (`value_id`,`language_id`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;CREATE TABLE IF NOT EXISTS `product_to_value` ( `product_id` int(11) NOT NULL, `value_id` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`product_id`,`value_id`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;Если нет, то установка "вручную", или на систему, которая уже подвергалась изменениям в коде:1) Делаем запрос в базу данных
CREATE TABLE IF NOT EXISTS `category_option` ( `option_id` int(10) NOT NULL AUTO_INCREMENT, `type` int(1) DEFAULT '0', `sort_order` int(10) DEFAULT '0', PRIMARY KEY (`option_id`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;CREATE TABLE IF NOT EXISTS `category_option_description` ( `option_id` int(10) NOT NULL DEFAULT '0', `language_id` int(10) NOT NULL DEFAULT '0', `name` varchar(127) DEFAULT NULL, PRIMARY KEY (`option_id`,`language_id`), KEY `name` (`name`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;CREATE TABLE IF NOT EXISTS `category_option_to_category` ( `option_id` int(11) NOT NULL, `category_id` int(11) NOT NULL, PRIMARY KEY (`category_id`,`option_id`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;CREATE TABLE IF NOT EXISTS `category_option_value` ( `value_id` int(10) NOT NULL AUTO_INCREMENT, `option_id` int(10) DEFAULT '0', PRIMARY KEY (`value_id`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;CREATE TABLE IF NOT EXISTS `category_option_value_description` ( `value_id` int(10) NOT NULL DEFAULT '0', `language_id` int(10) NOT NULL DEFAULT '0', `option_id` int(10) NOT NULL DEFAULT '0', `name` varchar(127) DEFAULT NULL, PRIMARY KEY (`value_id`,`language_id`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;CREATE TABLE IF NOT EXISTS `product_to_value` ( `product_id` int(11) NOT NULL, `value_id` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`product_id`,`value_id`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;
2) В файле adminviewtemplatecatalogproduct_form.tplПосле
<a tab="#tab_links"><?php echo $tab_links; ?></a>Вставляем
<a tab="#tab_filter">Опции фильтра</a>После блока
<div id="tab_general"></div>Вставляем
<!-- Start tab filter--> <div id="tab_filter"> Сначала необходимо выбрать категории товара </div> <!-- End tab filter-->Теперь идем в конец файла, ДО
<?php echo $footer; ?>Вставляем
<script type="text/javascript"><!--$.tabs('#tabs a'); $.tabs('#languages a'); //--></script><script type="text/javascript"><!--$('input[name=product_category[]]').live('change', function() { getOptions();});<?php if (isset($this->request->get['product_id'])) { ?> <?php $if_product_id = '&product_id=' . $this->request->get['product_id']; ?> getOptions();<?php } else { ?> <?php $if_product_id = ''; ?><?php } ?>function getOptions() { var loadUrl = ''; var fields = $("input[name=product_category[]]").serializeArray(); jQuery.each(fields, function(i, field){ if (i == 0) { loadUrl += field.value; } else { loadUrl += '_' + field.value; } }); $('#tab_filter').load('index.php?route=catalog/product/filter&token=<?php echo $token; ?><?php echo $if_product_id; ?>&path=' + loadUrl); }//--></script>Сохраняем и закрываем.3) Открываем файл adminmodelcatalogproduct.php
После блока (метод addProduct)
if (isset($data['product_store'])) { foreach ($data['product_store'] as $store_id) { $this->db->query("INSERT INTO " . DB_PREFIX . "product_to_store SET product_id = '" . (int)$product_id . "', store_id = '" . (int)$store_id . "'"); } }Вставляем
// Start Filter if (isset($data['product_to_value_id'])) { foreach ($data['product_to_value_id'] as $value_id) { $this->db->query("INSERT INTO " . DB_PREFIX . "product_to_value SET product_id = '" . (int)$product_id . "', value_id = '" . (int)$value_id . "'"); } } // End filterПосле блока (метод updateProduct)
$this->db->query("DELETE FROM " . DB_PREFIX . "product_to_store WHERE product_id = '" . (int)$product_id . "'"); if (isset($data['product_store'])) { foreach ($data['product_store'] as $store_id) { $this->db->query("INSERT INTO " . DB_PREFIX . "product_to_store SET product_id = '" . (int)$product_id . "', store_id = '" . (int)$store_id . "'"); } }Вставляем
// Start filter $this->db->query("DELETE FROM " . DB_PREFIX . "product_to_value WHERE product_id = '" . (int)$product_id . "'"); if (isset($data['product_to_value_id'])) { foreach ($data['product_to_value_id'] as $value_id) { $this->db->query("INSERT INTO " . DB_PREFIX . "product_to_value SET product_id = '" . (int)$product_id . "', value_id = '" . (int)$value_id . "'"); } } // End filterПосле (метод copyProduct)
$data = array_merge($data, array('product_store' => $this->getProductStores($product_id)));Вставляем
// Start filter $data = array_merge($data, array('product_to_value_id' => $this->getProductValues($product_id))); // End filterПосле (метод deleteProduct)
$this->db->query("DELETE FROM " . DB_PREFIX . "product_to_store WHERE product_id = '" . (int)$product_id . "'");Вставляем
// Start filter $this->db->query("DELETE FROM " . DB_PREFIX . "product_to_value WHERE product_id = '" . (int)$product_id . "'"); // End filterИдем в конец файла, до закрытия класса вставляем
// Start filter public function getProductValues($product_id) { $values_id = array(); $query = $this->db->query("SELECT " . DB_PREFIX . "p2v.value_id AS value_id FROM " . DB_PREFIX . "product_to_value p2v WHERE p2v.product_id = '" . (int)$product_id . "'"); foreach ($query->rows as $result) { $values_id[] = $result['value_id']; } return $values_id; } // End filterСохраняем и закрываем4) Открываем admincontrollercatalogproduct.php
и идем в конец файла, до закрытия класса вставляем
// Start filter public function filter() { $this->load->model('catalog/filter'); $this->load->model('catalog/product'); $this->data['category_options'] = array(); if (isset($this->request->get['path']) && $this->request->get['path'] != '') { $parts = explode('_', $this->request->get['path']); $results = $this->model_catalog_filter->getOptionByCategoriesId($parts); if ($results) { foreach($results as $option) { $this->data['category_options'][] = array( 'option_id' => $option['option_id'], 'name' => $option['name'], 'type' => $option['type'], 'category_option_values' => $this->model_catalog_filter->getOptionValues($option['option_id']) ); } } else { $this->data['message'] = 'Этой категории товаров не присвоен ниодин фильтр'; } } else { $this->data['message'] = 'Сначала выберите категорию товаров'; } if (isset($this->request->get['product_id'])) { $product_id = $this->request->get['product_id']; } else { $product_id = 0; } $product_info = $this->model_catalog_product->getProductValues($product_id); if (isset($this->request->post['product_to_value_id'])) { $this->data['product_to_value_id'] = $this->request->post['product_to_value_id']; } elseif (isset($product_info)) { $this->data['product_to_value_id'] = $this->model_catalog_product->getProductValues($product_id); } else { $this->data['product_to_value_id'] = array(); } $this->data['language_id'] = $this->config->get('config_language_id'); $this->template = 'catalog/get_ajax_options.tpl'; $this->response->setOutput($this->render(TRUE), $this->config->get('config_compression')); } // End filterСохраняем и закрываем.5) Открываем catalogmodelcatalogproduct.php
Заменяем
public function getProductsByCategoryId($category_id, $sort = 'p.sort_order', $order = 'ASC', $start = 0, $limit = 20) {На
public function getProductsByCategoryId($category_id, $values, $sort = 'p.sort_order', $order = 'ASC', $start = 0, $limit = 20) {До блока
$sort_data = array( 'pd.name', 'p.sort_order', 'special', 'rating', 'p.price', 'p.model' );Вставляем
// Start filter if (isset($values) && $values != '') { $data = array(); foreach (explode('_', $values) as $value_id) { $data[] = "value_id = '" . (int)$value_id . "'"; } $sql .= " AND p.product_id IN (SELECT " . DB_PREFIX . "product_id FROM " . DB_PREFIX . "product_to_value WHERE " . implode(" OR ", $data) . ")"; } // End filterЗаменяем весь метод public function getTotalProductsByCategoryId На
public function getTotalProductsByCategoryId($category_id = 0, $values) { $sql = "SELECT COUNT(*) AS total FROM " . DB_PREFIX . "product_to_category p2c LEFT JOIN " . DB_PREFIX . "product p ON (p2c.product_id = p.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "' AND p2c.category_id = '" . (int)$category_id . "'"; // Start filter if (isset($values) && $values != '') { $data = array(); foreach (explode('_', $values) as $value_id) { $data[] = "value_id = '" . (int)$value_id . "'"; } $sql .= " AND p.product_id IN (SELECT product_id FROM " . DB_PREFIX . "product_to_value WHERE " . implode(" OR ", $data) . ")"; } // End filter $query = $this->db->query($sql); return $query->row['total']; }В этом же методе, до $query = $this->db->query($sql); Вставляем // Start filter if (isset($values) && $values != '') { $data = array(); foreach (explode('_', $values) as $value_id) { $data[] = "value_id = '" . (int)$value_id . "'"; } $sql .= " AND p.product_id IN (SELECT product_id FROM " . DB_PREFIX . "product_to_value WHERE " . implode(" OR ", $data) . ")"; } // End filterСохраняем, закрываем.6) Открываем catalogcontrollerproductcategory.php
Заменяем
$product_total = $this->model_catalog_product->getTotalProductsByCategoryId($category_id);На
$product_total = $this->model_catalog_product->getTotalProductsByCategoryId($category_id, $values = NULL);Заменяем
$results = $this->model_catalog_product->getProductsByCategoryId($category_id, $sort, $order, ($page - 1) * $this->config->get('config_catalog_limit'), $this->config->get('config_catalog_limit'));На
$results = $this->model_catalog_product->getProductsByCategoryId($category_id, $values = NULL, $sort, $order, ($page - 1) * $this->config->get('config_catalog_limit'), $this->config->get('config_catalog_limit'));
7) Качаем архив Openstore_module_product_filter_1.0_(manual_install).rar и извлекаем в корень сайта с заменой.8) Идем в админку -> дополнения и включаем фильтр. Дальше думаю всё ясно.