¿Cómo puedo modificar los datos que Finder descarga de mi tienda? #
Finder descarga periódicamente los productos, categorías, pedidos y demás datos de tu tienda para poder ofrecer resultados de búsqueda. Si necesitas ajustar esa información antes de que se descargue (ocultar ciertos productos, completar un texto, excluir una característica que no aporta nada a la búsqueda, etc.), puedes hacerlo mediante los hooks que Finder dispara durante ese proceso, sin tocar el módulo de Finder ni tu catálogo real.
¿Cómo funcionan los hooks de Finder? #
PrestaShop permite que cualquier módulo «se enganche» a puntos concretos de la ejecución de otro módulo mediante hooks. Finder dispara una serie de hooks propios justo antes de consultar la base de datos y justo después de leer cada tipo de dato. Registrar un hook siempre se hace desde el método install() de un módulo, así que para escucharlos hace falta un módulo de PrestaShop propio: puedes añadirlos a uno que ya tengas instalado en tu tienda, o crear uno nuevo solo para esto.
Crear un módulo para registrar los hooks #
Es un módulo de PrestaShop estándar, sin nada especial: un nombre técnico propio, una clase que extienda Module, y en install() registrar los hooks que te interesen. Por cada hook registrado se implementa un método hook + el nombre del 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 = 'Ajustes de Finder';
$this->description = 'Ajustes propios sobre los datos que descarga Finder';
$this->ps_versions_compliancy = ['min' => '1.6', 'max' => '9.999'];
}
public function install()
{
return parent::install()
&& $this->registerHook('sbFinderAfterGetSourceProduct');
// añade aquí el resto de hooks que necesites, ver listado más abajo
}
public function uninstall()
{
return parent::uninstall();
}
public function hookSbFinderAfterGetSourceProduct(array &$params)
{
// tu lógica aquí
}
}El nombre del módulo y de la clase puedes elegirlos libremente. Solo debe ser compatible con la versión de PrestaShop de tu tienda, en PHP plano y sin dependencias de Composer. Una vez escrito, se empaqueta en un .zip y se instala desde el back office como cualquier otro módulo o se sube la carpeta sin comprimir a la carpeta modules de tu tienda en el servidor.
Hooks disponibles para excluir datos antes de consultarlos #
Estos tres hooks se disparan justo antes de que Finder construya la consulta SQL de cada tipo de dato. Permiten excluir registros completos añadiendo condiciones a la consulta:
- sbFinderBeforeObjectModelNumRowsDBQuery
- sbFinderBeforeObjectModelPaginateDBQuery
- sbFinderBeforeObjectModelSearchByFiltersAndSourceIdDBQuery
Los tres reciben los mismos parámetros: $params[‘model’] (una cadena que identifica qué se está consultando) y $params[‘query’] (un objeto DbQuery de PrestaShop, pasado por referencia, al que se le puede añadir un where()). Los valores posibles de model son: product, category, order, cms_category, cms, supplier, manufacturer, tag, attribute o product_attribute (dependiendo de la versión de PrestaShop), attribute_group, carrier, cart_rule, country, feature, feature_value, currency y group.
La tabla principal de la consulta siempre tiene el alias a (y, cuando la consulta hace join con idiomas o tiendas, esos alias son l y s). Por ejemplo, para excluir por completo unas características concretas:
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]; // IDs de características que no quieres indexar
if ($model === 'feature' && !empty($excludedIds)) {
$query->where('a.id_feature NOT IN (' . implode(', ', $excludedIds) . ')');
}
}Nota: para excluir un dato hay que registrar y responder a los tres hooks a la vez, porque Finder los usa en momentos distintos (contar resultados, paginar y buscar por filtros).
Hooks disponibles para modificar los datos ya obtenidos #
Estos hooks se disparan después de que Finder haya leído cada tipo de dato y antes de enviarlo, uno por cada fuente de datos:
- Productos: sbFinderAfterGetSourceProduct
- Categorías: sbFinderAfterGetSourceCategory
- Pedidos: sbFinderAfterGetSourceOrder
- Categorías de contenido (CMS): sbFinderAfterGetSourceCMSCategory
- Páginas de contenido (CMS): sbFinderAfterGetSourceCMS
- Proveedores: sbFinderAfterGetSourceSupplier
- Fabricantes: sbFinderAfterGetSourceManufacturer
- Etiquetas: sbFinderAfterGetSourceTag
- Atributos: sbFinderAfterGetSourceAttribute
- Combinaciones de producto: sbFinderAfterGetSourceProductAttribute
- Grupos de atributos: sbFinderAfterGetSourceAttributeGroup
- Transportistas: sbFinderAfterGetSourceCarrier
- Reglas de carrito: sbFinderAfterGetSourceCartRule
- Países: sbFinderAfterGetSourceCountry
- Características: sbFinderAfterGetSourceFeature
- Valores de características: sbFinderAfterGetSourceFeatureValue
- Monedas: sbFinderAfterGetSourceCurrency
- Grupos de clientes: sbFinderAfterGetSourceGroup
Todos reciben $params[‘records’]: un array con los registros de esa página, pasado por referencia, que se puede recorrer y modificar directamente. Cada registro trae, entre otras claves, meta_keys (por ejemplo el id_product original), texts (un array con una entrada {iso, name, value} por cada campo traducible y cada idioma) y platform_attributes (el resto de columnas de la tienda: precio, stock, si está activo, imágenes, características, etc., según el tipo de dato).
Por ejemplo, completar la descripción corta de un producto en español con información adicional antes de que Finder la indexe:
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));
}
}
}
}Por ejemplo, ocultar de las búsquedas un producto que cumpla una condición propia de la tienda, sin desactivarlo en el catálogo:
public function hookSbFinderAfterGetSourceProduct(array &$params)
{
$products = &$params['records'];
foreach ($products as &$product) {
if ($this->shouldBeHiddenFromSearch($product)) {
$product['platform_attributes']['active'] = false;
}
}
}Buenas prácticas #
- Los hooks «después de obtener los datos» reciben una página entera de golpe, no un registro cada vez. Si necesitas consultar la base de datos dentro del hook, hazlo una sola vez para todos los IDs de la página (por ejemplo con un WHERE id_product IN (…)) en vez de lanzar una consulta por producto.
- Modifica solo las claves que ya existen en el registro (texts, platform_attributes, etc.); no cambies la estructura general que espera Finder.
- Para excluir un dato por completo, es más eficiente hacerlo con los hooks «antes de consultar» (no llega a descargarse) que filtrarlo después con un hook «después de obtener los datos».
- Prueba los cambios con un producto controlado antes de publicarlos en producción.
¿Necesitas ayuda? #
Si tienes dudas tras leer la documentación o necesitas ayuda con algún caso concreto, ponte en contacto con nosotros.