Magento - addStoreFilter not working? - magento

When getting a product collection in Magento, I would expect the StoreFilter to do just that, filter by the current store. But I can't get it to work.
Say I have 2 stores set up like so:
And both stores have a different root category. Main Store is the default sample data, Store2 has just one product I added. I would have thought that using the store filter, only products within the root category of the current store would show up. But I'm getting every product showing. I'm testing this by placing the following in my category view template:
$store_id = Mage::app()->getStore()->getId();
$_testproductCollection = Mage::getResourceModel('reports/product_collection')
->setStoreId($storeId)
->addStoreFilter($store_id)
->addAttributeToSelect('*');
$_testproductCollection->load();
foreach($_testproductCollection as $_testproduct){
echo $this->htmlEscape($_testproduct->getName());
};
If I echo the store ID, it's giving me the correct number. I have only one product in Store 2, so why am I getting every product from all stores returned? I can set every product in Main Store to not show in Store2 and then add a visibility filter, but that would take forever.
Also, I just noticed, if I echo the products store ID, I get the current ID, not the store it's assigned to:
echo $_testproduct->getStoreId()
What's going on?
UPDATE (April 8 2011):
OK, so I tried joining the fields so that the store_id is included (as suggested below), the section of code {{table}}.store_id = 1 is just setting all the products to have a store_id of 1. How can I just get the store_id associated with the product?
$_testproductCollection = Mage::getResourceModel('catalog/product_collection');
$_testproductCollection->joinField('store_id', 'catalog_category_product_index', 'store_id', 'product_id=entity_id', '{{table}}.store_id = 1', 'left');
$_testproductCollection->getSelect()->distinct(true);
$_testproductCollection->addAttributeToSelect('*')->load();
foreach($_testproductCollection as $_testproduct){
echo $this->htmlEscape($_testproduct->getName())."<br/>";
echo "STORE IS ".$_testproduct->getData('store_id')."<br/>";
};
If I check the catalog_category_product_index table of my db, the store_id's are correct.

$_testproductCollection should look like this $_testproductCollection = Mage::getResourceModel('reports/product_collection')->addAttributeToSelect('*')->addStoreFilter().
If You print SELECT from that collection You will see that there ain't any store column, so addStoreFilter() can't apply WHERE.
You should use joinField() on Your collection and add store_id column from catalog_product_entity_varchar table.
EDIT
Sorry to keep You waiting ;)
$collection = Mage::getResourceModel('catalog/product_collection');
$collection->joinField('store_id', 'catalog_category_product_index', 'store_id', 'product_id=entity_id', '{{table}}.store_id = 1', 'left');
$collection->getSelect()->distinct(true);
This should do the trick, but just to be sure, please check if you're getting right products :)

This worked for me:
Mage::app()->setCurrentStore($storeId);
$productCollection = Mage::getModel('catalog/product')
->getCollection()
->addStoreFilter()
->addAttributeToSelect(array('sku','price'));

OK, I think this works, haven't tested too much but seems to have done the trick. You need to first get your stores root category id, then join some fields so you have access to the products "category_id", then filter using that:
$_rootcatID = Mage::app()->getStore()->getRootCategoryId();
$_testproductCollection = Mage::getResourceModel('catalog/product_collection')
->joinField('category_id','catalog/category_product','category_id','product_id=entity_id',null,'left')
->addAttributeToFilter('category_id', array('in' => $_rootcatID))
->addAttributeToSelect('*');
$_testproductCollection->load();
foreach($_testproductCollection as $_testproduct){
echo $this->htmlEscape($_testproduct->getName())."<br/>";
};

I think
You don't need to do any joins as the magento's setStoreId() will work.
$collection = Mage::getModel("catalog/product")
->getCollection()
->setStoreId(1) //change store Id according your needs
->addAttributeToSelect(array('name','url','sku'))
->setPageSize(20);
This will get maximum 20 products from store id 1

Related

Magento - get order id from increment id

How do you get the Order Id from magento Order Increment Id?
I can use the following get the product id from SKU:
$product_id = Mage::getModel('catalog/product')->getIdBySku('ABCD1234');
The above example lets me get just the database entity_id of a product without loading everything. I want to achieve the same for order.
In a Magento model, the load method can take an optional second argument of what attribute to load by.
So, in your case, the following should work:
$order = Mage::getModel('sales/order')->load($incrementId, 'increment_id');
$id = $order->getId();
In more complex cases, e.g. where you want to load by a combination of fields, you can load a collection, and get the first element of the collection. In your case, you'd do it like this:
$order = Mage::getModel('sales/order')->getCollection()
->addFieldToFilter('increment_id', $increment_id)
->getFirstItem();
You can load an order from the IncrementId.
$orderIncrementId = "1000001";
$order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);
echo $order->getId();
If you want to fetch only order_id then simply use mysql query, if you want order_id in for loop, it is not load entire order object and it is very quick and fast, you don't need to load order object model.
$write = Mage::getSingleton('core/resource')->getConnection('core_read');
$result=$write->query("SELECT entity_id FROM `sales_flat_order` WHERE `increment_id` = 'your increment id' ");
$row = $result->fetch();
echo $row['entity_id'];

Magento 1.7 Append Complex Data

I am trying to append a category id to a large number of SKUs in Magento 1.7. I have used the Import > Append Complex Data and, although it checked the file and ran ok, it did not add these SKUs to the category I wanted them in.
So, the objective is to leave all these SKUs in the categories there are in now but add an additional category.
Any help would be appreciated. Even if it is a different method entirely.
The fastest way to do this is to directly insert this as a SQL query using:
INSERT INTO `catalog_category_product` (
`category_id` ,
`product_id` ,
`position`
)
VALUES (
'4', '34', '0'
), (
'4', '35', '0'
);
In this case, it would add the category Id of 4 to the products with Id 34 and 35. You can create a small PHP script to dynamically create such a query from your file of SKUs and Category Ids.
Reindex after your query was successfully executed.
Alternatively, using the Magento eco-system and not the database, you can do this:
$categoryIds = array();
$toBeUpdatedProducts = array(4,6,7); // all the Ids you want to update
$newCategoryId = 65; // Id of new category
foreach ($toBeUpdatedProducts as $productId) {
$product = Mage::getModel('catalog/product')->load($productId);
$categoryIds = $product->getCategoryIds();
$categoryIds[] = $newCategoryId; // Add new category to existing ones
$product->setCategoryIds($categoryIds);
$product->save();
}

Magento: Build Reviews Collection From an Array of Product IDs

I'm attempting to build a product reviews collection that combines reviews from multiple different products. I'm using the following code, but the collection only returns the reviews from the first product ID listed in the array, instead of both product IDs.
$entity_ids = "153435, 153438";
$reviewcollection = Mage::getModel('review/review')->getCollection()->addEntityFilter('product', array('in' => $entity_ids));
$reviewcollection->addStoreFilter(Mage::app()->getStore()->getId())->addStatusFilter(Mage_Review_Model_Review::STATUS_APPROVED)->setDateOrder()->addRateVotes();
$_items = $reviewcollection->getItems();`
Any ideas how to get the collection to combine the reviews from multiple product IDs?
$entity_ids = array(153435, 153438);
$reviewcollection = Mage::getModel('review/review')->getCollection()
->addStoreFilter(Mage::app()->getStore()->getId())
->addStatusFilter(Mage_Review_Model_Review::STATUS_APPROVED)
->addFieldToFilter('entity_id', Mage_Review_Model_Review::ENTITY_PRODUCT)
->addFieldToFilter('entity_pk_value', array('in' => $entity_ids))
->setDateOrder()
->addRateVotes()
;
$_items = $reviewcollection->getItems();
addEntityFilter() doesn't accept an array. You could try addFieldToFilter($field, $condition) or override the collection and write your own method. Alternatively, you could just loop through your ids and merge the results.

Getting qty of products in particular orders in Magento

I would like to ask you for piece of information that would help me to resolve my issue.
My purpose is to get from the Magento database particular product qty in every order (orders must be in exact definied status). I use batch/script standing apart from Magento but uses Mage:app. I do not know if I should start with models (which seems to be logical approach but slow in the same time) or to work directly on database (which is more difficult).
Thank you for any advice.
Regards,
Querying the database is not that complicated:
SELECT *
FROM sales_flat_order o
LEFT JOIN sales_flat_order_item i ON o.entity_id = i.order_id
WHERE o.status IN ('pending', 'processing')
AND i.product_id = <YOUR_PRODUCT_ID>
total_qty_ordered field in result will represent the ordered quantity.
Getting ordered items quantity through models is not heavy either:
<?php
require_once('app/Mage.php');
umask(0);
Mage::app('default');
$core_resource = Mage::getSingleton('core/resource');
$orders = Mage::getResourceModel('sales/order_collection');
$orders->getSelect()->joinLeft(array('ordered_products' => $core_resource->getTableName('sales/order_item')), 'main_table.entity_id = ordered_products.order_id', array('ordered_products.*'));
$orders->addAttributeToSelect('*')
->addFieldToFilter('status', array('in' => array('pending', 'processing')))
->addAttributeToFilter('main_table.store_id', Mage::app()->getStore()->getId())
->addAttributeToFilter('ordered_products.product_id', array('eq' => '2'));
foreach($orders as $order) {
echo 'Order #' . $order->getId() . ': ' . $order->getData('total_qty_ordered') . '<br/>';
}
The first approach may be a faster but the second one will be Magneto-Upgrade-Safe. So you decide which approach to use.

Magento Filter By Relative Value

I would like to filter a collection by relative value per that row. For example,
SELECT * FROM table WHERE column_1 > column_2
The only thing I know how to do in Magento would be
$q = Mage::getModel('table')->getCollection()
->addAttributeToFilter('column_1', array('gt' => $some_number));
or something of that sort. I can only give it a value to compare against, not a column name. I also looked at the Zend_Db_Select method at the where clause but didn't find anything that would help. Do I actually have to go all the way down to a direct SQL query (something which is, of course, avoided at all costs)? (I'm running Magento 1.3.2.4)
Thank you.
Try something like
$q = Mage::getModel('table')->getCollection()
->addAttributeToSelect('column_1')
->addAttributeToSelect('column_2')
->addAttributeToFilter('column_1', array('gt' => Zend_Db_Expr('`column_2`')));
OK, this is probably not the ideal solution, but it's one way of getting what you need.
This is how I got a collection of products that were on sale, where a products final price is lower than its price.
I first made a new empty data collection. Then defined the collection I was going to loop through filtering what I could first. After that I looped through that collection and any products that matched my requirements got added to the empty collection.
$this->_itemCollection = new Varien_Data_Collection();
$collection = Mage::getResourceModel('catalog/product_collection');
$collection->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());
$category = Mage::getModel('catalog/category')->load($this->getCategoryId());
$collection = $this->_addProductAttributesAndPrices($collection)
->addStoreFilter()
->addCategoryFilter($category)
->addAttributeToSort('position', 'asc');
$i=0;
foreach($collection as $product){
if($product->getFinalPrice() > $product->getPrice() && !$this->_itemCollection->getItemById($product->getId())){
$this->_itemCollection->addItem($product);
$i++;
}
if($i==$this->getProductsCount()){
break;
}
}
$this->setProductCollection($this->_itemCollection);

Resources