I want to create product filters in listing pages of category using our own custom apis i have tried many things like
$layer = Mage::getModel("catalog/layer");
$category = Mage::getModel("catalog/category")->load($categoryid);
$layer->setCurrentCategory($category);
$attributes = $layer->getFilterableAttributes();
But this only loads the Filterable atrribute code for the category But we want the Filters values and count for the product collection available in that category.
Below code will load all the available options of that attribute but I want it for product collection specific
foreach($attributes as $attribute){
$options = $attribute->getSource()->getAllOptions(false);
}
Like we have Mobiles category having 1000s of mobiles and having filterable attribute Brand so i need
Brand
Brand A (100 products)
Brand B (500 products)
Brand C (400 products)
How can this be achived if i don't want to load whole product collection as loading 1000s of product will take too much time to response.
This code works for me :
public function ws_getfiter($store_id,$categoryid){
Mage::app()->setCurrentStore($store_id);
$layer = Mage::getModel("catalog/layer");
$category = Mage::getModel("catalog/category")->load($categoryid);
$layer->setCurrentCategory($category);
$attributes = $layer->getFilterableAttributes();
$filter = array();
$count = 0;
foreach ($attributes as $attribute)
{
if ($attribute->getAttributeCode() == 'price') {
$filterBlockName = 'catalog/layer_filter_price';
} elseif ($attribute->getBackendType() == 'decimal') {
$filterBlockName = 'catalog/layer_filter_decimal';
} else {
$filterBlockName = 'catalog/layer_filter_attribute';
}
$filter[$count]["code"] = $attribute->attribute_code;
$filter[$count]["type"] = $attribute->frontend_input;
$filter[$count]["label"] = $attribute->frontend_label;
$result = Mage::app()->getLayout()->createBlock($filterBlockName)->setLayer($layer)->setAttributeModel($attribute)->init();
$innercount = 0;
$filter_data = array();
foreach($result->getItems() as $option) {
$filter_data[$innercount]["count"] = $option->getCount();
$filter_data[$innercount]["label"] = $option->getLabel();
$filter_data[$innercount]["id"] = $option->getValue();
$innercount++;
}
$filter[$count]["values"] = $filter_data;
$count++;
}
return $filter;
}
But using this we are only getting single level of filter but i want it for multiple level.
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';
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']);
}
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);
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 />";
}