Довелось мне недавно переносить интернет-магазин из Webasyst Shop Script Premium на Prestashop 1.6x, да не простой магазин, а с кучей переделок, с функционалом, чпу, и тд… Нужно было скрыть товары из категорий со скобками () в названии и отобразить кнопки в карточке товара на эти скрытые товары. А еще в этих скобках находилась характеристика — ширина товара, при ее выборе в фильтре необходимо раскрывать эти товары, которые мы ранее скрыли. Такое решение имеет огромный плюс — вместо атрибутов используем полноценный товар — получаем гибкость при настройке URL, экспорте в маркет, синхронизации с 1С УТ …
Проблема решилась написанием своего скрипта для экспорта из из Webasyst Shop Script Premium в Prestashop 1.6x. , модулем Faktiva Clean URLs и некоторыми переделками кода, которыми хочу поделиться с вами. Для начала скроем товары со скобкой, для этого в classes/Сategory.php в SQL запрос добавим AND pl.name
NOT LIKE «%(%»
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
$sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) AS quantity'.(Combination::isFeatureActive() ? ', IFNULL(product_attribute_shop.id_product_attribute, 0) AS id_product_attribute, product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity' : '').', pl.`description`, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, image_shop.`id_image` id_image, il.`legend` as legend, m.`name` AS manufacturer_name, cl.`name` AS category_default, DATEDIFF(product_shop.`date_add`, DATE_SUB("'.date('Y-m-d').' 00:00:00", INTERVAL '.(int)$nb_days_new_product.' DAY)) > 0 AS new, product_shop.price AS orderprice FROM `'._DB_PREFIX_.'category_product` cp LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = cp.`id_product` '.Shop::addSqlAssociation('product', 'p'). (Combination::isFeatureActive() ? ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop ON (p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='.(int)$context->shop->id.')':'').' '.Product::sqlStock('p', 0).' LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (product_shop.`id_category_default` = cl.`id_category` AND cl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('cl').') LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').') LEFT JOIN `'._DB_PREFIX_.'image_shop` image_shop ON (image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop='.(int)$context->shop->id.') LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.') LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer` WHERE product_shop.`id_shop` = '.(int)$context->shop->id.' \AND pl.`name` NOT LIKE "%(%" AND cp.`id_category` = '.(int)$this->id .($active ? ' AND product_shop.`active` = 1' : '') .($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '') .($id_supplier ? ' AND p.id_supplier = '.(int)$id_supplier : ''); |
Еще нужно немного переделать часть кода, который отвечает за общее количество товаров в категории.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/** Return only the number of products */ if ($get_total) { $sql = 'SELECT COUNT(cp.`id_product`) AS total FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON p.`id_product` = cp.`id_product` LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON p.`id_product` = pl.`id_product` WHERE pl.`name` NOT LIKE "%(%" AND cp.`id_category` = '.(int)$this->id. ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : ''). ($active ? ' AND product_shop.`active` = 1' : ''). ($id_supplier ? 'AND p.id_supplier = '.(int)$id_supplier : ''); return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); } |
Теперь у нас «Товар (2м)» скрыт, (при отключенном модуле фильтров) давайте отобразим его в карточке родительского товара «Товар». Для этого я добавил свою функцию getProductsLinksAt($name), после getCombinationImageById, примерно 2225 строка в classes/Product.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
/** * SELECT pl.`id_product`, pl.`name`, pl.`link_rewrite` FROM `ps_product_lang` pl WHERE `name` LIKE 'Весна Нева 1%(%' ORDER BY `name` * slavenja */ public static function getProductsLinksAt($name) { $names = explode("(", $name); $result = Db::getInstance()->executeS(' SELECT pl.`id_product`, pl.`name`, pl.`link_rewrite` FROM `'._DB_PREFIX_.'product_lang` pl WHERE `name` LIKE "'. $names[0] .'%(%" ORDER BY `name` ' ); if (!$result) { return false; } $proddd = ''; $k = 0; foreach ($result as $row) { $start = strpos($row['name'], '('); $end = strpos($row['name'], ')', $start + 1); $length = $end - $start; $knopka = substr($row['name'], $start + 1, $length - 1); $knopka = str_replace(',', '.', $knopka); $knopka2 = floatval($knopka); $k++; $proddd .= '<div style="float:left" card_cost="' . $knopka2 . '"><a href="' . $row['link_rewrite'] . '.html" class="button button-info" title="' . $row['name'] . '">' . $knopka . '</a></div>'; } return $proddd; } |
Далее в product.tpl вашей темы добавим вывод кнопок
1 2 3 4 5 |
<div class="deck_container" style="visibility: hidden;"> {$product->getProductsLinksAt($product->name|escape:'html':'UTF-8')} </div> <br/> <br/> |
И в product.js добавим вначале кода небольшой скрипт для сортировки и показа
1 2 3 4 5 6 7 8 9 10 |
$(window).load(function() { var c = jQuery.makeArray($(".deck_container div")); c.sort(function(a, b) { a = $(a).attr("card_cost"); b = $(b).attr("card_cost"); return a - b }); $(c).appendTo(".deck_container"); $(".deck_container").css("visibility", "visible"); }); |
Теперь у нас товар со скобкой скрывается в категории и отображается в товаре, но если включим модуль — Блок многоуровневой навигации (фильтры), скрытие пропадет, исправим это. Идем в modules/blocklayered/blocklayered.php ищем $this->nbr_products = Db::getInstance()->getValue(‘SELECT COUNT(*) FROM ‘._DB_PREFIX_.’cat_filter_restriction’, false); и меняем на
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
// start $this->nbr_products = Db::getInstance()->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'cat_filter_restriction cr LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON pl.`id_product` = cr.`id_product` WHERE pl.`name` NOT LIKE "%(%"', false); $skrit = 'AND pl.`name` NOT LIKE "%(%"'; // NOTE jsox addon if(isset($selected_filters['id_feature']) && is_array($selected_filters['id_feature'])){ foreach ($selected_filters['id_feature'] as $value) { $parts = explode('_', $value); if(isset($parts[0]) && (int)$parts[0] === сюда ид характеристики!!!!!!!!!!!!!!!){ $skrit = ''; $this->nbr_products = Db::getInstance()->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'cat_filter_restriction', false); break; } } } // NOTE /jsox addon if ($this->nbr_products == 0) $this->products = array(); else { $product_per_page = isset($this->context->cookie->nb_item_per_page) ? (int)$this->context->cookie->nb_item_per_page : Configuration::get('PS_PRODUCTS_PER_PAGE'); $default_products_per_page = max(1, (int)Configuration::get('PS_PRODUCTS_PER_PAGE')); $n = $default_products_per_page; if (isset($this->context->cookie->nb_item_per_page)) { $n = (int)$this->context->cookie->nb_item_per_page; } if ((int)Tools::getValue('n')) { $n = (int)Tools::getValue('n'); } $nb_day_new_product = (Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20); // end |
И немного меняем запрос
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
if (version_compare(_PS_VERSION_, '1.6.1', '>=') === true) { $this->products = Db::getInstance()->executeS(' SELECT p.*, '.($alias_where == 'p' ? '' : 'product_shop.*,' ).' '.$alias_where.'.id_category_default, pl.*, image_shop.`id_image` id_image, il.legend, m.name manufacturer_name, '.(Combination::isFeatureActive() ? 'product_attribute_shop.id_product_attribute id_product_attribute,' : '').' DATEDIFF('.$alias_where.'.`date_add`, DATE_SUB("'.date('Y-m-d').' 00:00:00", INTERVAL '.(int)$nb_day_new_product.' DAY)) > 0 AS new, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity'.(Combination::isFeatureActive() ? ', product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity' : '').' FROM '._DB_PREFIX_.'cat_filter_restriction cp LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = cp.`id_product` '.Shop::addSqlAssociation('product', 'p'). (Combination::isFeatureActive() ? ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop ON (p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='.(int)$context->shop->id.')':'').' LEFT JOIN '._DB_PREFIX_.'product_lang pl ON (pl.id_product = p.id_product'.Shop::addSqlRestrictionOnLang('pl').' AND pl.id_lang = '.(int)$cookie->id_lang.') LEFT JOIN `'._DB_PREFIX_.'image_shop` image_shop ON (image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop='.(int)$context->shop->id.') LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$cookie->id_lang.') LEFT JOIN '._DB_PREFIX_.'manufacturer m ON (m.id_manufacturer = p.id_manufacturer) '.Product::sqlStock('p', 0).' WHERE '.$alias_where.'.`active` = 1 '.$skrit.' AND '.$alias_where.'.`visibility` IN ("both", "catalog") ORDER BY '.Tools::getProductsOrder('by', Tools::getValue('orderby'), true).' '.Tools::getProductsOrder('way', Tools::getValue('orderway')).' , cp.id_product'. ' LIMIT '.(((int)$this->page - 1) * $n.','.$n), true, false); } |
Далее поправим вывод товаров по производителю (classes/Manufacturer.php 382 строка AND pl.name
NOT LIKE «%(%»):
1 2 3 4 5 6 7 8 |
$sql .= ' WHERE p.`id_manufacturer` = '.(int)$id_manufacturer.' '.($active ? ' AND product_shop.`active` = 1' : '').' '.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').' AND pl.`name` NOT LIKE "%(%" GROUP BY p.id_product ORDER BY '.$alias.'`'.bqSQL($order_by).'` '.pSQL($order_way).' LIMIT '.(((int)$p - 1) * (int)$n).','.(int)$n; |
Далее поправим вывод в поиске (classes/Search.php 284 строка AND pl.name
NOT LIKE «%(%»):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
if ($ajax) { $sql = 'SELECT DISTINCT p.id_product, pl.name pname, cl.name cname, cl.link_rewrite crewrite, pl.link_rewrite prewrite '.$score.' FROM '._DB_PREFIX_.'product p INNER JOIN `'._DB_PREFIX_.'product_lang` pl ON ( p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').' ) '.Shop::addSqlAssociation('product', 'p').' INNER JOIN `'._DB_PREFIX_.'category_lang` cl ON ( product_shop.`id_category_default` = cl.`id_category` AND cl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('cl').' ) WHERE p.`id_product` '.$product_pool.' AND pl.`name` NOT LIKE "%(%" ORDER BY position DESC LIMIT 10'; |
И наконец в модулях, на главной — популярные и новые товары (classes/Product.php в функции getNewProducts)
1 2 3 4 5 |
$sql->where('product_shop.`active` = 1'); $sql->where('pl.`name` NOT LIKE "%(%"'); if ($front) { $sql->where('product_shop.`visibility` IN ("both", "catalog")'); } |
почему было бы просто не импортировать и не прописать 301 переадресацию.
товаров много было?
все же такие лучше танцы с бубном думаю опасно.
я бы анализировал 100% времени через вебвизор как ведет себя клиент на сайте с отказом
Товаров 20000 примерно, 301 редирект — не очень качественное решение. Сайт работает нормально, СЕО в плюсе, клиентов больше.