Magento - Select stock status in category->getProductCollection - magento

I am trying to get the stock status of all products within a particular category. My current code is below but getIsInStock is not part of the default collection. How can i get this value in the same way as ->addAttributeToSelect('product_type')
$collection = Mage::getModel('catalog/category')->load($_cat_id)->getProductCollection()
->addAttributeToSelect('product_type');
foreach ($collection as $product) {
if( $product->getIsInStock() ) {
print $product->getProductType().' is in stock';
}
}

You can join your collection by :
$collection->joinField(
'is_in_stock',
'cataloginventory/stock_item',
'is_in_stock',
'product_id=entity_id',
'{{table}}.stock_id=1',
'left'
)
let me know if it helpes

Related

Get all existing values of attribute in the eav table

I have the attribute "country" which is varchar, it is set in every product that I have.
I need to have a list of all the values that are set for this attribute thought all the products. Basically what I want to do is the equivalent of this query:
SELECT `value` FROM `catalog_product_entity_varchar` WHERE attribute_id=147
How to do this the magento way?
The thing I am doing at the moment is to get the collection of all the products and loop through them, which is not an option.
Check below code:-
$attribute = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'color');
if ($attribute->usesSource()) {
$options = $attribute->getSource()->getAllOptions(false);
}
What about this?
$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToSelect('sku');
$collection->addAttributeToSelect('country');
foreach ($collection as $product) {
// ... Your stuff here
}

Magento - Filter products that have a specific customer group price set (by group code, not id)

I'm looking to filter a product list by those products which have a group_price set at the product level and assigned to a specific customer group.
I was thinking it would be something along the lines of:
$products->addFieldToFilter('group_price', array(
array(
'cust_group' => 2
)
));
But it appears that group_price is not an attribute. Additionally, $_product->getGroupPrice() always returns the product's price despite if a group price is set on the product or not.
Ideally, I'd prefer to filter these by the customer group code (ie. Wholesale, Retail, etc) instead of the group id (simply for the case where someone might delete a customer group and recreate it later and the id changes).
Any thoughts?
I have a similar requirement but the problem is that iterating over a large product collection is way too slow.
The catalog_product_index_price table contains group information so you may try something like:
$productCollection = Mage::getModel('catalog/product')->getCollection();
...
$productCollection->addFinalPrice();
$productCollection->getSelect()->where(
'price_index.customer_group_id = ? AND price_index.group_price IS NOT NULL',
$customer_group_id
);
I ended up using this:
$products = Mage::getModel('catalog/product')->getResourceCollection();
$products
->addAttributeToSelect('*')
->addAttributeToFilter('visibility', array('neq' => 1));
foreach ($products as $product => $value) {
//still not sure how to get 'group_price' without running load() =(
$productModel = Mage::getModel('catalog/product')->load($value->getId());
$groupPrices = $productModel->getData('group_price');
// A helper of mine
// store the customer's groupId to compare against available group prices array below.
$currentGroupId = Mage::helper('user')->getCustomerGroup()->getId();
// remove products w/o configured group prices
if (!count($groupPrices)) {
$products->removeItemByKey($product);
}
foreach ($groupPrices as $key) {
foreach ($key as $subkey => $value) {
if ($subkey == "cust_group") {
$customerGroup = $subkey;
if ($value != $currentGroupId) {
$products->removeItemByKey($product);
}
}
}
}
};
$this->_productCollection = $products;
return $this->_productCollection;

magento product collection with specific id

i select products with
$products = Mage::getModel('catalog/product')->getCollection()->addAttributeToFilter('entity_id', array('in' => $productIds));
how can i archieve that the collection is in the same order as the ids in $productIds?
thanks
$productIds = array(1,3,2);
$products = Mage::getModel('catalog/product')->getCollection()
->addAttributeToFilter('entity_id', array('in' => $productIds));
$products->getSelect()->order("find_in_set(entity_id,'".implode(',',$productIds)."')");
foreach($products as $product)
{
echo $product->getEntityId();
echo $product->getSku();
}
See more #
Magento get a product collection in an arbitrary order
How to select mysql rows in the order of IN clause

Magento: fetching manufacturer/brand from database

I have this code from Mukesh Chapagain: link here
$_product = Mage::getModel('catalog/product')->load(PRODUCT_ID);
$manufacturerName = $_product->getAttributeText('manufacturer');
$manufacturerId = $_product->getManufacturer();
This seems not to pick up the manufacturers even though I have them as attributes. Is it due to the fact that the manufacturer field is a drop-down?
any help in getting manufacturer attribute will be appreciated
To retrieve all Manufactures
$attribute = Mage::getModel('eav/config')->getAttribute('catalog_product', 'manufacturer');
foreach ( $attribute->getSource()->getAllOptions(true, true) as $option){
$attributeArray[$option['value']] = $option['label'];
}
foreach($attributeArray as $key=>$val){
echo $val;
}
Get products from Manufactures
$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToSelect('manufacturer');
$collection->addFieldToFilter(array(
array('attribute' => 'manufacturer', 'eq' =>$designer_id),
));
Get selected manufacturer to products
$_productCollection=$this->getLoadedProductCollection();
foreach ($_productCollection as $_product):
echo $_product->getAttributeText('manufacturer');
endforeach;
Honestly, I cannot tell what is wrong with the code in question.
However I have recently been working on something related - if you're trying to use a collection of products. Rather than trying to fix something which probably isn't broken, think of this as an alternative suggestion.
To start with you would need to download my library of query patterns. It contains a class for drop-down attributes. The following adds a manufacturer_text column to the collection.
$products = Mage::getResourceModel('catalog/product_collection');
Knectar_Select_Product_Values::enhanceProducts($products, 'manufacturer');
foreach ($products as $product) {
echo $product->getManufacturerText(), '<br>';
}
This work for me:
SELECT
CPEI.entity_id,
CPE.sku,
CPEI.attribute_id,
EA.attribute_code,
CPEI.value AS value_id,
EAOV.value
FROM
catalog_product_entity_int AS CPEI
INNER JOIN eav_attribute_option_value AS EAOV ON (EAOV.option_id = CPEI.value AND EAOV.store_id = CPEI.store_id)
INNER JOIN catalog_product_entity AS CPE USING(entity_id)
INNER JOIN eav_attribute_option AS EAO USING(option_id)
INNER JOIN eav_attribute AS EA ON(CPEI.attribute_id = EA.attribute_id)
WHERE
(
CPEI.value IS NOT NULL AND
EA.attribute_code = 'manufacturer' AND
CPEI.store_id = 0
);

Programmatically add Magento products to categories

I am using Magento 1.4.0.1.
I have over 21000 simple products, each entered into a single category.
There are hundreds of categories in my site.
Some products belong in multiple categories.
Is there some way for me to programmatically add products into multiple categories?
In PHP code you can put them into the category while you are importing them.
Say you have a product called $product and a category ID called $category_id
You can set the categories which a product belongs to by doing the following
$categories = array($category_id);
$product->setCategoryIds($categories);
$product->save();
If the product already has categories and you'd like to add one more then you can use getCategoryIds() like this:
$categories = $product->getCategoryIds();
$categories[] = $categoryId;
$product->setCategoryIds($categories);
$product->save();
Or, as mentioned by Joshua Peck in the comments, you can use the category_api model to add or remove a product from a category without affecting it's current category assignments:
Mage::getSingleton('catalog/category_api')
->assignProduct($category->getId(),$p‌​roduct->getId());
Mage::getSingleton('catalog/category_api')
->removeProduct($category->getId(),$p‌​roduct->getId());
I just want to add that you can remove and add with getSingleton category API:
To Remove product from category:
Mage::getSingleton('catalog/category_api')->removeProduct($category->getId(),$p‌​roduct->getId());
To Add Product to Category:
Mage::getSingleton('catalog/category_api')->assignProduct($category->getId(),$p‌​roduct->getId());
This will not overwrite any categories the product is already in
You can write a module (which takes time but potentially quicker at importing your data) or you can put something together with the API (less involving of Magento programming but potentially slower at importing your data).
Your starting point of what-you-know-already, how valuable your time is and how often you will need to run the update should determine your choice.
Here is the Magento API documentation for adding products to categories (see example at foot of page):
http://www.magentocommerce.com/wiki/doc/webservices-api/api/catalog_category
Well I ended up doing this with the API for some reason of laziness. This adds all the visible products into the category with ID 146:
<?php
$client= new SoapClient('http://www.example.com/api/soap/?wsdl', array('trace' => 1, "connection_timeout" => 120));
// Can be added in Magento-Admin -> Web Services with role set to admin
$sess_id= $client->login('apiuser', 'apikey');
// Get the product list through SOAP
$filters = array('visibility' => '4', 'status' => '1');
$all_products=$client->call($sess_id, 'product.list', array($filters));
// Now chuck them into category 146
foreach($all_products as $product)
{ //var_dump($product);
echo $product['sku']."\n";
$doit=$client->call($sess_id, 'category.assignProduct', array('146', $product['sku']));
}
?>
After looking into the Magento API: Magento adds products to categories in the following way:
public function assignProduct($categoryId, $productId, $position = null, $identifierType = null)
{
$category = $this->_initCategory($categoryId);
$positions = $category->getProductsPosition();
$productId = $this->_getProductId($productId);
$positions[$productId] = $position;
$category->setPostedProducts($positions);
try {
$category->save();
} catch (Mage_Core_Exception $e) {
$this->_fault('data_invalid', $e->getMessage());
}
return true;
}
And getting all the asigned products:
public function assignedProducts($categoryId, $store = null)
{
$category = $this->_initCategory($categoryId);
$storeId = $this->_getStoreId($store);
$collection = $category->setStoreId($storeId)->getProductCollection();
($storeId == 0)? $collection->addOrder('position', 'asc') : $collection->setOrder('position', 'asc');;
$result = array();
foreach ($collection as $product) {
$result[] = array(
'product_id' => $product->getId(),
'type' => $product->getTypeId(),
'set' => $product->getAttributeSetId(),
'sku' => $product->getSku(),
'position' => $product->getPosition()
);
}
return $result;
}
The best above answer points to use Mage::getSingleton('catalog/category_api')
->assignProduct($category->getId(),$p‌​roduct->getId());
Anyway that function is pretty slow in case you have a lot of products/categories to update.
This is because the api function assignProduct():
only accept 1 product/category at time
for every call it loads the product and the category and then save the category
( very slow in case you need to update the same category multiple times )
For example suppose you want to assign 10 products to 1 category ... it gonna load and save the same category 10 times ...
( and load all product that is not actually required if you are sure you product ids are corrects)
A faster way
I came up with the below function that is the same as the api one but it loads and save the category only one time.
This function accept an array as parameter $data that needs to contains all collect changes in the form of $category_id => array(all the products you want to assign)
It is trivial to customize it as for your needs adding, for example, a parameter for store_id ( the function use 0 by default) and position information to the products ...
Add category
function assignCategories($data)
{
foreach ($data as $cat_id => $products_ids) {
/** #var $category Mage_Catalog_Model_Category */
$category = Mage::getModel('catalog/category')
->setStoreId(0)
->load($cat_id );
$positions = $category->getProductsPosition();
foreach ($products_ids as $pid) {
$positions[$pid] = null;
}
$category->setPostedProducts($positions);
$category->save();
}
}
Remove category
function removeProduct($data)
{
foreach ($data as $cat_id => $products_ids) {
/** #var $category Mage_Catalog_Model_Category */
$category = Mage::getModel('catalog/category')
->setStoreId(0)
->load($cat_id);
$positions = $category->getProductsPosition();
foreach ($products_ids as $pid) {
unset($positions[$pid]);
}
$category->setPostedProducts($positions);
$category->save();
}
}
note
Saving the category trigger the Category Flat Data and Catalog URL Rewrites reindex ( if they are set as update on save ).
This is not exactly fast ( the API call does the same ) ...
... so you may want to set these reindex to update manually before running your changes and then do a full reindex on them after
( depending on the number of categories/product you are updating this could be the best option )
We can assign multiple products to the category programmatically using magento scripts. Please create an array of the categories and the select the products based on the custom attribute or field.
$newproducts = $product->getCollection()->addAttributeToFilter(array(array('attribute'=>'attribute_label', 'eq'=> 'attribute_id')));
Loop through the products and assign to category as shown below.
$newCategory = array( $list[0] , $list[$key]);
foreach ($newproducts as $prod)
{
$prod->setCategoryIds(array_merge($prod->getCategoryIds(), $newCategory));
$prod->save();
}
Please refer my tutorial which gives a step by step explanation.
Best way to assign the categories to the products.
Reference from core code - app\code\core\Mage\Catalog\Model\Resource\Category.php
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$categoryProductTable = Mage::getSingleton('core/resource')->getTableName('catalog/category_product');
$productData = array();$position=0;
foreach ($_productCollection as $product) {
$productData[] = array(
'category_id' => (int)$catId1,
'product_id' => (int)$product->getId(),
'position' => (int)$position
);
$productData[] = array(
'category_id' => (int)$catId2,
'product_id' => (int)$product->getId(),
'position' => (int)$position
);
}
$write->insertMultiple($categoryProductTable, $productData);

Resources