En este tutorial voy a mostraros cómo podemos añadir botones de navegación (Anterior y Siguiente) en cada página de producto en Prestashop para permitir una navegación más fácil a través de las categorías.
Compatibilidad: Prestashop 1.6 y 1.5
Descargar los archivos del proyectoComenzando...
Para entrar en materia tendremos que editar los siguientes archivos:
prestashop/override/classes/Product.php
prestashop/override/controllers/front/ProductController.php
prestashop/themes/default-bootstrap/product.tpl
Los archivos Product.php y ProductController.php tenemos que crearlos en las rutas indicadas.
Trabajando con el archivo Product.php
El archivo Product.php será el encargado de tomar los productos "anterior" y "posterior". La navegación se hará entre los productos de la categoría por defecto, es decir, los productos pueden estar asociados a varias categorías, pero todos tienen que estar asociados a una categoría por defecto, así que la navegación se realizará entre aquellos productos asociados a una misma categoría por defecto.
Manos a la obra
Creamos un nuevo archivo dentro de prestashop/override/classes/ y lo llamamos Product.php. Pegar el siguiente código en este archivo:
class Product extends ProductCore { }
A continuación, vamos a crear el método que necesitamos, y empezaremos por tomar la posición actual del producto en su categoría por defecto:
public function getAdjacentProducts() { $position = Db::getInstance()->getValue('SELECT position FROM '._DB_PREFIX_.'category_product WHERE id_product = ' . (int)$this->id . ' AND id_category = ' . (int)$this->id_category_default); }
Una vez que tengamos esto, podemos recuperar los productos de "anterior" y "siguiente" de la base de datos:
public function getAdjacentProducts() { //get the current position in the product's default category $position = Db::getInstance()->getValue('SELECT position FROM '._DB_PREFIX_.'category_product WHERE id_product = ' . (int)$this->id . ' AND id_category = ' . (int)$this->id_category_default); // var_dump($position); // get products that are before and after $previous = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT cp.id_product, pl.link_rewrite, cp.position, pl.name FROM '._DB_PREFIX_.'category_product cp LEFT JOIN '._DB_PREFIX_.'product_lang pl ON (cp.id_product = pl.id_product) LEFT JOIN '._DB_PREFIX_.'product p ON (cp.id_product = p.id_product) WHERE p.id_category_default = '.(int)$this->id_category_default.' AND (cp.position < '. (int)($position ) .' ) AND cp.id_category = ' . (int)$this->id_category_default .' AND pl.id_lang = '.(Context::getContext()->language->id).' ORDER BY cp.position DESC'); $next = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT cp.id_product, pl.link_rewrite, cp.position, pl.name FROM '._DB_PREFIX_.'category_product cp LEFT JOIN '._DB_PREFIX_.'product_lang pl ON (cp.id_product = pl.id_product) LEFT JOIN '._DB_PREFIX_.'product p ON (cp.id_product = p.id_product) WHERE p.id_category_default = '.(int)$this->id_category_default.' AND (cp.position > '. (int)($position ) .' ) AND cp.id_category = ' . (int)$this->id_category_default .' AND pl.id_lang = '.(Context::getContext()->language->id).' ORDER BY cp.position ASC'); return array('previous' => $previous, 'next' => $next); }
Estamos utilizando básicamente la misma consulta, tanto para el producto anterior y siguiente. Para el anterior, obtenemos el primer producto que tiene una posición más baja. Para el siguiente, la posición inmediatamente superior.
Nótese que sólo tomamos productos de la misma categoría por defecto, y es por eso que no podemos simplemente utilizar la posición +1 y la posición -1 en una única consulta (tendríamos lagunas).
Asignando los productos a la página del producto
Ahora asignaremos las variables de la página del producto. Crear el archivo ProductController.php en la ruta prestashop/override/controllers/front/. Entonces, inicializamos la anulación de clase:
class ProductController extends ProductControllerCore { public function initContent() { parent::initContent(); } }
Como podemos ver extendemos el método initContent(). Por lo tanto, dentro del método, y antes de llamar a parent::initContent();, pegar el siguiente código:
$adjacent_products = $this->product->getAdjacentProducts(); $this->context->smarty->assign(array( 'prev_product'=> $adjacent_products['previous'], 'next_product'=> $adjacent_products['next'] ));
Este override final debería tener este aspecto:
class ProductController extends ProductControllerCore { public function initContent() { $adjacent_products = $this->product->getAdjacentProducts(); $this->context->smarty->assign(array( 'prev_product'=> $adjacent_products['previous'], 'next_product'=> $adjacent_products['next'] )); parent::initContent(); } }
Es hora de agregar nuestros botones! Antes de eso, debemos borrar el archivo prestashop/cache/class_index.php para que el override pueda hacer efecto.
Añadiendo los botones en la plantilla product.tpl
La plantilla product.tpl donde debemos introducir el código, se encuentra en la carpeta de nuestro theme. Tendremos que decidir donde vamos a insertar el código de los botones. General, recomiendo añadirlos en la parte superior de la página del producto, de manera que estén en una posición accesible. Por supuesto, podemos colocarlos donde nos plazca.
En Prestashop 1.6 debemos colocar el código justo antes de esta etiqueta:
<div class="primary_block row" itemscope itemtype="http://schema.org/Product">
El código:
<!-- Navigation --> <div class="product-navigation clearfix" style="margin-bottom:20px"> {if $prev_product} <a title="{$prev_product.name}" class="btn btn-default" href="{$link->getProductLink($prev_product.id_product, $prev_product.link_rewrite)}">{l s='Previous Product'}</a> {/if} {if $next_product} <a title="{$next_product.name}" class="btn btn-default" style="float:right"href="{$link->getProductLink($next_product.id_product, $next_product.link_rewrite)}">{l s='Next Product'}</a> {/if} </div>
En Prestashop 1.5 colocaremos el código inmediatamente después de esta etiqueta:
{include file="$tpl_dir./breadcrumb.tpl"}
Y ya hemos terminado!!!
Hola, he intentado hacer esta modificación pero me sale este error
ResponderEliminarNotice: Undefined index: prev_product in /var/www/vhosts/seduci2.com/httpdocs/version2/tools/smarty/sysplugins/smarty_internal_templatebase.php(171) : eval()'d code on line 115Notice: Trying to get property of non-object in /var/www/vhosts/seduci2.com/httpdocs/version2/tools/smarty/sysplugins/smarty_internal_templatebase.php(171) : eval()'d code on line 115Notice: Undefined index: next_product in /var/www/vhosts/seduci2.com/httpdocs/version2/tools/smarty/sysplugins/smarty_internal_templatebase.php(171) : eval()'d code on line 121Notice: Trying to get property of non-object in /var/www/vhosts/seduci2.com/httpdocs/version2/tools/smarty/sysplugins/smarty_internal_templatebase.php(171) : eval()'d code on line 121
Sabes a que se debe y como solucionarlo?
Saludos
Carlos
Hola Carlos,
Eliminar¿Qué versión de Prestashop estás usando?
Hola Francisco, estoy en 1.6.0.9
ResponderEliminarHola Carlos,
EliminarSupongo que no has descargado los archivos del proyecto porque no funcionaba el enlace. Descárgalos ahora que debería funcionar. Crea los archivos en las rutas correspondientes. Luego copia el código de los archivos del proyecto y lo pegas en los archivos que tu has creado. En el de la plantilla (el tpl), pega el código necesario, no pegues todo el código del archivo. Borra también el archivo class_index.PHP de la carpeta cache. Y me comentas cómo te ha ido.
Hola, lo he podido solucionar, debia ser un problema del cache del servidor, porque despues de reiniciarlo todo a funcionado perfectamente, muchas gracias por este hack y por tu ayuda
ResponderEliminarHola Javier.
ResponderEliminarAcabo de descargar tus ficheros.
El fichero tpl descargado reside tambien en la carpeta override y tiene mucho codigo.
Mi pregunta es:
¿ Se pude overridar el fichero tpl ?
S ies asi, ¿ Con poner en dicho fichero solo las lineas de codigo que indicas es suficiente ?
Hola tocayo:
ResponderEliminarEl fichero tpl reside en el tema en cuestión. Lo que es una buena práctica (yo diría imprescindible) es duplicar el tema por defecto y trabajar sobre la copia, de esta forma si actualizas Prestashop efectivamente podría cambiar el tema por defecto, pero la copia que tu hagas a partir del tema por defecto no se actualizará, de esta forma no perderás los cambios.
Seguramente haga un pequeño tutorial sobre cómo hacer esto, es muy fácil.
Hola Francisco, muchas gracias por tu publicación, hasta hace unos días me estaba funcionando perfectamente, pero tuve que actualizar a la versión 1.6.1.11 y ahora no me funciona, he borrado la caché. Utilizo un tema diferente del default-bootstrap. Tienes alguna idea que pudo haber pasado? Gracias nuevamente
ResponderEliminarBorra el archivo prestashop/cache/class_index.php
EliminarY recarga la página.