If you want to search products by category using blocksearch
module you need to override module and one Prestashop class.
How to do this
- Create file
/override/classes/Search.php
with content:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253<?phpclass Search extends SearchCore {const SEARCH_IN_SUBCATEGORIES = true;public static function find($id_lang, $expr, $page_number = 1, $page_size = 1, $order_by = 'position', $order_way = 'desc', $ajax = false, $use_cookie = true, Context $context = null) {$id_category = intval(Tools::getValue('search_category'));$category_ids = false;if (!$context) {$context = Context::getContext();}if ($id_category > 0) {// get categories to search$key = 'search-getCategoryChildrenRecursive-' . $context->shop->id . '-' . $id_category;if (self::SEARCH_IN_SUBCATEGORIES && !Cache::isStored($key)) {$category_ids = self::getCategoryChildrenRecursive($id_category);Cache::store($key, $category_ids);} elseif (self::SEARCH_IN_SUBCATEGORIES && Cache::isStored($key)) {$category_ids = Cache::retrieve($key);} else {$category_ids = array($id_category);}}$db = Db::getInstance(_PS_USE_SQL_SLAVE_);// TODO : smart page managementif ($page_number < 1) {$page_number = 1;}if ($page_size < 1) {$page_size = 1;}if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) {return false;}$intersect_array = array();$score_array = array();$words = explode(' ', Search::sanitize($expr, $id_lang, false, $context->language->iso_code));foreach ($words as $key => $word) {if (!empty($word) && strlen($word) >= (int) Configuration::get('PS_SEARCH_MINWORDLEN')) {$word = str_replace(array('%', '_'), array('\\%', '\\_'), $word);$start_search = Configuration::get('PS_SEARCH_START') ? '%' : '';$end_search = Configuration::get('PS_SEARCH_END') ? '' : '%';$intersect_array[] = 'SELECT DISTINCT si.id_productFROM ' . _DB_PREFIX_ . 'search_word swLEFT JOIN ' . _DB_PREFIX_ . 'search_index si ON sw.id_word = si.id_wordWHERE sw.id_lang = ' . (int) $id_lang . 'AND sw.id_shop = ' . $context->shop->id . 'AND sw.word LIKE' . ($word[0] == '-' ? ' \'' . $start_search . pSQL(Tools::substr($word, 1, PS_SEARCH_MAX_WORD_LENGTH)) . $end_search . '\'' : ' \'' . $start_search . pSQL(Tools::substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH)) . $end_search . '\'');if ($word[0] != '-') {$score_array[] = 'sw.word LIKE \'' . $start_search . pSQL(Tools::substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH)) . $end_search . '\'';}} else {unset($words[$key]);}}if (!count($words)) {return ($ajax ? array() : array('total' => 0, 'result' => array()));}$score = '';if (is_array($score_array) && !empty($score_array)) {$score = ',(SELECT SUM(weight)FROM ' . _DB_PREFIX_ . 'search_word swLEFT JOIN ' . _DB_PREFIX_ . 'search_index si ON sw.id_word = si.id_wordWHERE sw.id_lang = ' . (int) $id_lang . 'AND sw.id_shop = ' . $context->shop->id . 'AND si.id_product = p.id_productAND (' . implode(' OR ', $score_array) . ')) position';}$sql_groups = '';if (Group::isFeatureActive()) {$groups = FrontController::getCurrentCustomerGroups();$sql_groups = 'AND cg.`id_group` ' . (count($groups) ? 'IN (' . implode(',', $groups) . ')' : '= 1');}$results = $db->executeS('SELECT DISTINCT cp.`id_product`FROM `' . _DB_PREFIX_ . 'category_product` cp' . (Group::isFeatureActive() ? 'INNER JOIN `' . _DB_PREFIX_ . 'category_group` cg ON cp.`id_category` = cg.`id_category`' : '') . 'INNER JOIN `' . _DB_PREFIX_ . 'category` c ON cp.`id_category` = c.`id_category`INNER JOIN `' . _DB_PREFIX_ . 'product` p ON cp.`id_product` = p.`id_product`' . Shop::addSqlAssociation('product', 'p', false) . 'WHERE c.`active` = 1' . (($category_ids !== false) ? 'AND cp.`id_category` IN (' . implode(',', $category_ids) . ')' : '') . 'AND product_shop.`active` = 1AND product_shop.`visibility` IN ("both", "search")AND product_shop.indexed = 1' . $sql_groups, true, false);$eligible_products = array();foreach ($results as $row) {$eligible_products[] = $row['id_product'];}$eligible_products2 = array();foreach ($intersect_array as $query) {foreach ($db->executeS($query, true, false) as $row) {$eligible_products2[] = $row['id_product'];}}$eligible_products = array_unique(array_intersect($eligible_products, array_unique($eligible_products2)));if (!count($eligible_products)) {return ($ajax ? array() : array('total' => 0, 'result' => array()));}$product_pool = '';foreach ($eligible_products as $id_product) {if ($id_product) {$product_pool .= (int) $id_product . ',';}}if (empty($product_pool)) {return ($ajax ? array() : array('total' => 0, 'result' => array()));}$product_pool = ((strpos($product_pool, ',') === false) ? (' = ' . (int) $product_pool . ' ') : (' IN (' . rtrim($product_pool, ',') . ') '));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 pINNER 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 . 'ORDER BY position DESC LIMIT 10';return $db->executeS($sql, true, false);}if (strpos($order_by, '.') > 0) {$order_by = explode('.', $order_by);$order_by = pSQL($order_by[0]) . '.`' . pSQL($order_by[1]) . '`';}$alias = '';if ($order_by == 'price') {$alias = 'product_shop.';} elseif (in_array($order_by, array('date_upd', 'date_add'))) {$alias = 'p.';}$sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity,pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`name`,image_shop.`id_image` id_image, il.`legend`, m.`name` manufacturer_name ' . $score . ',DATEDIFF(p.`date_add`,DATE_SUB("' . date('Y-m-d') . ' 00:00:00",INTERVAL ' . (Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20) . ' DAY)) > 0 new' . (Combination::isFeatureActive() ? ', product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, IFNULL(product_attribute_shop.`id_product_attribute`,0) id_product_attribute' : '') . 'FROM ' . _DB_PREFIX_ . 'product p' . Shop::addSqlAssociation('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') . ')' . (Combination::isFeatureActive() ? 'LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute_shop` product_attribute_shopON (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_ . 'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer`LEFT JOIN `' . _DB_PREFIX_ . 'image_shop` image_shopON (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 . ')WHERE p.`id_product` ' . $product_pool . 'GROUP BY product_shop.id_product' . ($order_by ? 'ORDER BY ' . $alias . $order_by : '') . ($order_way ? ' ' . $order_way : '') . 'LIMIT ' . (int) (($page_number - 1) * $page_size) . ',' . (int) $page_size;$result = $db->executeS($sql, true, false);$sql = 'SELECT COUNT(*)FROM ' . _DB_PREFIX_ . 'product p' . Shop::addSqlAssociation('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') . ')LEFT JOIN `' . _DB_PREFIX_ . 'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer`WHERE p.`id_product` ' . $product_pool;$total = $db->getValue($sql, false);if (!$result) {$result_properties = false;} else {$result_properties = Product::getProductsProperties((int) $id_lang, $result);}return array('total' => $total, 'result' => $result_properties);}/*** Get category children recursive** @param int $id_category_* @param int $id_shop_* @param array $results* @return array*/public static function getCategoryChildrenRecursive($id_category_, $id_shop_ = null, &$results = array()) {$id_category = intval($id_category_);if (!in_array($id_category, $results)) {array_push($results, $id_category);}if ($id_shop_ === null) {$id_shop_ = Context::getContext()->shop->id;}$id_shop = intval($id_shop_);$q = "SELECT c.`id_category`, COUNT(child.`id_category`) AS children ". "FROM `" . _DB_PREFIX_ . "category` c ". "JOIN `" . _DB_PREFIX_ . "category_shop` cs ON (c.`id_category` = cs.`id_category`) ". "LEFT JOIN `" . _DB_PREFIX_ . "category` child ON (c.`id_category` = child.`id_parent`) ". "WHERE c.`id_parent` = " . $id_category . " AND cs.`id_shop` = " . $id_shop;$data = Db::getInstance()->executeS($q);foreach ($data as $d) {if (!in_array($d['id_category'], $results)) {array_push($results, intval($d['id_category']));}if (intval($d['children']) > 0) {self::getCategoryChildrenRecursive($d['id_category'], $id_shop, $results);}}return $results;}} - Create file
/override/module/blocksearch/blocksearch.php
with content:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354<?phpclass BlockSearchOverride extends BlockSearch {public function hookTop($params) {$key = $this->getCacheId('blocksearch-top' . ((!isset($params['hook_mobile']) || !$params['hook_mobile']) ? '' : '-hook_mobile'));if (Tools::getValue('search_query') || !$this->isCached('blocksearch-top.tpl', $key)) {$this->calculHookCommon($params);$this->smarty->assign(array('blocksearch_type' => 'top','search_query' => (string) Tools::getValue('search_query')));}Media::addJsDef(array('blocksearch_type' => 'top'));$categories_key = $this->getCacheId('blocksearch-top-categories-list');if (!$this->isCached('blocksearch-top.tpl', $categories_key)) {$categories_ = Category::getCategories(Context::getContext()->language->id, true, 'c.`level_depth`', 'AND (c.`level_depth` = 2 OR c.`level_depth` = 3)');$categories = array();foreach ($categories_ as $cats) {foreach ($cats as $cat) {$categories[] = $cat['infos'];}}Cache::store($categories_key, $categories);} else {$categories = Cache::retrieve($categories_key);}$this->smarty->assign(array('categories' => $categories));return $this->display(__FILE__, 'blocksearch-top.tpl', Tools::getValue('search_query') ? null : $key);}public function calculHookCommon($params) {$this->smarty->assign(array('ENT_QUOTES' => ENT_QUOTES,'search_ssl' => Tools::usingSecureMode(),'ajaxsearch' => Configuration::get('PS_SEARCH_AJAX'),'instantsearch' => Configuration::get('PS_INSTANT_SEARCH'),'self' => dirname(__FILE__),));return true;}} - Create/modify file
/themes/yourThemeName/modules/blocksearch/block-search-top.tpl
with content:
1234567891011121314151617181920212223242526<!-- Block search module TOP --><div id="search_block_top" class="col-sm-4 clearfix"><form id="searchbox" method="get" action="{$link->getPageLink('search', null, null, null, false, null, true)|escape:'html':'UTF-8'}" ><input type="hidden" name="controller" value="search" /><input type="hidden" name="orderby" value="position" /><input type="hidden" name="orderway" value="desc" /><input class="search_query form-control" type="text" id="search_query_top" name="search_query" placeholder="{l s='Search' mod='blocksearch'}" value="{$search_query|escape:'htmlall':'UTF-8'|stripslashes}" />{* display categories list *}<select class="form-control" name="search_category"><option value="0">{l s='All Categories' mod='blocksearch'}</option>{foreach from=$categories item='c'}<option value="{$c.id_category}" {if isset($smarty.get.search_category) && $smarty.get.search_category == $c.id_category}selected{/if}>{$c.name}</option>{/foreach}</select>{* / display categories list *}<button type="submit" name="submit_search" class="btn btn-default button-search"><span>{l s='Search' mod='blocksearch'}</span></button></form></div><!-- /Block search module TOP --> - Remove file
/cache/class_index.php
. - Done 🙂
is it for prestashop 1.7?
No, it’s for PrestaShop 1.6.
Is this going to work in 1.7
For 1.6 works like a charm.
Thank you VERY MUCH for sharing!