Jump to content

Search product from product attribute module


Recommended Posts

<?php
if (!defined('_PS_VERSION_')) {
    exit;
}

class Search_By_Size extends Module
{
    public function __construct()
    {
        $this->name = 'search_by_size';
        $this->tab = 'front_office_features';
        $this->version = '1.0.0';
        $this->author = 'Orange Mantra';
        $this->need_instance = 0;

        parent::__construct();

        $this->displayName = $this->l('Search by Size');
        $this->description = $this->l('Module to search products by attributes.');

        $this->ps_versions_compliancy = array('min' => '1.7', 'max' => _PS_VERSION_);
        $this->bootstrap = true;
    }

    public function install()
    {
        return parent::install() &&
            $this->registerHook('displayHome') &&
            $this->registerHook('header') &&
            $this->installOverrides();
    }

    public function uninstall()
    {
        return parent::uninstall() &&
            $this->uninstallOverrides();
    }

    public function installOverrides()
    {
        return $this->addOverride('controllers/front/listing/SearchController.php');
    }

    public function uninstallOverrides()
    {
        return $this->removeOverride('controllers/front/listing/SearchController.php');
    }

    public function addOverride($file)
    {
        $src = dirname(__FILE__) . '/override/' . $file;
        $dest = _PS_OVERRIDE_DIR_ . $file;

        if (!file_exists($src)) {
            return false;
        }

        if (!is_dir(dirname($dest))) {
            mkdir(dirname($dest), 0755, true);
        }

        return copy($src, $dest);
    }

    public function removeOverride($file)
    {
        $dest = _PS_OVERRIDE_DIR_ . $file;

        if (file_exists($dest)) {
            unlink($dest);
        }

        return true;
    }

    public function hookDisplayHome($params)
    {
        $this->context->smarty->assign(array(
            'search_action' => $this->context->link->getPageLink('search'),
        ));

        return $this->display(__FILE__, 'views/templates/hook/searchbar.tpl');
    }

    public function hookHeader($params)
    {
        $this->context->controller->addCSS($this->_path . 'css/search_by_size.css', 'all');
        $this->context->controller->addJS($this->_path . 'js/search_by_size.js');
    }
}
<div id="search-by-size" class="search-by-size">
    <h3>You can search product also from size</h3>
    <form action="{$search_action}" method="get" id="searchbox">
        <input type="text" id="search_query" name="search_query" placeholder="Search by size" autocomplete="off"/>
        <button type="submit">Search</button>
    </form>
    <ul id="autocomplete-results" style="display: none;"></ul>
</div>
<?php
include_once(dirname(__FILE__) . '/../../../../config/config.inc.php');
include_once(dirname(__FILE__) . '/../../../../init.php');


class Search_by_sizeAjaxModuleFrontController extends ModuleFrontController
{
    public function initContent()
    {


        //parent::initContent();
        $this->ajax = true;

        header('Content-Type: application/json');

         //die("Hellosss");


        if (Tools::getValue('query')) {
            $query = Tools::getValue('query');


            $colorAttributes = $this->getColorAttributes($query);
            echo json_encode($colorAttributes);
        } else {
            echo json_encode(array('error' => 'Query parameter missing'));
        }

        exit;
    }

    private function getColorAttributes($query)
    {
        $sql = 'SELECT a.id_attribute, al.name AS attribute_name 
                FROM ' . _DB_PREFIX_ . 'attribute a
                LEFT JOIN ' . _DB_PREFIX_ . 'attribute_lang al ON (a.id_attribute = al.id_attribute AND al.id_lang = ' . (int)$this->context->language->id . ')
                LEFT JOIN ' . _DB_PREFIX_ . 'attribute_group ag ON (a.id_attribute_group = ag.id_attribute_group)
                LEFT JOIN ' . _DB_PREFIX_ . 'attribute_group_lang agl ON (ag.id_attribute_group = agl.id_attribute_group AND agl.id_lang = ' . (int)$this->context->language->id . ')
                WHERE agl.public_name = "Color" AND al.name LIKE "%' . pSQL($query) . '%"';
        $results = Db::getInstance()->executeS($sql);

        $colorAttributes = [];
        foreach ($results as $result) {
            $colorAttributes[] = $result['attribute_name'];
        }

        return $colorAttributes;
    }
}
#search-by-size {

    padding: 20px;
    border: 1px solid #ccc;
    background-color: #f9f9f9;
    display: flex;
    flex-wrap: wrap;
    position: relative;
    

}
#search-by-size h3 {
    margin-bottom: 10px;
    width: 100%;
    text-align: center;
}

#search_query {
    width: 80%;
    padding: 10px;
    margin-right: 10px;
    border: 1px solid #ccc;
    border-radius: 4px;
}

#searchbox button {
    padding: 10px 15px;
    border: none;
    background-color: #5cb85c;
    color: white;
    border-radius: 4px;
    cursor: pointer;
    width: 18%;
}

#searchbox button:hover {
    background-color: #4cae4c;
    width: 18%;
}

#autocomplete-results {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid #ccc;
    background-color: white;
    position: absolute;
    width: 70%;
    z-index: 1000;
    top: calc(100% - 20px);
}

#autocomplete-results li {
    padding: 10px;
    cursor: pointer;
}

#autocomplete-results li:hover {
    background-color: #eee;
}


form#searchbox {
    width: 100%;
}
document.addEventListener('DOMContentLoaded', function() {
    const searchQueryInput = document.getElementById('search_query');
    const resultsContainer = document.getElementById('autocomplete-results');
    if (searchQueryInput) {
        searchQueryInput.addEventListener('input', function() {
            const query = this.value;

            if (query.length > 0) {
                const fetchURL = prestashop.urls.base_url + 'index.php?fc=module&module=search_by_size&controller=ajax&query=' + encodeURIComponent(query);

                fetch(fetchURL)
                    .then(response => {
                        if (!response.ok) {
                            throw new Error('Network response was not ok');
                        }
                        return response.json();
                    })
                    .then(data => {
                        console.log(data); // Log the response
                        resultsContainer.innerHTML = ''; // Clear previous results
                        if (data.length > 0) {
                            data.forEach(item => {
                                const li = document.createElement('li');
                                li.textContent = item;
                                li.addEventListener('click', function() {
                                    searchQueryInput.value = item;
                                    resultsContainer.innerHTML = ''; // Clear results on click
                                    resultsContainer.style.display = 'none'; // Hide results container
                                });
                                resultsContainer.appendChild(li);
                            });
                        } else {
                            resultsContainer.innerHTML = '<li>No result found</li>';
                        }
                        resultsContainer.style.display = 'block'; // Show results container
                    })
                    .catch(error => {
                        console.error('Error fetching data:', error);
                    });
            } else {
                resultsContainer.innerHTML = ''; // Clear results if query is empty
                resultsContainer.style.display = 'none'; // Hide results container if query is empty
            }
        });
    }
}); 
<?php


class SearchController extends SearchControllerCore
{

    die("Hello");
    public function initContent()
    {
        parent::initContent();


        if (Tools::getValue('color')) {
            $color = Tools::getValue('color');
            $this->filterProductsByColor($color);
        }
    }

    private function filterProductsByColor($color)
    {
        $sql = 'SELECT DISTINCT p.id_product
                FROM ' . _DB_PREFIX_ . 'product p
                LEFT JOIN ' . _DB_PREFIX_ . 'product_attribute pa ON (p.id_product = pa.id_product)
                LEFT JOIN ' . _DB_PREFIX_ . 'product_attribute_combination pac ON (pa.id_product_attribute = pac.id_product_attribute)
                LEFT JOIN ' . _DB_PREFIX_ . 'attribute a ON (pac.id_attribute = a.id_attribute)
                LEFT JOIN ' . _DB_PREFIX_ . 'attribute_lang al ON (a.id_attribute = al.id_attribute AND al.id_lang = ' . (int)$this->context->language->id . ')
                LEFT JOIN ' . _DB_PREFIX_ . 'attribute_group ag ON (a.id_attribute_group = ag.id_attribute_group)
                LEFT JOIN ' . _DB_PREFIX_ . 'attribute_group_lang agl ON (ag.id_attribute_group = agl.id_attribute_group AND agl.id_lang = ' . (int)$this->context->language->id . ')
                WHERE agl.public_name = "Color" AND al.name = "' . pSQL($color) . '"';

        $productIds = Db::getInstance()->executeS($sql);

        $productIdList = array_map(function($product) {
            return $product['id_product'];
        }, $productIds);

        if (!empty($productIdList)) {
            $productIdString = implode(',', $productIdList);
            $sql = 'SELECT DISTINCT p.*, pl.name, pl.description_short, pl.link_rewrite, image_shop.id_image, il.legend, m.name AS manufacturer_name 
                    FROM ' . _DB_PREFIX_ . 'product p
                    LEFT JOIN ' . _DB_PREFIX_ . 'product_lang pl ON (p.id_product = pl.id_product AND pl.id_lang = ' . (int)$this->context->language->id . ' AND pl.id_shop = ' . (int)$this->context->shop->id . ')
                    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)$this->context->shop->id . ')
                    LEFT JOIN ' . _DB_PREFIX_ . 'image_lang il ON (image_shop.id_image = il.id_image AND il.id_lang = ' . (int)$this->context->language->id . ')
                    LEFT JOIN ' . _DB_PREFIX_ . 'manufacturer m ON (m.id_manufacturer = p.id_manufacturer)
                    WHERE p.id_product IN (' . $productIdString . ') AND p.active = 1 AND p.visibility IN ("both", "search") 
                    ORDER BY p.id_product DESC';
            
            $products = Db::getInstance()->executeS($sql);
            $this->context->smarty->assign(array(
                'products' => $products,
            ));
        } else {
            $this->context->smarty->assign(array(
                'products' => [],
            ));
        }

        $this->setTemplate('catalog/listing/product-list.tpl');
    }
}

Hello everyone,

It's a prestashop custom module code and I want search product by attributes :

search_by_size |->search_by_size.php
                |->controllers -> front->ajax.php
                |->css -> search_by_size.css
                |->js -> search_by_size.js
                |->override -> controllers -> front -> listing -> SearchController.php
                |->views -> templates -> hook -> searchbar.tpl


Now I want some changes in it,

1.Custom Search Logic Based on Color Attributes:

When a user searches for a color (e.g., "red"), the search results should include products with color attributes matching the search query.
If multiple products have the same color attribute (e.g., "red"), all those products should be displayed in the search results.
Products with multiple color attributes (e.g., "red", "white", "black") should also be included in the search results if any of their color attributes match the search query.


2. Isolation from Default Search Bar:

Your custom search functionality should not interfere with the default search bar provided by PrestaShop.
The default search bar should continue to function as expected, independent of your custom search functionality.

3. Removal of Unnecessary Parts:

Any unnecessary code or overrides that might be causing issues or not contributing to the color-based search functionality should be removed from the module.

4. Limiting Search to Color Attributes Only:

The search functionality should only consider color attributes when performing searches. Other attributes (e.g., product names, descriptions) should be ignored in the search process.


Now I'm facing many issue in it, 

1. I want search product based on colour attributes, But not getting a satisfied output so I'm doing override searchcontroller in it, but it's not working.
like I do search "red" then if 2 products have red attribute then should be show in search result, if any product have multiple color like red, white, black then it'll show also in search result..

2. It's reflect to default search bar, it should be not work like this.

3.  let me know what need to be remove in it..

4.  I want it should be work with only color attributes not with products name or etc..


Please help me on it 

Link to comment
Share on other sites

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...