Jump to content

Show categories in search result page


Alvarosc

Recommended Posts

Hi!!

 

I'm been looking for this customization for a few months but I didn't find how to do it.

 

I'd like to show in search result page products and categories. I mean, I'd like to show 2 sections. First one, categories that have that word in their name or description (if it is possible). Second one, products that have that word in their name or description (this is the default search of Prestashop).

 

I know you can do it it's with a query to MySQL and PHP, but I have basic knowledge of both of them (I can edit but I can't create), so if someone could give a website with some code or a basis to work I would greatly appreciate it.

 

Sorry about my poor English.

 

So thanks!!  :)

Link to comment
Share on other sites

  • 1 year later...
  • 3 years later...
  • 4 weeks later...

Ok, I think I made it but presentation layer is up to You. I won't cover basics of overrides here, I'll just post changes and addition in functions. If You know PS Basics then You will make it. This doesn't support pagination. Basically it is quite simple to do but it just looks hard.

We need to edit only 3 files: Search.php, SearchController.php and Search.tpl from theme folder.

 

First thing we need create function to search in categories so let's go Search.php (You can create an override for this) with this function in it.

 public static function findCategories($expr, $id_shop = 1, $id_lang = 1, $order_by = 'id_parent', $limit = 15, $search_in_keywords = false)
    {
        $db = Db::getInstance(_PS_USE_SQL_SLAVE_);
        $expr = pSQL(Tools::substr($expr, 0, PS_SEARCH_MAX_WORD_LENGTH));
        $keywords_search = ($search_in_keywords) ? 'OR cl.meta_keywords LIKE \'%'.$expr.'%\'' : '';

        $query = '
            SELECT * FROM '._DB_PREFIX_.'category_lang cl
            LEFT JOIN '._DB_PREFIX_.'category c ON cl.id_category = c.id_category
            LEFT JOIN '._DB_PREFIX_.'category_shop cs ON cs.id_category = cl.id_category
            WHERE (cl.name
            LIKE \'%'.$expr.'%\' '.$keywords_search.')
            AND cl.id_lang = '.(int)$id_lang.'
            AND c.active = 1
            AND cs.id_shop = '.(int)$id_shop.'
            ORDER BY c.'.pSQL($order_by).'
            LIMIT '.(int)$limit.'
        ';

        if ($results = $db->executeS($query))
            return $results;
        else
            return false;
    }

Now let's go to SearchController.php and look for public function initContent() function (as stated before - you can create override of it) and search for this line 

[...] 
} elseif (($query = Tools::getValue('search_query', Tools::getValue('ref'))) && !is_array($query)) {
            $this->productSort();
            $this->n = abs((int)(Tools::getValue('n', $product_per_page)));
            $this->p = abs((int)(Tools::getValue('p', 1)));
            $original_query = $query;
            $query = Tools::replaceAccentedChars(urldecode($query));
            $search = Search::find($this->context->language->id, $query, $this->p, $this->n, $this->orderBy, $this->orderWay);
           
            if (is_array($search['result'])) {
                foreach ($search['result'] as &$product) {
                    $product['link'] .= (strpos($product['link'], '?') === false ? '?' : '&').'search_query='.urlencode($query).'&results='.(int)$search['total'];
                }
            }

			Hook::exec('actionSearch', array('expr' => $query, 'total' => $search['total']));
            $nbProducts = $search['total'];
            $this->pagination($nbProducts);

            $this->addColorsToProductList($search['result']);

            $this->context->smarty->assign(array(
                'products' => $search['result'], // DEPRECATED (since to 1.4), not use this: conflict with block_cart module
                'search_products' => $search['result'],
                'nbProducts' => $search['total'],
                'search_query' => $original_query,
                'homeSize' => Image::getSize(ImageType::getFormatedName('home'))));
        }

and change it to this:

elseif (($query = Tools::getValue('search_query', Tools::getValue('ref'))) && !is_array($query)) {
            $this->productSort();
            $this->n = abs((int)(Tools::getValue('n', $product_per_page)));
            $this->p = abs((int)(Tools::getValue('p', 1)));
            $original_query = $query;
            $query = Tools::replaceAccentedChars(urldecode($query));
            $search = Search::find($this->context->language->id, $query, $this->p, $this->n, $this->orderBy, $this->orderWay);
            $search_cats = Search::findCategories($query, $this->context->shop->id, $this->context->language->id, 'id_parent', 15, false); // added by Eryk
            if (is_array($search['result'])) {
                foreach ($search['result'] as &$product) {
                    $product['link'] .= (strpos($product['link'], '?') === false ? '?' : '&').'search_query='.urlencode($query).'&results='.(int)$search['total'];
                }
            }

			Hook::exec('actionSearch', array('expr' => $query, 'total' => $search['total']));
            $nbProducts = $search['total'];
            $this->pagination($nbProducts);

            $this->addColorsToProductList($search['result']);

            $this->context->smarty->assign(array(
                'products' => $search['result'], // DEPRECATED (since to 1.4), not use this: conflict with block_cart module
                'search_products' => $search['result'],
                'search_cats' => $search_cats, // added by Eryk
                'nbProducts' => $search['total'],
                'search_query' => $original_query,
                'homeSize' => Image::getSize(ImageType::getFormatedName('home'))));
        }

Now in search.tpl from You theme folder You need to display these values but I won't help You with bad look - I created this only for myself and for my theme so You need to adjust it with Your html + smarty.

Right after 

{include file="$tpl_dir./errors.tpl"}

add this code

{if isset($search_cats) && $search_cats}
    <div id="categories">
        <hr>
        <h3 class="t18"><strong>{l s='Categories found'} ({$search_cats|@count} results)</strong></h3>
        {if $nbProducts > 0}
            <p class="lighter">You will find founed products below categories results.</p>
        {/if}
        <ul class="clearfix row">
        {foreach from=$search_cats item=category name=cat}
            <li class="col-xs-6 col-lg-3">
                <div class="product-container">
                    <a href="{$link->getCategoryLink($category.id_category, $category.link_rewrite)|escape:'html':'UTF-8'}" title="{$category.name|escape:'html':'UTF-8'}" class="img">
                        {if $category.id_category}
                            <img src="{$img_cat_dir}{$category.id_category}_thumb.jpg" alt="{$category.name|escape:'html':'UTF-8'}" width="{$mediumSize.width}" height="{$mediumSize.height}" class="img-responsive"/>
                        {else}
                            <img src="{$img_cat_dir}{$category.id_category}medium_default.jpg" alt="{$category.name|escape:'html':'UTF-8'}" width="{$mediumSize.width}" height="{$mediumSize.height}" class="img-responsive"/>
                        {/if}
                    </a>
                    <h5>
                        <a class="product-name" href="{$link->getCategoryLink($category.id_category, $category.link_rewrite)|escape:'html':'UTF-8'}">
                            <strong>{$category.name|escape:'html':'UTF-8'}</strong>
                        </a>
                    </h5>
                </div>
            </li>
        {/foreach}
            </ul>
        </div>
{/if}

Save, upload, clear cache. Should work, In my shop works.

Few disclaimers:

In SearchController.php You can edit parameters for findCategories() function. You can set last parameter to true instead of false if You want to search in meta_keywords of categories.

You should also change first parameter of this function from $query to $original_query if You are from Poland or something, because Tools::replaceAccentedChars(urldecode($query)); is removing "ł" and it changes it "l" instead. 

You can change col-lg-3 to col-lg-2 if You want to have 6 thumbnails instead of 4.

Good luck, I won't support this code and any issues with it ;)
 

Edited by hakeryk2 (see edit history)
  • Thanks 1
Link to comment
Share on other sites

  • 1 year later...
On 10/7/2019 at 12:54 PM, hakeryk2 said:

Ok, I think I made it but presentation layer is up to You. I won't cover basics of overrides here, I'll just post changes and addition in functions. If You know PS Basics then You will make it. This doesn't support pagination. Basically it is quite simple to do but it just looks hard.

We need to edit only 3 files: Search.php, SearchController.php and Search.tpl from theme folder.

 

First thing we need create function to search in categories so let's go Search.php (You can create an override for this) with this function in it.


 public static function findCategories($expr, $id_shop = 1, $id_lang = 1, $order_by = 'id_parent', $limit = 15, $search_in_keywords = false)
    {
        $db = Db::getInstance(_PS_USE_SQL_SLAVE_);
        $expr = pSQL(Tools::substr($expr, 0, PS_SEARCH_MAX_WORD_LENGTH));
        $keywords_search = ($search_in_keywords) ? 'OR cl.meta_keywords LIKE \'%'.$expr.'%\'' : '';

        $query = '
            SELECT * FROM '._DB_PREFIX_.'category_lang cl
            LEFT JOIN '._DB_PREFIX_.'category c ON cl.id_category = c.id_category
            LEFT JOIN '._DB_PREFIX_.'category_shop cs ON cs.id_category = cl.id_category
            WHERE (cl.name
            LIKE \'%'.$expr.'%\' '.$keywords_search.')
            AND cl.id_lang = '.(int)$id_lang.'
            AND c.active = 1
            AND cs.id_shop = '.(int)$id_shop.'
            ORDER BY c.'.pSQL($order_by).'
            LIMIT '.(int)$limit.'
        ';

        if ($results = $db->executeS($query))
            return $results;
        else
            return false;
    }

Now let's go to SearchController.php and look for public function initContent() function (as stated before - you can create override of it) and search for this line 


[...] 
} elseif (($query = Tools::getValue('search_query', Tools::getValue('ref'))) && !is_array($query)) {
            $this->productSort();
            $this->n = abs((int)(Tools::getValue('n', $product_per_page)));
            $this->p = abs((int)(Tools::getValue('p', 1)));
            $original_query = $query;
            $query = Tools::replaceAccentedChars(urldecode($query));
            $search = Search::find($this->context->language->id, $query, $this->p, $this->n, $this->orderBy, $this->orderWay);
           
            if (is_array($search['result'])) {
                foreach ($search['result'] as &$product) {
                    $product['link'] .= (strpos($product['link'], '?') === false ? '?' : '&').'search_query='.urlencode($query).'&results='.(int)$search['total'];
                }
            }

			Hook::exec('actionSearch', array('expr' => $query, 'total' => $search['total']));
            $nbProducts = $search['total'];
            $this->pagination($nbProducts);

            $this->addColorsToProductList($search['result']);

            $this->context->smarty->assign(array(
                'products' => $search['result'], // DEPRECATED (since to 1.4), not use this: conflict with block_cart module
                'search_products' => $search['result'],
                'nbProducts' => $search['total'],
                'search_query' => $original_query,
                'homeSize' => Image::getSize(ImageType::getFormatedName('home'))));
        }

and change it to this:


elseif (($query = Tools::getValue('search_query', Tools::getValue('ref'))) && !is_array($query)) {
            $this->productSort();
            $this->n = abs((int)(Tools::getValue('n', $product_per_page)));
            $this->p = abs((int)(Tools::getValue('p', 1)));
            $original_query = $query;
            $query = Tools::replaceAccentedChars(urldecode($query));
            $search = Search::find($this->context->language->id, $query, $this->p, $this->n, $this->orderBy, $this->orderWay);
            $search_cats = Search::findCategories($query, $this->context->shop->id, $this->context->language->id, 'id_parent', 15, false); // added by Eryk
            if (is_array($search['result'])) {
                foreach ($search['result'] as &$product) {
                    $product['link'] .= (strpos($product['link'], '?') === false ? '?' : '&').'search_query='.urlencode($query).'&results='.(int)$search['total'];
                }
            }

			Hook::exec('actionSearch', array('expr' => $query, 'total' => $search['total']));
            $nbProducts = $search['total'];
            $this->pagination($nbProducts);

            $this->addColorsToProductList($search['result']);

            $this->context->smarty->assign(array(
                'products' => $search['result'], // DEPRECATED (since to 1.4), not use this: conflict with block_cart module
                'search_products' => $search['result'],
                'search_cats' => $search_cats, // added by Eryk
                'nbProducts' => $search['total'],
                'search_query' => $original_query,
                'homeSize' => Image::getSize(ImageType::getFormatedName('home'))));
        }

Now in search.tpl from You theme folder You need to display these values but I won't help You with bad look - I created this only for myself and for my theme so You need to adjust it with Your html + smarty.

Right after 


{include file="$tpl_dir./errors.tpl"}

add this code


{if isset($search_cats) && $search_cats}
    <div id="categories">
        <hr>
        <h3 class="t18"><strong>{l s='Categories found'} ({$search_cats|@count} results)</strong></h3>
        {if $nbProducts > 0}
            <p class="lighter">You will find founed products below categories results.</p>
        {/if}
        <ul class="clearfix row">
        {foreach from=$search_cats item=category name=cat}
            <li class="col-xs-6 col-lg-3">
                <div class="product-container">
                    <a href="{$link->getCategoryLink($category.id_category, $category.link_rewrite)|escape:'html':'UTF-8'}" title="{$category.name|escape:'html':'UTF-8'}" class="img">
                        {if $category.id_category}
                            <img src="{$img_cat_dir}{$category.id_category}_thumb.jpg" alt="{$category.name|escape:'html':'UTF-8'}" width="{$mediumSize.width}" height="{$mediumSize.height}" class="img-responsive"/>
                        {else}
                            <img src="{$img_cat_dir}{$category.id_category}medium_default.jpg" alt="{$category.name|escape:'html':'UTF-8'}" width="{$mediumSize.width}" height="{$mediumSize.height}" class="img-responsive"/>
                        {/if}
                    </a>
                    <h5>
                        <a class="product-name" href="{$link->getCategoryLink($category.id_category, $category.link_rewrite)|escape:'html':'UTF-8'}">
                            <strong>{$category.name|escape:'html':'UTF-8'}</strong>
                        </a>
                    </h5>
                </div>
            </li>
        {/foreach}
            </ul>
        </div>
{/if}

Save, upload, clear cache. Should work, In my shop works.

Few disclaimers:

In SearchController.php You can edit parameters for findCategories() function. You can set last parameter to true instead of false if You want to search in meta_keywords of categories.

You should also change first parameter of this function from $query to $original_query if You are from Poland or something, because Tools::replaceAccentedChars(urldecode($query)); is removing "ł" and it changes it "l" instead. 

You can change col-lg-3 to col-lg-2 if You want to have 6 thumbnails instead of 4.

Good luck, I won't support this code and any issues with it ;)
 

In which prestashop version did you make this modification? Thanks

Link to comment
Share on other sites

  • 7 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...