New Products page in Prestashop helps introduce and promote fresh offerings. How does it work from inside? Find out more about the controller, the main Product:: getNewPrоduсts method that returns the list of goods, considered by the system as new, new-products.tpl template and many more.
There is a special controller which is responsible for generating a new products page: controllers/front/NewProductsController.php. This controller implements only 2 methods: initContent and setMedia and it is inherited from the FrontController class. Let’s take a look at each of them:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public function initContent() { parent::initContent(); $this->productSort(); //set $this->orderBy and $this->orderWay variables $nbProducts = (int)Product::getNewProducts( $this->context->language->id, (isset($this->p) ? (int)($this->p) - 1 : null), (isset($this->n) ? (int)($this->n) : null), true ); //Get new products $this->context->smarty->assign(array( 'products' => Product::getNewProducts($this->context->language->id, (int)($this->p) - 1, (int)($this->n), false, $this->orderBy, $this->orderWay), //collection of products 'add_prod_display' => Configuration::get('PS_ATTRIBUTE_CATEGORY_DISPLAY'), //There is an option in the admin panel which allows you to hide the 'Add to cart' button for those items, which have been modified. Looks like it has been done to make customers view all variants of modifications, since the list displays the 'original' variant only. So the value of this option is not transmitted to the template. That is why it does not output the button for modified items (by default). 'nbProducts' => $nbProducts, //number of products 'homeSize' => Image::getSize(ImageType::getFormatedName('home')), //sets the image size 'comparator_max_item' => Configuration::get('PS_COMPARATOR_MAX_ITEM') //flag responsible for the maximum amount of items to compare. )); $this->setTemplate(_PS_THEME_DIR_.'new-products'); //template responsible for displaying the goods. } public function setMedia() { parent::setMedia(); $this->addCSS(_THEME_CSS_DIR_.'product_list.css'); //adding styles if (Configuration::get('PS_COMPARATOR_MAX_ITEM')) $this->addJS(_THEME_JS_DIR_.'products-comparison.js'); //if the configuration flag PS_COMPARATOR_MAX_ITEM is set, then connects the js file 'products-comparison.js } |
The method Product:: getNewPrоduсts takes a special place in this controller. The method returns the list of goods, considered by the system as new. Let’s take a closer look at the method, which returns the collection of new products.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
/** * Get new products * * @param integer $id_lang Language id * @param integer $pageNumber Start from (optional) * @param integer $nbProducts Number of products to return (optional) * @return array New products */ public static function getNewProducts($id_lang, $page_number = 0, $nb_products = 10, $count = false, $order_by = null, $order_way = null, Context $context = null) { if (!$context) $Context = Context: :getCоntext( ); //getting the object Context. If you are not yet familiar with this Singleton, you should consider this class more carefully. It is used everywhere and is quite useful for customizations. $front = true; //the flag which is responsible for the type of the controller if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) $front = false; if ($page_number < 0) $page_number = 0; //page number if ($nb_products < 1) $nb_products = 10; //number of products on the page if (empty($order_by) || $order_by == 'position') $order_by = 'date_add'; //sort order If (empty( $оrder_wаy)) $оrder_wаy = 'DESC'; //sorting direction if ($order_by == 'id_product' || $order_by == 'price' || $order_by == 'date_add' || $order_by == 'date_upd') $order_by_prefix = 'p'; //sorting prefix p, for the fields from the table ‘product’ else if ($order_by == 'name') $order_by_prefix = 'pl'; //sorting prefix pl, for the fields from the table ‘product_lang’ if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) die(Tools::displayError()); $Groups = FrоntCоntrоller: :getCurrentCustоmerGrоups( ); //user groups. They are required when you need to limit the number of goods to be displayed for certain user groups. $sql_groups = (count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); if (strpos($order_by, '.') > 0) { $order_by = explode('.', $order_by); $order_by_prefix = $order_by[0]; $order_by = $order_by[1]; } //if this flag is available, number of products will be returned, not the collection if ($count) { $sql = 'SELECT COUNT(p.`id_product`) AS nb FROM `'._DB_PREFIX_.'product` p '.Shop::addSqlAssociation('product', 'p').' WHERE product_shop.`active` = 1 AND DATEDIFF( product_shop.`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 '.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').' AND p.`id_product` IN ( SELECT cp.`id_product` FROM `'._DB_PREFIX_.'category_group` cg LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON (cp.`id_category` = cg.`id_category`) WHERE cg.`id_group` '.$sql_groups.' )'; return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); } $sql = new DbQuery(); //the query to database is made via the DbQuery class $sql->select( 'p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, MAX(image_shop.`id_image`) id_image, il.`legend`, m.`name` AS manufacturer_name, DATEDIFF( product_shop.`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 AS new' ); $sql->from('product', 'p'); $sql->join(Shop::addSqlAssociation('product', 'p')); $sql->leftJoin('product_lang', 'pl', ' p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl') ); $sql->leftJoin('image', 'i', 'i.`id_product` = p.`id_product`'); $sql->join(Shop::addSqlAssociation('image', 'i', false, 'image_shop.cover=1')); $sql->leftJoin('image_lang', 'il', 'i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang); $sql->leftJoin('manufacturer', 'm', 'm.`id_manufacturer` = p.`id_manufacturer`'); $sql->where('product_shop.`active` = 1'); if ($front) $sql->where('product_shop.`visibility` IN ("both", "catalog")'); $sql->where(' DATEDIFF( product_shop.`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' ); $sql->where('p.`id_product` IN ( SELECT cp.`id_product` FROM `'._DB_PREFIX_.'category_group` cg LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON (cp.`id_category` = cg.`id_category`) WHERE cg.`id_group` '.$sql_groups.')' ); $sql->groupBy('product_shop.id_product'); $sql->orderBy((isset($order_by_prefix) ? pSQL($order_by_prefix).'.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way)); $sql->limit($nb_products, $page_number * $nb_products); //Adding table data with attributes if (Combination::isFeatureActive()) { $sql->select('MAX(product_attribute_shop.id_product_attribute) id_product_attribute'); $sql->leftOuterJoin('product_attribute', 'pa', 'p.`id_product` = pa.`id_product`'); $sql->join(Shop::addSqlAssociation('product_attribute', 'pa', false, 'product_attribute_shop.default_on = 1')); } $sql->join(Product::sqlStock('p', Combination::isFeatureActive() ? 'product_attribute_shop' : 0)); $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); if ($order_by == 'price') Tools::orderbyPrice($result, $order_way); if (!$result) return false; $products_ids = array(); foreach ($result as $row) $products_ids[] = $row['id_product']; // You can thus avoid one query per product, because there will be only one query for all the products of the cart Product::cacheFrontFeatures($products_ids, $id_lang); return Product::getProductsProperties((int)$id_lang, $result); //returns modified array $result. For example, this method adds data id_imаge |
To finish with this controller we need to see what is inside the template new-products.tpl:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
{capture name=path}{l s='New products'}{/capture} {include file="$tpl_dir./breadcrumb.tpl"} {*adds the bread-crump file*} <h1>{l s='New products'}</h1> {if $products} <div class="content_sortPagiBar"> {include file="$tpl_dir./pagination.tpl"} {*The file responsible for navigation between pages*} <div class="sortPagiBar clearfix"> {include file="./product-sort.tpl"} {*sorting*} {include file="./product-compare.tpl"} {*product comparison*} {include file="./nbr-product-page.tpl"} {*number of items on the page*} </div> </div> {include file="./product-list.tpl" products=$products} {*the same file as on the catalog page*} <div class="content_sortPagiBar"> <div class="sortPagiBar clearfix"> {include file="./product-sort.tpl"} {*sorting*} {include file="./product-compare.tpl"} {*product comparison*} {include file="./nbr-product-page.tpl"} {*number of items on the page*} </div> {include file="./pagination.tpl"}"} {*The file responsible for navigation between pages*} </div> {else} <p class="warning">{l s= No new products.'}</p> {/if} |
The content of the template shows that this is just a compilation of other templates, which we saw on the catalog page. Such an approach makes the markup of the page much easier: you just need to properly markup the category template. This template, as well as the controller, is very similar to the Bestseller template and controller.
The constant PS_NB_DAYS_NEW_PRODUCT is responsible for the number of days which a product is considered as new. It can be configured in the back office under Preferences – > Products.
Denise, you can use this module – http://module-presta.com/home-tabs.html
I wonder it is possible to show number of new products added? I have 2000 new products. It will be nice to show customer this information
Hi, Alex. What would be the syntax to check only if a product is considered as new?
I’m trying the following:
(Product::getNewProducts($IdProduct) > 0) ? 1 : 0;
But it’s not working >.<
Mark Cuy,
You need to modify the query in the function, that returns a collection of new products.
How to change the controller if i want filter the product by feature alex, example i add feature publish_date in all product, and i want show only prduct with publish_date between 2010-10-01 until 2015-01-01
Thanks alex
Angela,
It is possible to implement this, however, this would require developing of a new module, that is why unfortunately I can not provide so much code in a single comment. Anyway, this looks like a good idea for a new article or even module) In case you need to implement this asap, you may contact Valerie at [email protected] for help.
Hi Alex,
your post is very interesting.
Is it possible to create a different page with the new products, one for each category?
For example, i have a store with the category: Man Woman Kids ; i would to have one different page with the new products one for man , one for woman, one for kids.
Let me know, how i can do it.
Many Thanks
Angela
Xavier,
You can use the function Product::getNewPrоduсts() to modify SQL for receiving new products. This is exactly the place which is responsible for generating the query for receiving new products.
Hi,
I would like to filter as new products products which are in stock.
How could I do that: I guess I could update a SQL statement in the NewProductsController.php page, however I have no clue what and where!
Could you help me with that (I am using 1.5.6 !)
Many thanks!
Xavier
Denise,
You can use this module – http://module-presta.com/home-carousel.html. There’s a setting there to display new products
Hello, could the new-products page also be shown directly on the homepage as index? I tried to modify homefeatured module to show new products which was working but the new-products.tpl code is not working in homefeatured.tpl. The page is missing the sort function on the top (pagination and “sort by”).