Jump to content

Redirigir productos descatalogados


Iván Ros Navarro

Recommended Posts

Buenos días,

 

Prestashop está mejorando mucho en optimización SEO, pero todavía está un poco verde en algunos aspectos y, a pesar de no ser un experto en SEO, se me ha dado la necesidad de redirigir productos que están descatalogados a su categoría y no a un producto en específico, dado que pueden darse casos en los que un artículo puede no ser lo suficientemente parecido a otro para "suplantarlo" y, creo más conveniente que sea el propio cliente el que elija otro artículo dentro de la misma categoría que el artículo descatalogado.

 

Pues bien, aquí tenéis un pequeño aporte que puede servirle a algunos.

 

 

En el archivo /controllers/front/ProductController.php, sobre la línea 108 hay que comentar o eliminar esta línea para los casos en los que no tenga un artículo asociado no establezca la redirección 404 y quede la redirección 301

if (!$this->product->id_product_redirected || $this->product->id_product_redirected == $this->product->id)
	$this->product->redirect_type = '404';

y cambiadla por este código para que cuando no tenga redirección 301 ni 302 sea 404

if ($this->product->redirect_type != '301' && $this->product->redirect_type != '302')
	$this->product->redirect_type = '404';

Con esto hecho, vamos a la línea 112, donde tenemos este código en la función "public function init()":

switch ($this->product->redirect_type)
{
	case '301':     
                header('HTTP/1.1 301 Moved Permanently');
		header('Location: '.$this->context->link->getProductLink($this->product->id_product_redirected));
		exit;
	break;
	case '302':
		header('HTTP/1.1 302 Moved Temporarily');
		header('Cache-Control: no-cache');
		header('Location: '.$this->context->link->getProductLink($this->product->id_product_redirected));
		exit;
	break;
	case '404':
	default:
		header('HTTP/1.1 404 Not Found');
		header('Status: 404 Not Found');
		$this->errors[] = Tools::displayError('This product is no longer available.');
	break;
}

Cambiamos el caso 301 para que quede de la siguiente forma:

case '301':
	if ($this->product->id_product_redirected){
		header('HTTP/1.1 301 Moved Permanently');
		header('Location: '.$this->context->link->getProductLink($this->product->id_product_redirected));
	} else {
		header('HTTP/1.1 301 Moved Permanently');
		header('Location: '.$this->context->link->getCategoryLink($this->product->id_category_default));
	}
	exit;
break;

Comprobamos si tenemos producto relacionado ("id_product_redirected"). Si no tenemos producto relacionado, lo redirigimos a la categoría del producto obteniendo el link con "getCategoryLink" y especificando el Id de la categoría del producto con "id_category_default".

 

Es muy sencillo pero como buen novato tardé bastante en realizarlo. Se puede hacer lo mismo en el 302 si se necesita. Aún así me falta perfeccionarlo para que incluya un mensaje que informe al cliente de que el producto está descatalogado y que se le muestra una serie de artículos de su misma categoría. Cuando lo tenga os lo pondré también, aunque si hay alguien que dé con la solución antes que yo y lo pone, agradecido.

 

Espero os sirva. Un saludo,

Iván Ros

 

 

EDITO: Como bien ha dicho ventura, esto es mejor hacerlo mediante override. Aquí lo tenéis, el archivo sería /override/controllers/front/ProductController.php. Recordad eliminar el archivo /cache/class_index.php después de la modificación para asegurarnos de que coja bien el override.

<?php

class ProductController extends ProductControllerCore
{
	/**
	 * Initialize product controller
	 * @see FrontController::init()
	 */
	public function init()
	{
		parent::init();

		if ($id_product = (int)Tools::getValue('id_product'))
			$this->product = new Product($id_product, true, $this->context->language->id, $this->context->shop->id);

		if (!Validate::isLoadedObject($this->product))
		{
			header('HTTP/1.1 404 Not Found');
			header('Status: 404 Not Found');
			$this->errors[] = Tools::displayError('Product not found');
		}
		else
		{
			$this->canonicalRedirection();
			/*
			 * If the product is associated to the shop
			 * and is active or not active but preview mode (need token + file_exists)
			 * allow showing the product
			 * In all the others cases => 404 "Product is no longer available"
			 */
			if (!$this->product->isAssociatedToShop() || !$this->product->active)
			{
				if (Tools::getValue('adtoken') == Tools::getAdminToken('AdminProducts'.(int)Tab::getIdFromClassName('AdminProducts').(int)Tools::getValue('id_employee')) && $this->product->isAssociatedToShop())
				{
					// If the product is not active, it's the admin preview mode
					$this->context->smarty->assign('adminActionDisplay', true);
				}
				else
				{
					$this->context->smarty->assign('adminActionDisplay', false);
					if ($this->product->redirect_type != '301' && $this->product->redirect_type != '302')
						$this->product->redirect_type = '404';
					
					switch ($this->product->redirect_type)
					{
						case '301':
							if ($this->product->id_product_redirected){
								header('HTTP/1.1 301 Moved Permanently');
								header('Location: '.$this->context->link->getProductLink($this->product->id_product_redirected));
							} else {
								header('HTTP/1.1 301 Moved Permanently');
								header('Location: '.$this->context->link->getCategoryLink($this->product->id_category_default));
							}
							exit;
						break;
						case '302':
							header('HTTP/1.1 302 Moved Temporarily');
							header('Cache-Control: no-cache');
							header('Location: '.$this->context->link->getProductLink($this->product->id_product_redirected));
							exit;
						break;
						case '404':
						default:
							header('HTTP/1.1 404 Not Found');
							header('Status: 404 Not Found');
							$this->errors[] = Tools::displayError('This product is no longer available.');
						break;
					}
				}
			}
			elseif (!$this->product->checkAccess(isset($this->context->customer->id) && $this->context->customer->id ? (int)$this->context->customer->id : 0))
			{
				header('HTTP/1.1 403 Forbidden');
				header('Status: 403 Forbidden');
				$this->errors[] = Tools::displayError('You do not have access to this product.');
			}
			else
			{
				// Load category
				$id_category = false;
				if (isset($_SERVER['HTTP_REFERER']) && $_SERVER['HTTP_REFERER'] == Tools::secureReferrer($_SERVER['HTTP_REFERER']) // Assure us the previous page was one of the shop
					&& preg_match('~^.*(?<!\/content)\/([0-9]+)\-(.*[^\.])|(.*)id_(category|product)=([0-9]+)(.*)$~', $_SERVER['HTTP_REFERER'], $regs))
				{
					// If the previous page was a category and is a parent category of the product use this category as parent category
					$id_object = false;
					if (isset($regs[1]) && is_numeric($regs[1]))
						$id_object = (int)$regs[1];
					elseif (isset($regs[5]) && is_numeric($regs[5]))
						$id_object = (int)$regs[5];
					if ($id_object)
					{
						$referers = array($_SERVER['HTTP_REFERER'],urldecode($_SERVER['HTTP_REFERER']));
						if (in_array($this->context->link->getCategoryLink($id_object), $referers))
							$id_category = (int)$id_object;
						elseif (isset($this->context->cookie->last_visited_category) && (int)$this->context->cookie->last_visited_category && in_array($this->context->link->getProductLink($id_object), $referers))
							$id_category = (int)$this->context->cookie->last_visited_category;
					}

				}
				if (!$id_category || !Category::inShopStatic($id_category, $this->context->shop) || !Product::idIsOnCategoryId((int)$this->product->id, array('0' => array('id_category' => $id_category))))
					$id_category = (int)$this->product->id_category_default;
				$this->category = new Category((int)$id_category, (int)$this->context->cookie->id_lang);
				if (isset($this->context->cookie) && isset($this->category->id_category) && !(Module::isInstalled('blockcategories') && Module::isEnabled('blockcategories')))
					$this->context->cookie->last_visited_category = (int)$this->category->id_category;
			}
		}
	}
}
Edited by Gorhaen (see edit history)
Link to comment
Share on other sites

  • 2 months later...

Buenas noches, no sé si será por la versión de prestashop, ya que tengo la 1.6.1.4 pero ese archivo /override/controllers/front/ProductController.php. no lo tengo dentro de la carpeta, tengo otro que se llama OrderOpcController.php, como puedo hacerlo?, gracias de antemano y saludos

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...