来自特定类别prestashop

时间:2018-04-24 11:17:18

标签: prestashop prestashop-1.7

我想从一个类别中获取新产品,因此我尝试更改控制器。

在prestashop 1.7中是NewProductsController.php,

里面有这个功能

protected function getProductSearchQuery()
{
    $query = new ProductSearchQuery();
    $query
        ->setQueryType('new-products')
        ->setSortOrder(new SortOrder('product', 'date_add', 'desc'))
    ;

    return $query;
}

我将其改为

protected function getProductSearchQuery()
{
    $query = new ProductSearchQuery();
    $query
        ->setIdCategory('MY-NEW-ID-CATEGORY')
        ->setQueryType('new-products')
        ->setSortOrder(new SortOrder('product', 'date_add', 'desc'))
    ;

    return $query;
}

但它仍然显示所有产品,而不是该类别的产品。

我决定采用不同的方式,

在Product.php中我写

public static function getNewProductsFromCategory($id_lang, $page_number = 0, $nb_products = 10, $count = false, $order_by = null, $order_way = null, $category_id = 2,  Context $context = null)
{
    $now = date('Y-m-d') . ' 00:00:00';
    if (!$context) {
        $context = Context::getContext();
    }

    $front = true;
    if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) {
        $front = false;
    }

    if ($page_number < 1) {
        $page_number = 1;
    }
    if ($nb_products < 1) {
        $nb_products = 10;
    }
    if (empty($order_by) || $order_by == 'position') {
        $order_by = 'date_add';
    }
    if (empty($order_way)) {
        $order_way = 'DESC';
    }
    if ($order_by == 'id_product' || $order_by == 'price' || $order_by == 'date_add' || $order_by == 'date_upd') {
        $order_by_prefix = 'product_shop';
    } elseif ($order_by == 'name') {
        $order_by_prefix = 'pl';
    }
    if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) {
        die(Tools::displayError());
    }

    $sql_groups = '';
    if (Group::isFeatureActive()) {
        $groups = FrontController::getCurrentCustomerGroups();
        $sql_groups = ' AND EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp
            JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.id_category = cg.id_category AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= '.(int)Configuration::get('PS_UNIDENTIFIED_GROUP')).')
            WHERE cp.`id_product` = p.`id_product`)';
    }

    if (strpos($order_by, '.') > 0) {
        $order_by = explode('.', $order_by);
        $order_by_prefix = $order_by[0];
        $order_by = $order_by[1];
    }

    $nb_days_new_product = (int) Configuration::get('PS_NB_DAYS_NEW_PRODUCT');

    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 product_shop.`id_category_default`=10)
                AND product_shop.`date_add` > "'.date('Y-m-d', strtotime('-'.$nb_days_new_product.' DAY')).'"
                '.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').'
                '.$sql_groups;
        return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
    }
    $sql = new DbQuery();
    $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`, pl.`available_now`, pl.`available_later`, image_shop.`id_image` id_image, il.`legend`, m.`name` AS manufacturer_name,
        (DATEDIFF(product_shop.`date_add`,
            DATE_SUB(
                "'.$now.'",
                INTERVAL '.$nb_days_new_product.' 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_shop', 'image_shop', 'image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop='.(int)$context->shop->id);
    $sql->leftJoin('image_lang', 'il', 'image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang);
    $sql->leftJoin('manufacturer', 'm', 'm.`id_manufacturer` = p.`id_manufacturer`');
    $sql->leftJoin('category_product', 'cp', 'cp.`id_product` = p.`id_product`');

    $sql->where('product_shop.`active` = 1' );
    $sql->where('cp.`id_category`='.(int)$category_id );

    if ($front) {
        $sql->where('product_shop.`visibility` IN ("both", "catalog")');
    }
    $sql->where('product_shop.`date_add` > "'.date('Y-m-d', strtotime('-'.$nb_days_new_product.' DAY')).'"');
    if (Group::isFeatureActive()) {
        $groups = FrontController::getCurrentCustomerGroups();
        $sql->where('EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp
            JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.id_category = cg.id_category AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1').')
            WHERE cp.`id_product` = p.`id_product`)');
    }

    $sql->orderBy((isset($order_by_prefix) ? pSQL($order_by_prefix).'.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way));
    $sql->limit($nb_products, (int)(($page_number-1) * $nb_products));

    if (Combination::isFeatureActive()) {
        $sql->select('product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, IFNULL(product_attribute_shop.id_product_attribute,0) id_product_attribute');
        $sql->leftJoin('product_attribute_shop', 'product_attribute_shop', 'p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='.(int)$context->shop->id);
    }
    $sql->join(Product::sqlStock('p', 0));

    $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);

    if (!$result) {
        return false;
    }

    if ($order_by == 'price') {
        Tools::orderbyPrice($result, $order_way);
    }
    $products_ids = array();
    foreach ($result as $row) {
        $products_ids[] = $row['id_product'];
    }
    // Thus you can 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);
}

在我的控制器中,我从产品控制器中的新功能中获取产品ID,然后获取产品属性

$products_id = Product::getNewProductsFromCategory($this->context->language->id,0, 1,false,'date_add', 'DESC',$category_ids);
$this->returnLastProductsFromCategory($products_id);


public function returnLastProductsFromCategory($products_id)
        {
            $products = Product::getProductsProperties($this->context->language->id, $products_id);
            $assembler = new ProductAssembler($this->context);
            $presenterFactory = new ProductPresenterFactory($this->context);
            $presentationSettings = $presenterFactory->getPresentationSettings();
            $presenter = new ProductListingPresenter(
                new ImageRetriever(
                    $this->context->link
                ),
                $this->context->link,
                new PriceFormatter(),
                new ProductColorsRetriever(),
                $this->context->getTranslator()
            );
            $products_for_template = [];
            foreach ($products as $rawProduct) {
                $products_for_template[] = $presenter->present(
                    $presentationSettings,
                    $assembler->assembleProduct($rawProduct),
                    $this->context->language
                );
            }
            return $this->context->smarty->assign('products', $products_for_template);
            //return $this->context->smarty->fetch('module:cmsproducts/products.tpl');
        }

它有效,但我认为与NewProductsController相比,有太多的操作。

3 个答案:

答案 0 :(得分:1)

我解决问题。方案: 在Product.php类中,我添加了一些函数,我们将几个类别作为字符串发送。

public static function getNewProductsFromCategory($id_lang, $page_number = 0, $nb_products = 10, $count = false, $order_by = null, $order_way = null, $category_ids ,  Context $context = null)
    {
        $now = date('Y-m-d') . ' 00:00:00';
        if (!$context) {
            $context = Context::getContext();
        }

        $front = true;
        if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) {
            $front = false;
        }

        if ($page_number < 1) {
            $page_number = 1;
        }
        if ($nb_products < 1) {
            $nb_products = 10;
        }
        if (empty($order_by) || $order_by == 'position') {
            $order_by = 'date_add';
        }
        if (empty($order_way)) {
            $order_way = 'DESC';
        }
        if ($order_by == 'id_product' || $order_by == 'price' || $order_by == 'date_add' || $order_by == 'date_upd') {
            $order_by_prefix = 'product_shop';
        } elseif ($order_by == 'name') {
            $order_by_prefix = 'pl';
        }
        if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) {
            die(Tools::displayError());
        }

        $sql_groups = '';
        if (Group::isFeatureActive()) {
            $groups = FrontController::getCurrentCustomerGroups();
            $sql_groups = ' AND EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp
                JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.id_category = cg.id_category AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= '.(int)Configuration::get('PS_UNIDENTIFIED_GROUP')).')
                WHERE cp.`id_product` = p.`id_product`)';
        }

        if (strpos($order_by, '.') > 0) {
            $order_by = explode('.', $order_by);
            $order_by_prefix = $order_by[0];
            $order_by = $order_by[1];
        }

        $nb_days_new_product = (int) Configuration::get('PS_NB_DAYS_NEW_PRODUCT');

        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 product_shop.`date_add` > "'.date('Y-m-d', strtotime('-'.$nb_days_new_product.' DAY')).'"
                    '.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').'
                    '.$sql_groups;
            return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
        }
        $sql = new DbQuery();
        $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`, pl.`available_now`, pl.`available_later`, image_shop.`id_image` id_image, il.`legend`, m.`name` AS manufacturer_name,
            (DATEDIFF(product_shop.`date_add`,
                DATE_SUB(
                    "'.$now.'",
                    INTERVAL '.$nb_days_new_product.' 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_shop', 'image_shop', 'image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop='.(int)$context->shop->id);
        $sql->leftJoin('image_lang', 'il', 'image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang);
        $sql->leftJoin('manufacturer', 'm', 'm.`id_manufacturer` = p.`id_manufacturer`');
        $sql->leftJoin('category_product', 'cp', 'cp.`id_product` = p.`id_product`');

        $sql->where('product_shop.`active` = 1' );

        $test = (string)$sql->where('cp.`id_category` IN ('.$category_ids.')' );

        if ($front) {
            $sql->where('product_shop.`visibility` IN ("both", "catalog")');
        }
        $sql->where('product_shop.`date_add` > "'.date('Y-m-d', strtotime('-'.$nb_days_new_product.' DAY')).'"');
        if (Group::isFeatureActive()) {
            $groups = FrontController::getCurrentCustomerGroups();
            $sql->where('EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp
                JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.id_category = cg.id_category AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1').')
                WHERE cp.`id_product` = p.`id_product`)');
        }

        $sql->orderBy((isset($order_by_prefix) ? pSQL($order_by_prefix).'.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way));
        $sql->limit($nb_products, (int)(($page_number-1) * $nb_products));

        if (Combination::isFeatureActive()) {
            $sql->select('product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, IFNULL(product_attribute_shop.id_product_attribute,0) id_product_attribute');
            $sql->leftJoin('product_attribute_shop', 'product_attribute_shop', 'p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='.(int)$context->shop->id);
        }
        $sql->join(Product::sqlStock('p', 0));

        $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);

        if (!$result) {
            return false;
        }

        if ($order_by == 'price') {
            Tools::orderbyPrice($result, $order_way);
        }
        $products_ids = array();
        foreach ($result as $row) {
            $products_ids[] = $row['id_product'];
        }
        // Thus you can 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);
    }

从主类别生成id子类别我在类NewProductsControllerCore中添加函数并在查询中设置 - &gt; setIdsCategories($ categories_ids)

public function getChildrenCategories($category_id) 
     {
        $this->category = new Category((int) $category_id, (int) $this->context->cookie->id_lang);
        $subcategories = $this->category->getSubCategories($this->context->language->id, true);
        if($subcategories) {
            foreach($subcategories as $subcategory) {
                $source2 = $this->getChildrenCategories($subcategory["id_category"]);
                $source .= (string)$subcategory["id_category"].",".$source2; 
            }
        }
        $source = rtrim($source, ',');
        return $source;
     }

在类ProductSearchQuery.php

    private $ids_categories; 

 public function setIdsCategories($ids_categories)
    {
        $this->ids_categories = $id_categories;
        return $this;
    }

     public function getIdsCategories()
    {

        var_dump($this->ids_categories);
        return $this->ids_categories;
    }

在NewProductsProductSearchProvider.php

 private function getProductsOrCount(
        ProductSearchContext $context,
        ProductSearchQuery $query,
        $type = 'products'
    ) {
        return Product::getNewProductsFromCategory(
            $context->getIdLang(),
            $query->getPage(),
            $query->getResultsPerPage(),
            $type !== 'products',
            $query->getSortOrder()->toLegacyOrderBy(),
            $query->getSortOrder()->toLegacyOrderWay(),
            $query->getIdsCategories() // Added categories
        );
    }
  

但仍然是问题。分页不正常。我只有一个产品,但分页显示12.如果我点击下一页,则会显示所有产品。

答案 1 :(得分:0)

Controller NewProductsController.php最终依赖于Product.php控制器并使用方法getNewProducts()。您可以通过文件src/Adapter/NewProducts/NewProductsProductSearchProvider.php来关注此关系。所以,也许只有你可以做的是简化你的实现,它是修改一个默认方法getNewProducts()并添加一些额外的变量,它将指出只搜索一个类别或全部。

答案 2 :(得分:0)

我正在使用prestashop 1.7.4,并希望具有按类别显示新产品的相同功能。上面的两个答案都有帮助。我为相同创建了product.php覆盖。如果有id,并且是有效的类别,那么我也会寻找子类别。然后相应地修改查询。这是product.php覆盖文件。希望对您有所帮助。

<?php
/**
 * This override is developed to take care of new products by category.
    @ id From URL - which is category id
 * If the category id is validated, then looks for subcategories 
 * and creates a comma seperated string that contains category and all the subcategories under it.

 */

if (!defined('_CAN_LOAD_FILES_'))
exit;

class Product extends ProductCore
{


    /**
    * Get new products
    *
    * @param int $id_lang Language id
    * @param int $pageNumber Start from (optional)
    * @param int $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)
    {
        $now = date('Y-m-d') . ' 00:00:00';
        if (!$context) {
            $context = Context::getContext();
        }

        $front = true;
        if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) {
            $front = false;
        }

        if ($page_number < 1) {
            $page_number = 1;
        }
        if ($nb_products < 1) {
            $nb_products = 10;
        }
        if (empty($order_by) || $order_by == 'position') {
            $order_by = 'date_add';
        }
        if (empty($order_way)) {
            $order_way = 'DESC';
        }
        if ($order_by == 'id_product' || $order_by == 'price' || $order_by == 'date_add' || $order_by == 'date_upd') {
            $order_by_prefix = 'product_shop';
        } elseif ($order_by == 'name') {
            $order_by_prefix = 'pl';
        }
        if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) {
            die(Tools::displayError());
        }

        $sql_groups = '';
        if (Group::isFeatureActive()) {
            $groups = FrontController::getCurrentCustomerGroups();
            $sql_groups = ' AND EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp
                                JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.id_category = cg.id_category AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= '.(int)Configuration::get('PS_UNIDENTIFIED_GROUP')).')
                                WHERE cp.`id_product` = p.`id_product`)';
        }

        if (strpos($order_by, '.') > 0) {
            $order_by = explode('.', $order_by);
            $order_by_prefix = $order_by[0];
            $order_by = $order_by[1];
        }

        $nb_days_new_product = (int) Configuration::get('PS_NB_DAYS_NEW_PRODUCT');

        // changes to incorporate new products by category        
        $catId = Tools::getValue('id');
        $category = new Category((int)$catId, (int)$id_lang);
        if ( ! Validate::isLoadedObject($category)) {
            // not valid category
            // kill catagory id
            $catId = "";
        }

        if($catId && $catId!="") {
            $categories_ids = self::getChildrenCategories($catId);
            //echo "$catId, $categories_ids <br>";            
        }        

        if ($count) {
            $sql = 'SELECT COUNT(DISTINCT p.`id_product`) AS nb
                    FROM `'._DB_PREFIX_.'product` p
                    '.Shop::addSqlAssociation('product', 'p');
            if($catId && $catId!="") {
                $sql .= ' LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON ( p.`id_product` = cp.`id_product`)';                
            }
            $sql .= ' WHERE product_shop.`active` = 1';
            if($catId && $catId!="") {
                $sql .= ' AND p.`id_product` = cp.`id_product` ';
                $sql .= ' AND cp.`id_category` IN ('.$categories_ids.') ';
            }
            $sql .= ' AND product_shop.`date_add` > "'.date('Y-m-d', strtotime('-'.$nb_days_new_product.' DAY')).'"
                    '.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').'
                    '.$sql_groups;

            // echo $sql ."<br>";
            return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
        }
        $sql = new DbQuery();
        $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`, pl.`available_now`, pl.`available_later`, image_shop.`id_image` id_image, il.`legend`, m.`name` AS manufacturer_name,
                        (DATEDIFF(product_shop.`date_add`,
                                DATE_SUB(
                                        "'.$now.'",
                                        INTERVAL '.$nb_days_new_product.' 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_shop', 'image_shop', 'image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop='.(int)$context->shop->id);
        $sql->leftJoin('image_lang', 'il', 'image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang);
        $sql->leftJoin('manufacturer', 'm', 'm.`id_manufacturer` = p.`id_manufacturer`');

        // changes to incorporate new products by category        
        $catId = Tools::getValue('id');

        if($catId && $catId!="") {
            $sql->leftJoin('category_product', 'catp', 'catp.`id_product` = p.`id_product`');
            $test = (string)$sql->where('catp.`id_category` IN ('.$categories_ids.')' );            
        }

        $sql->where('product_shop.`active` = 1');

        if ($front) {
            $sql->where('product_shop.`visibility` IN ("both", "catalog")');
        }
        $sql->where('product_shop.`date_add` > "'.date('Y-m-d', strtotime('-'.$nb_days_new_product.' DAY')).'"');
        if (Group::isFeatureActive()) {
            $groups = FrontController::getCurrentCustomerGroups();
            $sql->where('EXISTS(SELECT 1 FROM `'._DB_PREFIX_.'category_product` cp
                                JOIN `'._DB_PREFIX_.'category_group` cg ON (cp.id_category = cg.id_category AND cg.`id_group` '.(count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1').')
                                WHERE cp.`id_product` = p.`id_product`)');
        }

        $sql->groupBy('p.`id_product`');

        $sql->orderBy((isset($order_by_prefix) ? pSQL($order_by_prefix).'.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way));
        $sql->limit($nb_products, (int)(($page_number-1) * $nb_products));

        if (Combination::isFeatureActive()) {
            $sql->select('product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, IFNULL(product_attribute_shop.id_product_attribute,0) id_product_attribute');
            $sql->leftJoin('product_attribute_shop', 'product_attribute_shop', 'p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='.(int)$context->shop->id);
        }
        $sql->join(Product::sqlStock('p', 0));

        // echo "sql=" . $sql ."<br>";

        $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);

        if (!$result) {
            return false;
        }

        if ($order_by == 'price') {
            Tools::orderbyPrice($result, $order_way);
        }
        $products_ids = array();
        foreach ($result as $row) {
            $products_ids[] = $row['id_product'];
        }
        // Thus you can 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);
    }    



        public function getChildrenCategories($category) 
     {
        // get category - sub category list in a comma seperated string
        $id_category = $category .',';
        $sql = "SELECT a.`id_category`, `active`  FROM `ps_category` a LEFT JOIN `ps_category_lang` b ON (b.`id_category` = a.`id_category` AND b.`id_lang` = 1 AND b.`id_shop` = 1) LEFT JOIN `ps_category_shop` sa ON (a.`id_category` = sa.`id_category` AND sa.id_shop = 1) WHERE 1 AND `id_parent` = $category ";
        $subcats_in_cat = Db::getInstance()->executeS($sql);

        foreach($subcats_in_cat as $subcat) {
            // echo $subcat ."<br>";
            $id_category .=  $subcat["id_category"] . ',' ;
            $sql = "SELECT a.`id_category`, `active`  FROM `ps_category` a LEFT JOIN `ps_category_lang` b ON (b.`id_category` = a.`id_category` AND b.`id_lang` = 1 AND b.`id_shop` = 1) LEFT JOIN `ps_category_shop` sa ON (a.`id_category` = sa.`id_category` AND sa.id_shop = 1) WHERE 1 AND `id_parent` = $subcat[id_category] ";
            $subSubcats_in_cat = Db::getInstance()->executeS($sql);                        

            foreach($subSubcats_in_cat as $subSubcat) {
                $id_category .=  $subSubcat["id_category"] . ',' ;
            }
        }
        //echo "$id_category <br>";

        $id_category = substr($id_category, 0, -1);
        $id_category = "$id_category";        

        return $id_category;

     }


}