PrestaShop ha un ottimo strumento di ricerca, ma a volte non soddisfa tutte le tue esigenze. Inoltre non è molto veloce e nei grandi negozi la ricerca e l’indicizzazione potrebbero essere molto lente.
Se desideri qualcosa di meglio, puoi utilizzare un’ottima alternativa – Sphinx.
Da Wikipedia:
Sphinx è un motore di ricerca Fulltext open source/software libero progettato per fornire funzionalità di ricerca full-text alle applicazioni client.
Sito web di Sphinx – http://sphinxsearch.com/
Installazione di Sphinx
Ho usato Debian 8.1. In altre distribuzioni Linux (e in particolar modo in Windows) l’installazione potrebbe differire leggermente.
Se Sphinx è disponibile nei repository, installalo semplicemente:
1 2 3 | su apt-get update apt-get install sphinxsearch |
Se Sphinx non è disponibile nei repository, puoi scaricare un programma di installazione dal sito ufficiale e installare le dipendenze:
1 2 3 | apt-get install mysql-client unixodbc libpq5 wget http://sphinxsearch.com/files/sphinxsearch_2.2.9-release-1~wheezy_i386.deb dpkg -i sphinxsearch_2.2.9-release-1~wheezy_i386.deb |
Devi sostituire il nome e l’url del programma di installazione con le versioni correnti rilevanti. Sono tutte disponibili sul sito ufficiale.
Configurazione di Sphinx
Apri la configurazione di Sphinx e modificala:
1 | nano /etc/sphinxsearch/sphinx.conf |
Devi modificare il blocco predefinito esistente “source src1” (o aggiungere un nuovo blocco). Il risultato dovrebbe apparire così:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | source PrestaSite { type = mysql sql_host = localhost # PrestaShop database username sql_user = DBUSER # PrestaShop database password sql_pass = DBPASSWORD # PrestaShop database name sql_db = DBNAME sql_port = 3306 # optional, default is 3306 sql_query_pre = SET NAMES utf8 # MySQL query with list of fields for indexation sql_query = SELECT id_product, name, description, description_short FROM ps_product_lang } |
Per prima cosa puoi vedere le impostazioni per connettersi al database (non dimenticare di modificarle con quelle pertinenti). Il parametro sql_query contiene una query con i campi per l’indicizzazione.
Queste sono tutte le impostazioni dalla mia configurazione. Fondamentalmente, il file di configurazione è ben documentato e tutte le opzioni sono descritte lì, in modo da poter personalizzare facilmente la tua configurazione.
Successivamente, nel blocco “index definition” devi configurare l’indice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | index PrestaSite { # data source for indexation source = PrestaSite # location for index data path = /var/lib/sphinxsearch/data/prestasite # morphology preprocessors morphology = stem_en # minimal word length for indexation min_word_len = 1 } |
Successivamente puoi vedere i blocchi “indexer settings” e “searchd settings”. Di solito vanno bene, puoi semplicemente saltarli.
Quindi, abbiamo configurato l’origine dati (source PrestaSite) e l’indice (index PrestaSite).
Indicizzazione
Avvia indexer per indicizzare il tuo database:
1 | indexer --all |
Avvio di Sphinx
Non dimenticare di avviare/riavviare searchd:
1 | searchd |
E aggiungi indexer a crontab:
1 | 15 * * * * root indexer --all |
L’indicizzazione verrà avviata ogni ora.
Configurazione di PrestaShop
Di seguito puoi vedere il codice per PrestaShop 1.6. Per le altre versioni di PrestaShop potrebbe differire leggermente.
Crea (o modifica) l’override della classe Search:
/override/classes/Search.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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | <?php class Search extends SearchCore { 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) { if (!$context) { $context = Context::getContext(); } $db = Db::getInstance(_PS_USE_SQL_SLAVE_); // TODO : smart page management if ($page_number < 1) $page_number = 1; if ($page_size < 1) $page_size = 1; if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) return false; if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) { return false; } $start = ($page_number - 1) * $page_size; // Sphinx search, get ids of found products $sphinx_results = self::getSphinxResults($expr, $start, $page_size); $result = null; $total = 0; // get products by id if something found if (is_array($sphinx_results) AND sizeof($sphinx_results) AND isset($sphinx_results['total']) AND $sphinx_results['total'] > 0) { $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`, MAX(image_shop.`id_image`) id_image, il.`legend`, m.`name` manufacturer_name, MAX(product_attribute_shop.`id_product_attribute`) id_product_attribute, DATEDIFF( p.`date_add`, DATE_SUB( NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY ) ) > 0 new 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_.'product_attribute` pa ON (p.`id_product` = pa.`id_product`) '.Shop::addSqlAssociation('product_attribute', 'pa', false, 'product_attribute_shop.`default_on` = 1').' '.Product::sqlStock('p', 'product_attribute_shop', false, $context->shop).' LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer` LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = p.`id_product`)'. Shop::addSqlAssociation('image', 'i', false, 'image_shop.cover=1').' LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.') WHERE p.`id_product` IN('.implode(',', $sphinx_results['results']).') GROUP BY product_shop.id_product'; $result = $db->executeS($sql); // results count $total = $sphinx_results['total']; } if (!$result) { $result_properties = array(); } else { $result_properties = Product::getProductsProperties((int)$id_lang, $result); } return array('total' => $total, 'result' => $result_properties); } protected static function getSphinxResults($search_query, $page_number, $page_size) { $results = array(); $total = 0; if(!$search_query) return null; // connect to Sphinx database $link = mysqli_connect('127.0.0.1', '', '', '', '9306'); if($link) { $query = 'SELECT * FROM `PrestaSite` WHERE MATCH(''.pSQL($search_query).'') limit '.(int)$page_number.', '.(int)$page_size.';'; if ($result = $link->query($query)) { while($query_results = $result->fetch_array()) { $results = array_merge($results, $query_results); } /* clear result */ $result->close(); } // get count of results $query_total = 'SELECT count(*) FROM `PrestaSite` WHERE MATCH(''.pSQL($search_query).'');'; if ($result = $link->query($query_total)) { $total = (int)$result->fetch_array()[0]; if($total > 1000) $total = 1000; } mysqli_close($link); } return array('results' => $results, 'total' => $total); } } |
Sostanzialmente, il codice è piuttosto semplice. Sovrascriviamo la funzione “find”, nella quale sostituiamo la ricerca di PrestaShop con la ricerca Sphinx. Sphinx restituisce gli id dei prodotti e utilizzando tali id eseguiamo la query dei dati dei prodotti. La seconda funzione (getSphinxResults) esegue direttamente la ricerca.
Alla fine, devi svuotare la cache e rimuovere la cache delle classi (/cache/class_index.php). Tutto fatto!
