Jump to content

[SOLVED] Create product list by specifying product id's


daquity36
 Share

Recommended Posts

Is it possible to create a custom product list by specifying product ids?

 

For example, if I want to display a product list of two products,

 

Can I do something like website.com/category.php?id_product=1&id_product=2 ??

 

Obviously the above doesn't work, but I am convinced there is an easy way to achieve this.

Edited by daquity36 (see edit history)

Share this post


Link to post
Share on other sites

In the same way the blocklayered module displays a subset of products (based on the filters applied) you could write a module that only displays products with certain product ids - the display side of it is trivial as all you have to do is pass the product list to the existing product-list.tpl template for display. Another "model" for this is the product compare subsystem which does something very similar (allows you to specify a set of products) but with an enhanced display format.

 

A quick proof of concept might be to replace the contents of product-comparison.tpl with the contents of product-list.tpl and see how it looks when you compare 2 products.... you might get errors as there may be smarty variables required in product-list.tpl that aren't assigned by the product comparison code.

 

I'm not sure how you would be able to get to the point of building the url in your scenario though? Is this something that you would hand-craft or is is built somehow automatically?

 

Paul

Share this post


Link to post
Share on other sites

Solution: in order to use this, type URL:

website.com/category.php?id_category=9&custom_id=1,5

where id_category can be anything and custom_ids are the ids of the products u want to display.

Only those products will be displayed.

Works for friendly url as well such as this:

website.com/9-women?custom_id=1,5

 

1)

In CategoryController.php,

public function process()
{
 parent::process();

 

add

 $products_id_array = Tools::getValue('custom_id'); //Query string for custom product list. ADDED.
 if($products_id_array)
  self::$smarty->assign('isCustomList', true);

 

change

if ($this->category->id != 1)
 $this->productListAssign();

to

if ($this->category->id != 1)
 $this->productListAssign($products_id_array);

(Add an argument)

 

2)

In function productListAssign,

change to

$this->cat_products = $this->category->getProducts((int)(self::$cookie->id_lang), (int)($this->p), (int)($this->n), $this->orderBy, $this->orderWay, false, true, false, 1, true, $products_id_array);

(Add an argument)

 

3)

Finally, go to classes/category.php

add an argument to function GetProducts

public function getProducts($id_lang, $p, $n, $orderBy = null, $orderWay = null, $getTotal = false, $active = true, $random = false, $randomNumberProducts = 1, $checkAccess = true, $products_id_array)

 

change the part where $sql is defined, to the following:

 if(!$products_id_array) //if NOT custom product list (normal category product list)
 $sql = '
 SELECT p.*, pa.`id_product_attribute`, pl.`description`, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`,
 pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, i.`id_image`, il.`legend`, m.`name` manufacturer_name,
 tl.`name` tax_name, t.`rate`, cl.`name` category_default, DATEDIFF(p.`date_add`, DATE_SUB(NOW(),
 INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 new
 FROM `'._DB_PREFIX_.'category_product` cp
 LEFT JOIN `'._DB_PREFIX_.'product` p ON (p.`id_product` = cp.`id_product`)
 LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (p.`id_product` = pa.`id_product` AND default_on = 1)
 LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (p.`id_category_default` = cl.`id_category` AND cl.`id_lang` = '.(int)$id_lang.')
 LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.')
 LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = p.`id_product` AND i.`cover` = 1)
 LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.')
 LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group` AND tr.`id_country` = '.(int)Country::getDefaultCountryId().' AND tr.`id_state` = 0)
 LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
 LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)$id_lang.')
 LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer`
 WHERE cp.`id_category` = '.(int)$this->id.($active ? ' AND p.`active` = 1' : '').'
 '.($id_supplier ? 'AND p.id_supplier = '.(int)$id_supplier : '');

 else //if custom product list. ADDED.
 {
 $sql = '
 SELECT p.*, pa.`id_product_attribute`, pl.`description`, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`,
 pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, i.`id_image`, il.`legend`, m.`name` manufacturer_name,
 tl.`name` tax_name, t.`rate`, cl.`name` category_default, DATEDIFF(p.`date_add`, DATE_SUB(NOW(),
 INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 new
 FROM `'._DB_PREFIX_.'category_product` cp
 LEFT JOIN `'._DB_PREFIX_.'product` p ON (p.`id_product` = cp.`id_product`)
 LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (p.`id_product` = pa.`id_product` AND default_on = 1)
 LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (p.`id_category_default` = cl.`id_category` AND cl.`id_lang` = '.(int)$id_lang.')
 LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.')
 LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = p.`id_product` AND i.`cover` = 1)
 LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.')
 LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group` AND tr.`id_country` = '.(int)Country::getDefaultCountryId().' AND tr.`id_state` = 0)
 LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
 LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)$id_lang.')
 LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer`
 WHERE p.`id_product` IN (' . $products_id_array . ')'.'
 AND cp.`id_category` = p.`id_category_default`'; //remove duplicates by finding only the rows where id_category = id_default_category
 }

 

And finally, I disabled pagination for custom product list page using smarty boolean {$isCustomList} because pagination doesn't really work with this solution.

 

EDIT: Change in step 2

Edited by daquity36 (see edit history)

Share this post


Link to post
Share on other sites

For pagination to work, in function getProducts in classes/category.php, find the part

if($getTotal)

and replace with

 

if ($getTotal)
if(!$products_id_array)
return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
SELECT COUNT(*)
FROM `'._DB_PREFIX_.'product` p
LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON (p.`id_product` = cp.`id_product`)
WHERE cp.`id_category` = '.(int)$this->id.($active ? ' AND p.`active` = 1' : '').'
'.($id_supplier ? 'AND p.id_supplier = '.(int)$id_supplier : ''));
else
{

return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
SELECT COUNT(*)
FROM `'._DB_PREFIX_.'product` p
WHERE p.`id_product` IN (' . $products_id_array . ')');
}

Also go to productListAssign function in CategoryController and add

$products_id_array = Tools::getValue('custom_id'); //Query string for custom product list. ADDED.

 

And replace

$this->nbProducts = $this->category->getProducts(NULL, NULL, NULL, $this->orderBy, $this->orderWay, true);

with

  if(!$products_id_array)
$this->nbProducts = $this->category->getProducts(NULL, NULL, NULL, $this->orderBy, $this->orderWay, true);
  else
$this->nbProducts = $this->category->getProducts(NULL, NULL, NULL, $this->orderBy, $this->orderWay, true, true, false, 1, true, $products_id_array);

Edited by daquity36 (see edit history)

Share this post


Link to post
Share on other sites

  • 2 months later...

First i need to say thank you for posting this solution it very useful for understand how it works a prestashop.

 

but i have question, because i think you have clearly understand about pagination.

 

This 2 lines:

 

if(!$products_id_array)
	$this->nbProducts = $this->category->getProducts(NULL, NULL, NULL, $this->orderBy, $this->orderWay, true);
  else
	$this->nbProducts = $this->category->getProducts(NULL, NULL, NULL, $this->orderBy, $this->orderWay, true, true, false, 1, true, $products_id_array);

 

If i understand well it return number of products? Or i am wrong?

 

If this is true is it necessary to call this getProducts() function? or if i have prepared array of all products in $products with can just do this:

 

$this->nbProducts = count($products);

 

for put number of total products in variable nbProducts?

Edited by anseme (see edit history)

Share this post


Link to post
Share on other sites

  • 4 weeks later...

Hi anseme,

 

Yes that assigns the correct # of products to the variable nbProducts.

If there is custom_id, then (the modified) getProducts() function will return:

 

   return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
   SELECT COUNT(*)
   FROM `'._DB_PREFIX_.'product` p
   WHERE p.`id_product` IN (' . $products_id_array . ')');

 

I don't think you can just do count($products) but I am not sure.

Share this post


Link to post
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
 Share

×
×
  • Create New...

Important Information

Cookies ensure the smooth running of our services. Using these, you accept the use of cookies. Learn More