Añadir botones de navegación (anterior y siguiente) en la página de producto de Prestashop 1.6

17 noviembre, 2014 |

Si te gusta, compártelo ;)

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.

Botones anterior y siguiente en página de producto de Prestashop

Compatibilidad: Prestashop 1.6 y 1.5

Descargar los archivos del proyecto

Comenzando...

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']
  ));
No hay nada especial aquí, sólo tenemos que utilizar el método creado anteriormente y, a continuación, asignar los productos "anteriores" y "siguientes".

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

9 comentarios:

  1. Hola, he intentado hacer esta modificación pero me sale este error
    Notice: 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

    ResponderEliminar
  2. Respuestas
    1. Hola Carlos,
      Supongo 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.

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

    ResponderEliminar
  4. Hola Javier.
    Acabo 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 ?

    ResponderEliminar
  5. Hola tocayo:

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

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

    ResponderEliminar
    Respuestas
    1. Borra el archivo prestashop/cache/class_index.php
      Y recarga la página.

      Eliminar