onchage dropdown data not getting refreshed in codeigniter - sql

I have following code to load data in website based on location selected, on change the ajax is getting fired and getting value in controller and from controller to model and going into where clause for sql by the result of sql is not getting showed on website.But always enters into else loop of model
View:
$(document).on('change','#delvloc',function(e){
e.preventDefault(); // stops the jump when an anchor clicked.
var title = this.value; // anchors do have text not values.
$.ajax({
url: 'index.php?route=product/category/newfunc',
data: {'title': title}, // change this to send js object
type: "get",
success: function(data){
//document.write(data); just do not use document.write
console.log(data);
}
});
});
Controller:
public function newfunc(){
$data = array(
'title' => $this->request->get['title']
);
$this->load->model('catalog/product');
$this->model_catalog_product->getProducts($data);
}
Model:
public function getProducts($data = array()) {
$sql="SELECT p.product_id,p.city, (SELECT AVG(rating) AS total FROM monster_review r1 WHERE r1.product_id = p.product_id AND r1.status = '1' GROUP BY r1.product_id) AS rating, (SELECT price FROM monster_product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1) AS discount, (SELECT price FROM monster_product_special ps WHERE ps.product_id = p.product_id AND ps.customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special FROM monster_product p LEFT JOIN monster_product_description pd ON (p.product_id = pd.product_id) LEFT JOIN monster_product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '0'"
if (!empty($data['title'])) {
$sql .= " and p.city='". $data['title']. "' GROUP BY p.product_id";
}
else{$sql .= " and p.city='Pune' GROUP BY p.product_id";}
}
My HTML:
Delivery Location:
<select name="delvloc" id="delvloc" style="width: 100px;" ">
<?php foreach ($city as $user_group) { ?>
<?php if ($user_group['city'] == $user_group_id) { ?>
<option value="<?php echo $user_group['user_group_id']; ?>" selected="selected"><?php echo $user_group['city']; ?></option>
<?php } else { ?>
<option value="<?php echo $user_group['city']; ?>"><?php echo $user_group['city']; ?></option>
<?php } ?>
<?php } ?>
</select>
</li>

In Model
function getProducts($data) {
$sql="SELECT p.product_id,p.city, (SELECT AVG(rating) AS total FROM monster_review r1 WHERE r1.product_id = p.product_id AND r1.status = '1' GROUP BY r1.product_id) AS rating, (SELECT price FROM monster_product_discount pd2 WHERE pd2.product_id = p.product_id AND pd2.customer_group_id = '1' AND pd2.quantity = '1' AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW()) AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW())) ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1) AS discount, (SELECT price FROM monster_product_special ps WHERE ps.product_id = p.product_id AND ps.customer_group_id = '1' AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())) ORDER BY ps.priority ASC, ps.price ASC LIMIT 1) AS special FROM monster_product p LEFT JOIN monster_product_description pd ON (p.product_id = pd.product_id) LEFT JOIN monster_product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '1' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '0'"; # Mssing ; here
if (!empty($data['title']))
{
$sql .= " and p.city='". $data['title']. "' GROUP BY p.product_id";
}
else{
$sql .= " and p.city='Pune' GROUP BY p.product_id";
}
$query = $this->db->query($sql);
$result = $query->result_array();
return $result;
}
In Controller
function newfunc()
{
$data = array(
'title' => $this->request->get['title']
);
$this->load->model('catalog/product');
$result = $this->model_catalog_product->getProducts($data);
$response['data'] = '';
if (empty($result))
{
$response['data'] = false;
}
else {
$response['data'] = $result;
}
echo json_encode($response);
}

Related

Get product total sales based on order status in WooCommerce

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 );

New products from specific category prestashop

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;
}
}

get table rate shipping data in Woocommerce REST API

I am trying to get all active shipping methods in Woocommerce REST API. How can I achieve this. I am new to woocommerce REST API, Any help is much appreciated.
I want response something like this -
{
"shipping_methods": {
"method_id": "method_title"
}
}
I , finally, come up with the solution. It may help others.
Below is complete code to get all table rate shipping data including shipping zones, shipping methods by zone and rates by zone -
header('Content-type: application/json');
$json_file=file_get_contents('php://input');
$jsonvalue= json_decode($json_file,true);
global $wpdb;
global $woocommerce;
$active_methods = array();
$shipping_methods = $woocommerce->shipping->load_shipping_methods();
//echo "<pre>";print_r($shipping_methods);
foreach ( $shipping_methods as $id => $shipping_method ) {
if ( isset( $shipping_method->enabled ) && 'yes' === $shipping_method->enabled ) {
$data_arr = array( 'title' => $shipping_method->title, 'tax_status' => $shipping_method->tax_status );
if($id=='table_rate'){
$raw_zones = $wpdb->get_results("SELECT zone_id, zone_name, zone_order FROM {$wpdb->prefix}woocommerce_shipping_zones order by zone_order ASC;");
//echo "<pre>";print_r($raw_zones);
$shipping = array();
$shippingarr = array();
foreach ($raw_zones as $raw_zone) {
$zones = new WC_Shipping_Zone($raw_zone->zone_id);
$zone_id = $zones->zone_id;
$zone_name = $zones->zone_name;
$zone_enabled = $zones->zone_enabled;
$zone_type = $zones->zone_type;
$zone_order = $zones->zone_order;
$shipping['zone_id'] = $zone_id;
$shipping['zone_name'] = $zone_name;
$shipping['zone_enabled'] = $zone_enabled;
$shipping['zone_type'] = $zone_type;
$shipping['zone_order'] = $zone_order;
$shipping_methods = $zones->shipping_methods;
foreach($shipping_methods as $shipping_method){
$methodid = $shipping_method["number"];
$raw_rates[$methodid]['rates'] = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}woocommerce_shipping_table_rates WHERE shipping_method_id={$methodid};",ARRAY_A);
}
$shipping['shipping_methods'] = $raw_rates;
$raw_country = $wpdb->get_results("SELECT location_code FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE zone_id={$zone_id};",ARRAY_N);
$shipping['countries'] = $raw_country;
$shippingarr[] = $shipping;
}
$data_arr['shipping_zones'] = $shippingarr;
}
$active_methods[ $id ] = $data_arr;
}
}
if(!empty($shippingarr)){
$result['success']='true';
$result['error']="0";
$result['msg']='Shipping methos found.';
$result['data']=$active_methods;
}else{
$result['success']='true';
$result['error']="0";
$result['msg']='Shipping methos found.';
$result['data']= array();
}
echo json_encode($result); `

Filter products by attribute in PrestaShop in php

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

CDbCriteria throwing column name is ambigous

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 )