I use product meta total_sales to display the total sales of a product, on the single product page in WooCommerce:
add_action( 'woocommerce_single_product_summary', 'wc_product_sold_count', 11 );
function wc_product_sold_count() {
global $product;
$units_sold = get_post_meta( $product->get_id(), 'total_sales', true );
echo '<p>' . sprintf( __( 'Units Sold: %s', 'woocommerce' ), $units_sold ) . '</p>';
}
But when some orders are canceled, the total sales are not automatically decreased. So, how can I get the total sales based on order status in WooCommerce?
To obtain the total sales, based on order statuses, you will have to use a custom function:
function get_product_total_sales_by_order_status( $product_id, $order_statuses ) {
global $wpdb;
return $wpdb->get_var( $wpdb->prepare("
SELECT SUM( opl.product_qty )
FROM {$wpdb->prefix}wc_order_product_lookup as opl
INNER JOIN {$wpdb->prefix}posts as p
ON opl.order_id = p.ID
AND p.post_status IN ( 'wc-" . implode( "', 'wc-", $order_statuses ) . "' )
AND opl.product_id = %d
", $product_id ) );
}
Which can then be used as:
// Set the product ID
$p_id = 30;
// Set the orders statuses (without wc-)
$statuses = array( 'on-hold', 'processing', 'completed' );
// Call function, display result
echo get_product_total_sales_by_order_status( $p_id, $statuses );
Or in your specific case:
function action_woocommerce_single_product_summary() {
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Set the orders statuses (without wc-)
$statuses = array( 'completed' );
// Call function
$total_sales = get_product_total_sales_by_order_status( $product->get_id(), $statuses );
// Display result
if ( $total_sales >= 1 ) {
echo sprintf( __( 'Total sales: %d', 'woocommerce' ), $total_sales );
} else {
echo __( 'N/A', 'woocommerce' );
}
}
}
add_action( 'woocommerce_single_product_summary', 'action_woocommerce_single_product_summary', 11 );
I want get new products from a category, so I tried to change the controller.
In prestashop 1.7 is NewProductsController.php,
And inside there is this function
protected function getProductSearchQuery()
{
$query = new ProductSearchQuery();
$query
->setQueryType('new-products')
->setSortOrder(new SortOrder('product', 'date_add', 'desc'))
;
return $query;
}
And I changed it into
protected function getProductSearchQuery()
{
$query = new ProductSearchQuery();
$query
->setIdCategory('MY-NEW-ID-CATEGORY')
->setQueryType('new-products')
->setSortOrder(new SortOrder('product', 'date_add', 'desc'))
;
return $query;
}
But it is still showing all the products, not the products from that category.
I decided to use a different way,
In Product.php I write
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);
}
And in my controller I get the products id's from my new function in product controller and then getting products attributes
$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');
}
It's working, but I think there are too many operations comparing to NewProductsController.
I solve problem. Solution :
In class Product.php i add function to which we send several categories as a string.
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);
}
To generate ids children categories from main category i add function in class NewProductsControllerCore and set in query ->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;
}
In class 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;
}
And in 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
);
}
But still is problem. Pagination not working properly. I have only one product but pagination showing 12. If i click next page, then all products appear.
Controller NewProductsController.php eventually relies on Product.php controller and use a method getNewProducts(). You can follow this relation through a file src/Adapter/NewProducts/NewProductsProductSearchProvider.php. So, maybe only what you can do to simplify your implementation it is to modify a default method getNewProducts() and add some extra variable which will point out to search throughout only one category or all.
I am using prestashop 1.7.4 and wanted the same functionality of displaying new products by category. Both the answers above helped. I created product.php override for the same. If there is id, and is a valid category, then I look for subcategories too. And then modify the query accordingly. This is the product.php override file. Hope this helps..
<?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;
}
}
I am more than novice in php, I understand parts of the code but most do not understand.
I'm modifying a module that exports PrestaShop products to a PDF based on the selected category.
Now, I want the "get" function to get all the active products, but not those that are enabled as "online_only".
The part of the code that calls the products is this:
public function getContent()
{
$context = Context::getContext();
$langmod = $context->langmod;
$products = '';
$i = 0;
foreach (Tools::getValue('categoryBox') as $osque) {
$productget = Product::getProducts(Context::getContext()->language->id, 0, 0, 'id_product', 'ASC', $osque, $active = true);
$products[$i]['products'] = $productget;
$id_lang = Context::getContext()->language->id;
$sql = '
SELECT `name`
FROM `'._DB_PREFIX_.'category_lang`
WHERE `id_category` = '.(int)$osque.'
AND `id_lang` = '.(int)$id_lang;
$name = Db::getInstance()->getValue($sql);
$products[$i]['categorie'] = $name;
$i++;
}
The boolean variable that checks this is:
online_only = true
online_only = false
So i tried modifyng this line of code:
$productget = Product::getProducts(Context::getContext()->language->id, 0, 0, 'id_product', 'ASC', $osque, $active = true, $online_only = false);
But I get a blank page..
Any help?
Thanks for your time :)
Try with this override (in override/classes/Product.php):
<?php
class ProductCore extends ProductCore
{
public static function getProducts($id_lang, $start, $limit, $order_by, $order_way, $id_category = false,
$only_active = false, Context $context = null, $pdf = false)
{
if (!$context)
$context = Context::getContext();
$front = true;
if (!in_array($context->controller->controller_type, array('front', 'modulefront')))
$front = false;
if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way))
die (Tools::displayError());
if ($order_by == 'id_product' || $order_by == 'price' || $order_by == 'date_add' || $order_by == 'date_upd')
$order_by_prefix = 'p';
else if ($order_by == 'name')
$order_by_prefix = 'pl';
else if ($order_by == 'position')
$order_by_prefix = 'c';
if (strpos($order_by, '.') > 0)
{
$order_by = explode('.', $order_by);
$order_by_prefix = $order_by[0];
$order_by = $order_by[1];
}
$sql = 'SELECT p.*, product_shop.*, pl.* , m.`name` AS manufacturer_name, s.`name` AS supplier_name
FROM `'._DB_PREFIX_.'product` p
'.Shop::addSqlAssociation('product', 'p').'
LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` '.Shop::addSqlRestrictionOnLang('pl').')
LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`)
LEFT JOIN `'._DB_PREFIX_.'supplier` s ON (s.`id_supplier` = p.`id_supplier`)'.
($id_category ? 'LEFT JOIN `'._DB_PREFIX_.'category_product` c ON (c.`id_product` = p.`id_product`)' : '').'
WHERE pl.`id_lang` = '.(int)$id_lang.
($id_category ? ' AND c.`id_category` = '.(int)$id_category : '').
($pdf ? ' AND p.`online_only` = 0' : '').
($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').
($only_active ? ' AND product_shop.`active` = 1' : '').'
ORDER BY '.(isset($order_by_prefix) ? pSQL($order_by_prefix).'.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way).
($limit > 0 ? ' LIMIT '.(int)$start.','.(int)$limit : '');
$rq = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
if ($order_by == 'price')
Tools::orderbyPrice($rq, $order_way);
foreach ($rq as &$row)
$row = Product::getTaxesInformations($row);
return ($rq);
}
}
And with in your code :
$productget = Product::getProducts(Context::getContext()->language->id, 0, 0, 'id_product', 'ASC', $osque, true, null, true);
To avoid the hassle of caching thought to delete the file class_index.php in the cache folder at the root of your site.
Regards
I have the following method in a controller of my Yii app.
public function actionManage($typeid=0, $locationid=0, $page=1, $rows=12, $sidx='date_input', $sord='desc', $kategori='')
{
if (Yii::app()->request->isAjaxRequest) {
// Jika dilakukan operasi 'edit' pada row
if (isset($_REQUEST['oper']))
{
$oper = $_REQUEST['oper'];
$id = $_REQUEST['id'];
if ($oper == 'edit')
{
$value = $_REQUEST['value'];
$record = InputData::model()->findByPk($id);
$record->value = $value;
$record->update();
}
if($oper == 'delete'){
$model = InputData::model()->findByPk($id);
$model->delete();
}
}
// inisialisasi criteria query
$criteria = new CDbCriteria();
$criteria->order = "$sidx $sord";
// filter lokasi
if (is_numeric($locationid) && $locationid !== 0)
{
$criteria->with = array('data'=>array(
'condition'=>'data.locationid=:locationid',
'params'=>array(':locationid'=>$locationid)
));
} else {
if (is_numeric($typeid) && $typeid !== 0)
{
$criteria->with = array('data.location'=>array(
'with'=>array(
'type'=>array(
'condition'=>'type.typeid=:typeid',
'params'=>array(':typeid'=>$typeid)
)
)
));
} else {
$criteria->with = array('data.location'=>array(
'with'=>array(
'type'=>array(
'condition'=>'type.type_desc=:type_desc',
'params'=>array(':type_desc'=>$kategori)
)
)
));
}
}
// filter range tanggal
if (isset($_REQUEST['startdate'], $_REQUEST['enddate']))
{
$startdate = $_REQUEST['startdate'];
$enddate = $_REQUEST['enddate'];
$criteria->condition = 'date_input <= :enddate AND date_input >= :startdate';
$criteria->params = array(':startdate'=>$startdate, ':enddate'=>$enddate);
}
if(isset($_REQUEST['dataid'])){
$dataid = $_REQUEST['dataid'];
$criteria->addCondition("dataid = $dataid");
}
$dataProvider = new CActiveDataProvider('InputData', array(
'criteria'=>$criteria,
'pagination'=>array(
'currentPage'=>$page-1,
'pageSize'=>$rows
)
));
$count = $dataProvider->totalItemCount;
$total_pages = $count > 0 ? ceil($count/$rows) : 0;
if ($page > $total_pages) $page=$total_pages;
// generate response untuk jqgrid
$response = new stdClass();
$response->page = $page;
$response->total = $total_pages;
$response->records = $count;
foreach($dataProvider->getData() as $row)
{
$response->rows[] = array(
'id'=>$row->inputdataid,
'cell'=>array(
$row->inputdataid,
$row->date_input,
$row->time_input,
$row->data->location->location_name,
$row->data->data_name,
$row->data->variable->var_name,
round($row->value, 3),
$row->data->variable->unit->uom_name,
($row->inputOfficer !== NULL ? $row->inputOfficer->officer_name:''),
'<i class="fa fa-pencil-square-o"></i> Edit <i class="fa fa-trash-o"></i> Delete'
)
);
}
echo json_encode($response);
} else {
$url = $this->createUrl("dataAir/manage");
$delurl = $this->createUrl("dataAir/deleteRow");
$startdate = '2013-01-01';
$enddate = date_format(new DateTime(), 'Y-m-d');
$this->render('jqgrid', array(
'kategori'=>$kategori,
'url'=>$url,
'delurl'=>$delurl,
'startdate'=>$startdate,
'enddate'=>$enddate
));
}
}
this line causing the problem
if(isset($_REQUEST['dataid'])){
$dataid = $_REQUEST['dataid'];
$criteria->addCondition("dataid = $dataid");
}
when, I remove those lines the method work just fine. what could be the problem causing ambigous colum name? here is the error log
SELECT COUNT(DISTINCT "t"."inputdataid") FROM "app_inputdata" "t" LEFT OUTER JOIN "app_ref_periodicdata" "data" ON ("t"."dataid"="data"."dataid") WHERE ((date_input <= :enddate AND date_input >= :startdate) AND (dataid = 7)) AND (data.locationid=:locationid). Bound with :startdate='2013-01-01', :enddate='2015-02-02', :locationid='6'
You need to add the table alias t to your condition:
$criteria->addCondition("t.dataid = $dataid");
Also, since $dataid is being obtained from a $_REQUEST it is best to pass it as a parameter. This can be done in two ways:
$criteria->addCondition("t.dataid = :dataid", [":dataid" => $dataid]);
$criteria->compare("t.dataid", $dataid);
you have used table aliases,
'with'=>array(
'type'=>array(
'condition'=>'type.type_desc=:type_desc', <<- I mean here you have used alias : type
'params'=>array(':type_desc'=>$kategori)
)
you just have to remember that the main model that you are working with, will always need alias t to unambigufy! (not sure if that is an actual word :D )