Come posso modificare i dati che Finder scarica dal mio negozio? #
Finder scarica periodicamente prodotti, categorie, ordini e altri dati del tuo negozio per poter offrire risultati di ricerca. Se hai bisogno di modificare queste informazioni prima che vengano scaricate (nascondere determinati prodotti, completare un testo, escludere una caratteristica che non apporta nulla alla ricerca, ecc.), puoi farlo tramite gli hook che Finder attiva durante questo processo, senza modificare il modulo Finder né il tuo catalogo reale.
Come funzionano gli hook di Finder? #
PrestaShop permette a qualsiasi modulo di “agganciarsi” a punti specifici dell’esecuzione di un altro modulo tramite gli hook. Finder attiva una serie di hook propri subito prima di eseguire le query sul database e subito dopo aver letto ogni tipo di dato. La registrazione di un hook viene sempre effettuata dal metodo install() di un modulo, quindi per poterli utilizzare è necessario disporre di un modulo PrestaShop personalizzato: puoi aggiungerli a un modulo che hai già installato nel tuo negozio oppure crearne uno nuovo appositamente per questo scopo.
Creare un modulo per registrare gli hook #
Si tratta di un normale modulo PrestaShop, senza nulla di particolare: un proprio nome tecnico, una classe che estenda Module e, nel metodo install(), la registrazione degli hook che ti interessano. Per ogni hook registrato viene implementato un metodo hook + il nome dell’hook:
<?php
if (!defined('_PS_VERSION_')) {
exit;
}
class MiTiendaFinderHooks extends Module
{
public function __construct()
{
$this->name = 'mitiendafinderhooks';
$this->tab = 'administration';
$this->version = '1.0.0';
$this->author = 'Mi tienda';
$this->need_instance = 0;
$this->bootstrap = true;
parent::__construct();
$this->displayName = 'Impostazioni di Finder';
$this->description = 'Impostazioni personalizzate sui dati scaricati da Finder';
$this->ps_versions_compliancy = ['min' => '1.6', 'max' => '9.999'];
}
public function install()
{
return parent::install()
&& $this->registerHook('sbFinderAfterGetSourceProduct');
// aggiungi qui gli altri hook di cui hai bisogno, consulta l'elenco qui sotto
}
public function uninstall()
{
return parent::uninstall();
}
public function hookSbFinderAfterGetSourceProduct(array &$params)
{
// la tua logica qui
}
}Puoi scegliere liberamente il nome del modulo e della classe. Devono semplicemente essere compatibili con la versione di PrestaShop utilizzata dal tuo negozio, essere scritti in PHP puro e non avere dipendenze Composer. Una volta scritto, il modulo può essere impacchettato in un file .zip e installato dal back office come qualsiasi altro modulo, oppure puoi caricare la cartella non compressa nella cartella modules del tuo negozio sul server.
Hook disponibili per escludere i dati prima di eseguire le query #
Questi tre hook vengono attivati subito prima che Finder costruisca la query SQL per ogni tipo di dato. Permettono di escludere interi record aggiungendo condizioni alla query:
- sbFinderBeforeObjectModelNumRowsDBQuery
- sbFinderBeforeObjectModelPaginateDBQuery
- sbFinderBeforeObjectModelSearchByFiltersAndSourceIdDBQuery
Tutti e tre ricevono gli stessi parametri: $params[‘model’] (una stringa che identifica ciò che viene consultato) e $params[‘query’] (un oggetto DbQuery di PrestaShop, passato per riferimento, al quale è possibile aggiungere una condizione where()). I possibili valori di model sono: product, category, order, cms_category, cms, supplier, manufacturer, tag, attribute o product_attribute (a seconda della versione di PrestaShop), attribute_group, carrier, cart_rule, country, feature, feature_value, currency e group.
La tabella principale della query utilizza sempre l’alias a (e, quando la query esegue una join con le lingue o i negozi, gli alias sono l e s). Ad esempio, per escludere completamente alcune caratteristiche:
public function hookSbFinderBeforeObjectModelNumRowsDBQuery(array &$params)
{
$this->excludeFeatures($params['model'], $params['query']);
}
public function hookSbFinderBeforeObjectModelPaginateDBQuery(array &$params)
{
$this->excludeFeatures($params['model'], $params['query']);
}
public function hookSbFinderBeforeObjectModelSearchByFiltersAndSourceIdDBQuery(array &$params)
{
$this->excludeFeatures($params['model'], $params['query']);
}
private function excludeFeatures(string $model, DbQuery $query)
{
$excludedIds = [12, 15]; // ID delle caratteristiche che non vuoi indicizzare
if ($model === 'feature' && !empty($excludedIds)) {
$query->where('a.id_feature NOT IN (' . implode(', ', $excludedIds) . ')');
}
}Nota: per escludere completamente un dato è necessario registrare e gestire tutti e tre gli hook contemporaneamente, perché Finder li utilizza in momenti diversi (per contare i risultati, effettuare la paginazione e cercare tramite filtri).
Hook disponibili per modificare i dati già ottenuti #
Questi hook vengono attivati dopo che Finder ha letto ogni tipo di dato e prima di inviarlo, uno per ogni fonte di dati:
- Prodotti: sbFinderAfterGetSourceProduct
- Categorie: sbFinderAfterGetSourceCategory
- Ordini: sbFinderAfterGetSourceOrder
- Categorie di contenuto (CMS): sbFinderAfterGetSourceCMSCategory
- Pagine di contenuto (CMS): sbFinderAfterGetSourceCMS
- Fornitori: sbFinderAfterGetSourceSupplier
- Produttori: sbFinderAfterGetSourceManufacturer
- Tag: sbFinderAfterGetSourceTag
- Attributi: sbFinderAfterGetSourceAttribute
- Combinazioni di prodotti: sbFinderAfterGetSourceProductAttribute
- Gruppi di attributi: sbFinderAfterGetSourceAttributeGroup
- Trasportatori: sbFinderAfterGetSourceCarrier
- Regole del carrello: sbFinderAfterGetSourceCartRule
- Paesi: sbFinderAfterGetSourceCountry
- Caratteristiche: sbFinderAfterGetSourceFeature
- Valori delle caratteristiche: sbFinderAfterGetSourceFeatureValue
- Valute: sbFinderAfterGetSourceCurrency
- Gruppi di clienti: sbFinderAfterGetSourceGroup
Tutti ricevono $params[‘records’]: un array contenente i record di quella pagina, passato per riferimento, che può essere percorso e modificato direttamente. Ogni record contiene, tra le altre, le chiavi meta_keys (ad esempio l’id_product originale), texts (un array con un elemento {iso, name, value} per ogni campo traducibile e per ogni lingua) e platform_attributes (le restanti colonne del negozio: prezzo, disponibilità, stato attivo, immagini, caratteristiche, ecc., a seconda del tipo di dato).
Ad esempio, per completare la descrizione breve di un prodotto in spagnolo con informazioni aggiuntive prima che Finder lo indicizzi:
public function hookSbFinderAfterGetSourceProduct(array &$params)
{
$products = &$params['records'];
foreach ($products as &$product) {
$extra = $this->getExtraKeywordsForProduct($product);
if (empty($extra) || empty($product['texts'])) {
continue;
}
foreach ($product['texts'] as &$text) {
if ($text['name'] === 'description_short' && $text['iso'] === 'es') {
$text['value'] = trim($text['value'] . '. ' . implode(', ', $extra));
}
}
}
}Ad esempio, per nascondere dai risultati di ricerca un prodotto che soddisfa una condizione specifica del negozio, senza disattivarlo nel catalogo:
public function hookSbFinderAfterGetSourceProduct(array &$params)
{
$products = &$params['records'];
foreach ($products as &$product) {
if ($this->shouldBeHiddenFromSearch($product)) {
$product['platform_attributes']['active'] = false;
}
}
}Buone pratiche #
- Gli hook “dopo aver ottenuto i dati” ricevono un’intera pagina alla volta, non un record alla volta. Se devi eseguire una query al database all’interno dell’hook, eseguila una sola volta per tutti gli ID della pagina (ad esempio con un WHERE id_product IN (…)) invece di eseguire una query per ogni prodotto.
- Modifica solo le chiavi che esistono già nel record (texts, platform_attributes, ecc.); non modificare la struttura generale prevista da Finder.
- Per escludere completamente un dato, è più efficiente farlo con gli hook “prima della query” (in questo modo il dato non viene scaricato) piuttosto che filtrarlo successivamente con un hook “dopo aver ottenuto i dati”.
- Testa le modifiche con un prodotto di prova prima di applicarle in produzione.
Hai bisogno di aiuto? #
Se hai dubbi dopo aver letto la documentazione o hai bisogno di aiuto per un caso specifico, contattaci.