Magento get products next by price - magento

I need to get a collection of products next by price for specific product in some category.
For example: I have product White Shoes, it is located in Shoes category. I need to get next five products, that has higher price than White Shoes in Shoes category, and five products that has lower price.
Thanks for your help!

This can probably be cleaned up from an efficiency standpoint, but hopefully you get the gist of it. There are two variables you'll need to set, $product which is probably your White Shoes product as a Mage_Catalog_Model_Product object and $category which is your Shoes category as a Mage_Catalog_Model_Category object.
UPDATE
This is a better way to do it without loading the entire product collection for $category.
// Load up to 5 products with price <= $product
$fiveLower = Mage::getModel('catalog/product')->getCollection()
// Add whatever attributes you want here
->addAttributeToSelect(array(
'name',
'product_url',
'small_image',
))
// $category is an instance of Mage_Catalog_Model_Category
->addCategoryFilter($category)
// Both of these are required to get the price
->addMinimalPrice()
->addFinalPrice()
// Filter out the current product by id
->addAttributeToFilter('entity_id', array('neq' => $product->getId()));
// Filter by final_price <= $product and limit to 5.
$fiveLower->getSelect()
->having('final_price <= ?', $product->getFinalPrice())
->order('final_price')
->limit(5, 0);
// Load up to 5 products with price > $product
$fiveHigher = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect(array(
'name',
'product_url',
'small_image',
))
->addCategoryFilter($category)
->addMinimalPrice()
->addFinalPrice();
$fiveHigher->getSelect()
->having('final_price > ?', $product->getFinalPrice())
->order('final_price')
->limit(5, 0);
echo 'These are the lower priced items:' . PHP_EOL;
foreach ($fiveLower as $item) {
echo $item->getName() . ' - ' . $item->getFinalPrice() . PHP_EOL;
}
echo 'These are the higher priced items:' . PHP_EOL;
foreach ($fiveHigher as $item) {
echo $item->getName() . ' - ' . $item->getFinalPrice() . PHP_EOL;
}

I had similar task, and here what I've done:
$customerGroupId = Mage::helper('customer')->getCustomer()->getGroupId();
$websiteId = Mage::app()->getStore()->getWebsiteId();
$finalPrice = $product->getFinalPrice();
$coreResource = Mage::getSingleton('core/resource');
$adapter = $coreResource->getConnection('catalog_read');
$prevSelect = $adapter->select()
->from(array('i' => $coreResource->getTableName('catalog/product_index_price')), array())
->join(
array('p' => $coreResource->getTableName('catalog/category_product')),
'p.product_id = i.entity_id',
array('product_id')
)
->where('p.category_id = ?', $categoryId)
->where('i.customer_group_id = ?', $customerGroupId)
->where('i.website_id = ?', $websiteId)
->where('p.product_id != ?', $product->getId())
->where('i.final_price < ?', $finalPrice)
->order('i.final_price DESC')
->limit(self::PRODUCTS_BLOCK_SIZE);
$lowerIds = array_reverse($adapter->fetchCol($prevSelect));
$nextSelect = $adapter->select()
->from(array('i' => $coreResource->getTableName('catalog/product_index_price')), array())
->join(
array('p' => $coreResource->getTableName('catalog/category_product')),
'p.product_id = i.entity_id',
array('product_id')
)
->where('p.category_id = ?', $categoryId)
->where('i.customer_group_id = ?', $customerGroupId)
->where('i.website_id = ?', $websiteId)
->where('p.product_id != ?', $product->getId())
->where('i.final_price > ?', $finalPrice)
->order('i.final_price ASC')
->limit(self::PRODUCTS_BLOCK_SIZE);
$higherIds = $adapter->fetchCol($nextSelect);
$lowerSliced = array_slice($lowerIds, -self::PRODUCTS_BLOCK_SIZE);
$requiredFromHigher = self::PRODUCTS_BLOCK_SIZE - count($lowerSliced);
$similarIds = array_merge(
$lowerSliced,
array_slice($higherIds, 0, $requiredFromHigher)
);
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('name')
->addAttributeToSelect('small_image')
->addAttributeToSelect('product_url')
->addAttributeToFilter('entity_id', array('in' => $similarIds))
->setPage(1, self::PRODUCTS_BLOCK_SIZE);

Related

how I can get all product which i buy

I try write this code
public function allsalesblock(){
echo 'other block ';
$orders = Mage::getResourceModel('sales/order_collection')
->addFieldToSelect('*')
->addFieldToFilter('customer_id', Mage::getSingleton('customer/session')->getId());
->addAttributeToSort('created_at', 'DESC');
$order = Mage::getModel("sales/order")->load($orders); //load order by order id
$ordered_items = $order->getAllItems();
foreach($ordered_items as $item){
echo $item->getItemId(); //product id
echo $item->getSku();
echo $item->getQtyOrdered(); //ordered qty of item
echo $item->getName();
}
}
But this doesn't work - i see white screen. I found this code(and modification) here How can I display all products bought by a customer in magento?
You can get it using below code,
<?php
require_once('app/Mage.php'); //Path to Magento
umask(0);
Mage::app();
$email = 'albert#example.com';
$_orders = Mage::getModel('sales/order')->getCollection()->addFieldToFilter('customer_email',$email);
foreach ($_orders as $order) {
$id[]= $order->getId();
}
//print_r($id);
foreach ($id as $order_id) {
$order = Mage::getModel('sales/order')->load($order_id);
#get all items
$items = $order->getAllItems();
$itemcount= count($items);
$data = array();
$i=0;
#loop for all order items
foreach ($items as $itemId => $item)
{
$data[$i]['name'] = $item->getName();
$data[$i]['price'] = $item->getPrice();
$data[$i]['sku'] = $item->getSku();
$data[$i]['id'] = $item->getProductId();
$data[$i]['qty'] = $item->getQtyToInvoice();
}
#displaying the array in order to see the products
echo '<pre/>';print_r($data);
}
here change the email address as you want to get products which that customer bought,
$email = 'albert#example.com';

Get Number of Orders per Product

I'm trying to build an array of orders => products that I can use in reporting/updating attributes. The format I'm going for is:
//$orders[<number of orders>] = <array of product ids with this many orders>
$orders = array(
1 => array(1, 2, 3),
2 => array(4, 5)
//etc
);
So far the best I can do is
$productCollection = Mage::getModel('catalog/product')
->addAttributeToSelect("sku")
->getCollection();
$orders = array();
foreach ($productCollection as $product) {
$ordered = Mage::getResourceModel('reports/product_collection')
->addOrderedQty()
->addAttributeToFilter('sku', $product->getSku())
->setOrder('ordered_qty', 'desc')
->getFirstItem();
$qtyOrdered = $ordered->getOrderedQty();
$total = $this->_counter - (int)(!$ordered ? 0 : $qtyOrdered);
if (!is_array($orders[$total])) {
$orders[$total] = array();
}
$orders[$total][] = $product->getId();
}
But this is obviously using a lot of resources, loading the entire product collection.
I think I can get by just using
$ordered = Mage::getResourceModel('reports/product_collection')
->addOrderedQty();
But I'm having trouble returning/iterating through the results. How do I extract the information I'm looking for?
This should be better.
$orderItems = Mage::getResourceModel('sales/order_item_collection');
$result = array();
foreach ($orderItems as $item) {
$result[$item->getOrderId()][] = $item->getProductId();
}
print_r($result);
NOTE: take care about hidden order item (Ex: simple, configurable product)
$ordered = Mage::getResourceModel('reports/product_collection')
->addOrderedQty();
foreach($ordered as $order) {
$qtyOrdered = (int)$order->getOrderedQty();
if (!is_array($totals[$qtyOrdered])) {
$totals[$qtyOrdered] = array();
}
$totals[$qtyOrdered][] = $order->getEntityId();
}
Works, but it seems to be returning product Ids that don't exists anymore.

Get ProductName using Collection Magento

I've a list of product Ids and based on that product Id I want to get product Name but as the catalog_product_entity table doesn't contain the product name only sku, I'm trapped.
kindly check my code, I've tried left and right join both but not getting the name
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('name')
->getSelect()->joinRight(
array('table_alias'=>'my_table'),
'entity_id = table_alias.product_id',
array('table_alias.*')
);
$result = null;
foreach ($collection as $temp) {
$result[] = array(
'name' => $temp->getCustomer_name(),
);
}
If you want your collection to load the product name, then the first part of your code is right. Here's a simplified version:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('name');
$result = array();
foreach ($collection as $temp) {
$result[] = array('name' => $temp->getName());
}
this is how I solved it
$resource = Mage::getSingleton('core/resource');
$readResource = $resource->getConnection('core_read');
$tableName = $resource->getTableName('myTable');
$results = $readResource->select('table_alias.*')
->from($tableName)
->joinLeft(
array('table_alias'=>'catalog_product_flat_1'),
'product_id = table_alias.entity_id',
array('table_alias.*')
)->where('customer_id=?',$customerId);
$products=$readResource->fetchAll($results);
$dataList = array();
foreach($products as $row)
{
$dataList[] = array('productName'=>$row['name'],'price'=> $row['price'],'status'=>$row['status'],'myTable_id'=>$row['myTable_id']);
}

How to get views / clicks of a specific product

As the title suggests, how do I get the number of views / clicks / impressions of a specific product in Magento. Any help is welcome.
This simple example will give you a list of products that have been viewed between the dates you specify + their view counts:
$fromDate = '2010-01-01';
$toDate = now();
$viewedProducts = Mage::getResourceModel('reports/product_collection')
->addViewsCount($fromDate, $toDate);
foreach($viewedProducts as $product) {
echo "ID: " . $product->getData('entity_id') . " - View Count: " . $product->getData('views') . "<br/>";
}
It helped me, get views just for one product.
$resource = Mage::getResourceModel('reports/event');
$select = $resource->getReadConnection()->select()
->from(array('ev' => $resource->getMainTable()), array(
'product_id' => 'object_id',
'view_count' => new Zend_Db_Expr('COUNT(*)')
))
->join(
array('et' => $resource->getTable('reports/event_type')),
"ev.event_type_id=et.event_type_id AND et.event_name='catalog_product_view'",'')
->group('ev.object_id')
->where('ev.object_id IN(?)', [$entity_id])
->where('ev.logged_at >= ?', $from)
->where('ev.logged_at <= ?', $to);
$views = $resource->getReadConnection()->fetchPairs($select);
$views = !empty($views[$entity_id]) ? $views[$entity_id] : 0;

Magento filter product collection by multiple categories

Is there an easy way to filter a product collection by multiple categories? To get all items in any of the listed categories? addCategoryFilter doesn't seem to allow an array.
Is the only way to get the collections for each category of interest separately then merge them?
I understand it used to be possible with something like
addAttributeToFilter('category_ids',array('finset'=>array('1','2')))
or similar, but that this is no longer possible since 1.4.
Note: I am using 1.6, and in case it's of any use, I'm using something like this:
$product = Mage::getModel('catalog/product');
$_productCollection = $product->getCollection()
->addAttributeToSelect('*')
->addAttributeToFilter('status',1)
->addStoreFilter();
Here's a method that doesn't require modifications to core.
It's taken from this post with the addition of the 'group' clause to handle duplicate product records.
$categories = array(7,45,233);
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('*')
->joinField('category_id',
'catalog/category_product',
'category_id',
'product_id=entity_id',
null,
'left')
->addAttributeToFilter('category_id', array('in' => $categories));
$collection->getSelect()->group('e.entity_id');
The way Magento works now, is to get the Store, and on the store, you can get the categories from the storecollection like $oStoreCollection->addCategoryFilter(array('1','2'));
I came across a solution that might help you, found here at:
http://www.magentocommerce.com/boards/&/viewthread/201114/#t329230
The code they use, looks like this:
Override Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection, and add the following methods:
public function addCategoriesFilter($categories)
{
$this->_productLimitationFilters['category_ids'] = $categories;
if ($this->getStoreId() == Mage_Core_Model_App::ADMIN_STORE_ID) {
$this->_applyZeroStoreProductLimitations();
} else {
$this->_applyProductLimitations();
}
return $this;
}
protected function _applyProductLimitations()
{
$this->_prepareProductLimitationFilters();
$this->_productLimitationJoinWebsite();
$this->_productLimitationJoinPrice();
$filters = $this->_productLimitationFilters;
// Addition: support for filtering multiple categories.
if (!isset($filters['category_id']) && !isset($filters['category_ids']) && !isset($filters['visibility'])) {
return $this;
}
$conditions = array(
'cat_index.product_id=e.entity_id',
$this->getConnection()->quoteInto('cat_index.store_id=?', $filters['store_id'])
);
if (isset($filters['visibility']) && !isset($filters['store_table'])) {
$conditions[] = $this->getConnection()
->quoteInto('cat_index.visibility IN(?)', $filters['visibility']);
}
// Addition: support for filtering multiple categories.
if (!isset($filters['category_ids'])) {
$conditions[] = $this->getConnection()
->quoteInto('cat_index.category_id=?', $filters['category_id']);
if (isset($filters['category_is_anchor'])) {
$conditions[] = $this->getConnection()
->quoteInto('cat_index.is_parent=?', $filters['category_is_anchor']);
}
} else {
$conditions[] = $this->getConnection()->quoteInto('cat_index.category_id IN(' . implode(',', $filters['category_ids']) . ')', "");
}
$joinCond = join(' AND ', $conditions);
$fromPart = $this->getSelect()->getPart(Zend_Db_Select::FROM);
if (isset($fromPart['cat_index'])) {
$fromPart['cat_index']['joinCondition'] = $joinCond;
$this->getSelect()->setPart(Zend_Db_Select::FROM, $fromPart);
}
else {
$this->getSelect()->join(
array('cat_index' => $this->getTable('catalog/category_product_index')),
$joinCond,
array('cat_index_position' => 'position')
);
}
$this->_productLimitationJoinStore();
Mage::dispatchEvent('catalog_product_collection_apply_limitations_after', array(
'collection' => $this
));
return $this;
}
protected function _applyZeroStoreProductLimitations()
{
$filters = $this->_productLimitationFilters;
// Addition: supprot for filtering multiple categories.
$categoryCondition = null;
if (!isset($filters['category_ids'])) {
$categoryCondition = $this->getConnection()->quoteInto('cat_pro.category_id=?', $filters['category_id']);
} else {
$categoryCondition = $this->getConnection()->quoteInto('cat_pro.category_id IN(' . implode(',', $filters['category_ids']) . ')', "");
}
$conditions = array(
'cat_pro.product_id=e.entity_id',
$categoryCondition
);
$joinCond = join(' AND ', $conditions);
$fromPart = $this->getSelect()->getPart(Zend_Db_Select::FROM);
if (isset($fromPart['cat_pro'])) {
$fromPart['cat_pro']['joinCondition'] = $joinCond;
$this->getSelect()->setPart(Zend_Db_Select::FROM, $fromPart);
}
else {
$this->getSelect()->join(
array('cat_pro' => $this->getTable('catalog/category_product')),
$joinCond,
array('cat_index_position' => 'position')
);
}
return $this;
}
It then gets called like this:
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('*')
->distinct(true) // THIS IS WHAT YOU NEED TO ADD
->addCategoriesFilter($category->getAllChildren(true)); // Make sure you don't forget to retrieve your category here.
HTH
If you want to filter on multiple categories, using AND (so a product must be in categorie A, B and C to show up, you need to have multiple joins:
$products = Mage::getModel('catalog/product')->getCollection()
->joinField('category_id_1', 'catalog/category_product', 'category_id', 'product_id=entity_id', null, 'left')
->joinField('category_id_2', 'catalog/category_product', 'category_id', 'product_id=entity_id', null, 'left')
->addAttributeToFilter('category_id_1', array('eq' => 358))
->addAttributeToFilter('category_id_2', array('eq' => 252))
// etc...
;
I managed to resolve this (after much trial and error) with the following code:
$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToFilter('status', 1);
$collection->addAttributeToSelect(array('name','sku','price','small_image'));
// Filter by multiple categories
$collection->joinField('category_id','catalog/category_product','category_id','product_id=entity_id',null,'left');
$data_cats = $this->getRequest()->getParam('categories');
// Or $data_cats = array(85,86,87,88);
$filter_cats = array();
foreach ($data_cats as $value_cats) {
$filter_cats[] = array(
'attribute' => 'category_id',
'finset' => $value_cats
);
}
$collection->addAttributeToFilter($filter_cats);
Hope this helps someone ;)
Magento 1.8.0.0;
Flat catalog enabled in admin;
Make sure you've cached the block in which you'll place this;
Don't add this in paid themes ..
The inner join hard-coded here reproduces this:
$collection->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());
without 'cat_index.category_id=2'
$category = Mage::getModel('catalog/category')->load(100);
$allChildsIds = $category->getAllChildren($category);
$visibility = Mage::getModel('catalog/product_visibility');
$collection = Mage::getResourceModel('catalog/product_collection');
$collection = $this->_addProductAttributesAndPrices($collection)
->addStoreFilter()
->setFlag('do_not_use_category_id', true)
->setFlag('disable_root_category_filter', true)
->addAttributeToSort('created_at', 'desc');
$whereCategoryCondition = $collection->getConnection()
->quoteInto('cat_index.category_id IN(?) ', $allChildsIds);
$collection->getSelect()->where($whereCategoryCondition);
$conditions = array();
$conditions[] = "cat_index.product_id = e.entity_id";
$conditions[] = $collection->getConnection()
->quoteInto('cat_index.store_id = ? ', Mage::app()->getStore()->getStoreId());
$conditions[] = $collection->getConnection()
->quoteInto('cat_index.visibility IN(?) ', $visibility->getVisibleInCatalogIds());
$collection->getSelect()->join(
array('cat_index' => $collection->getTable('catalog/category_product_index')),
join(' AND ', $conditions),
array()
);
$collection
->setPageSize(3)
->setCurPage(1);
$collection->load();
Filter Product Collection using multiple category ids
$all_categories = array('3','13','113');
$productCollection = Mage::getModel('catalog/product')->getCollection();
$productCollection->joinField('category_id', 'catalog/category_product', 'category_id',
'product_id = entity_id', null, 'left')
->addAttributeToSelect('*')
->addAttributeToFilter('type_id', array('eq' => 'simple'))
->addAttributeToFilter('category_id', array($all_categories));
foreach($productCollection as $product)
{
echo $product->getId() .$product->getName() . "<br/>";
}
You can remove the condition for product type i.e type_id or modify it as per requirement.
Reference: https://www.fmeextensions.com/blog/get-product-collection-by-category-id-magento-2/
$ids = [1,2,3,4,5,6,7];
$collectionFactory = $objectManager->get('\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory')->create();
$products = $collectionFactory->addAttributeToSelect('*')
->addCategoriesFilter(['in' => $ids]);
foreach ($products as $product) {
echo $product->getId() . "<br />";
echo $product->getName() . "<br />";
echo $product->getProductUrl() . "<br />";
}

Resources