list the values of a product attribute set in magento - magento

how do I find the values of a product's attribute set?
For example, there's a product with an Attribute Set called shirts - T, with attributes of Gender, Shirt Size, and Color. Starting with a $_product object, how do I find the values of the attributes, e.g. Mens, Green, Large?
i am able to getting the attribute set value in the following way:
$product = Mage::getModel('catalog/product')->load($productId);
$prodAttributeSet = Mage::getModel('eav/entity_attribute_set')->load($product->getAttributeSetId())->getAttributeSetName();
I want to get all available attribute set values and codes for specific attribute set(i.e shirt - T)

$_product = Mage::getModel('catalog/product')->load($productId);
Now suppose you want to access value of manufacturer of this product, then consider following code.
$manufacturerValue = $_product->getAttributeText('manufacturer');

As you mention in comment for size and color here i can give you one sample code to use.
If it is a select or multiselect attribute, you still need to map the option ID's to option values. That is the case if you are getting a list of integers instead of human readable labels (e.g. for the color or manufacturer attribute).
// specify the select or multiselect attribute code
$attributeCode = 'color';
// build and filter the product collection
$products = Mage::getResourceModel('catalog/product_collection')
->addAttributeToFilter($attributeCode, array('notnull' => true))
->addAttributeToFilter($attributeCode, array('neq' => ''))
->addAttributeToSelect($attributeCode);
$usedAttributeValues = array_unique($products->getColumnValues($attributeCode));
// ---- this is the different part compared to the previous example ----
// fetch the attribute model
$attributeModel = Mage::getSingleton('eav/config')
->getAttribute('catalog_product', $attributeCode);
// map the option id's to option labels
$usedAttributeValues = $attributeModel->getSource()->getOptionText(
implode(',', $usedAttributeValues)
);
Direct DB query example
Depending on where you want to do this, here is an example of fetching the values without using a product collection. It is slightly more efficient.
Only use the following code in resource models, as thats where DB related code belongs.
This is meant as an educational example to show how to work with Magento's EAV tables.
// specify the attribute code
$attributeCode = 'color';
// get attribute model by attribute code, e.g. 'color'
$attributeModel = Mage::getSingleton('eav/config')
->getAttribute('catalog_product', $attributeCode);
// build select to fetch used attribute value id's
$select = Mage::getSingleton('core/resource')
->getConnection('default_read')->select()
->from($attributeModel->getBackend()->getTable(), 'value')
->where('attribute_id=?', $attributeModel->getId())
->distinct();
// read used values from the db
$usedAttributeValues = Mage::getSingleton('core/resource')
->getConnection('default_read')
->fetchCol($select);
// map used id's to the value labels using the source model
if ($attributeModel->usesSource())
{
$usedAttributeValues = $attributeModel->getSource()->getOptionText(
implode(',', $usedAttributeValues)
);
}

If you want all the attributes of an attribute set you can do the following.
$product = Mage::getModel('catalog/product')->load($productId);
$attributes = $eavConfig->getEntityAttributeCodes( Mage_Catalog_Model_Product::ENTITY, $product );
print_r(attributes);

Related

Magento: where are catalog filter's (url get parameter's) handled in magento? and where is sql request made to fetch the result?

Magento currently handles only one filter parameter per category .
I want the filter to handle more than one parameter's for the same category.
eg, Suppose I choose 2 colors red and black in the filter using a checkbox for ex, and then click submit button (which I have added), then I want the page to display results for product's having color red or black.
For this, I want to know :
Where are GET parameter's for any filtering process handled in magento.
Where is the sql request made to fetch the results of filtering process.
So that I could handle more than one filter parameter's and display the results.
Any help or suggestion would be of great help.
Thanks in advance..
For your example scenario, you are filtering using attribute color having its attribute ID. The resource model is responsible to execute the SQL operations being performed on any attribute selection.
Go to file app/code/core/Mage/Catalog/Model/Resource/Layer/Filter/Attribute.php
public function applyFilterToCollection($filter, $value)
{
$collection = $filter->getLayer()->getProductCollection();
$attribute = $filter->getAttributeModel();
$connection = $this->_getReadAdapter();
$tableAlias = $attribute->getAttributeCode() . '_idx';
$conditions = array(
"{$tableAlias}.entity_id = e.entity_id",
$connection->quoteInto("{$tableAlias}.attribute_id = ?", $attribute->getAttributeId()),
$connection->quoteInto("{$tableAlias}.store_id = ?", $collection->getStoreId()),
$connection->quoteInto("{$tableAlias}.value = ?", $value)
);
$collection->getSelect()->join(
array($tableAlias => $this->getMainTable()),
implode(' AND ', $conditions),
array()
);
return $this;
}
In the above function, when you print the collection and exit it before return using,
$collection->printlogquery(true);
you will see the SQL query generated to fetch the results of filtering process.
You can modify this resource model in your local and using INNER JOIN change the SQL query to work for multiple attribute values.

adding a multiple list attribute to product collection filter in magento

I am trying to do an ajax related magento search, and i can't manage to correctly add a multi-select type product attribute to a product collection,
for instance:
$productModel = Mage::getModel('catalog/product'); //getting product model
$productCollection = $productModel->getCollection();
$productCollection->addAttributeToSelect(
Mage::getSingleton('catalog/config')
->getProductAttributes()
);
$productCollection->addAttributeToFilter(
array(
array('attribute'=>'my_attribute_id',
'finset' => Mage::getResourceModel('catalog/product')
->getAttribute('my_attribute_id')
->getSource()
->getOptionId($searched))
);
where $searched is the string in which i save the keyword. Now, let's presume that my_attribute_id is a multi-select product attribute which has one option named as "Red Bull"...if i search after the exact string "red bull", it works, but i would like to work if i search only after "red" or "bull".
Is there a way to get the option id for an attribute, even if the search string is incomplete? Because the problem is here:
Mage::getResourceModel('catalog/product')
->getAttribute('my_attribute_id')
->getSource()
->getOptionId($searched))
this code returns the id of the attribute option only if i search it entirely.Probably the model does a query something like this
"select...where value='$searched'"
Is there a way to get a list of attribute option id's even if the value of the option is not complete?..so to do a query like this
"select...where value like '%$searched%'"
Or is there a better way to retrieve product collection after a multi-select attribute partial value, other then the solution that I am trying?
Many thanks!
Please try this..
$collection = Mage::getModel('catalog/product')->getCollection();
->addAttributeToSelect('*')
->addFieldToFilter(
'my_attribute_id',
array(
'like' => Mage::getResourceModel('catalog/product')
->getAttribute('my_attribute_id')
->getSource()
->getOptionId($searched)
)
);

Attribute Options/Labels sorting define on Site View Level?

I using Magento 1.6.2.
Is there any way to set the position for Attribute Option Labels on a Site View Level and not on a global level?
Reason: Here the Values for Color in English and German
Black / Schwarz
Clear / Transparent
Copper / Kupfer
Yellow / Gelb
It is obvious that the sorting is different for different languages.
Overriding the position value and sorting the values in the frontpage code is not possible because there are options where alphanumeric sorting doesn't make sense:
i.e. Small Medium Large
Please help
Yes, this is very possible. But it's a fairly deep change, depending on what you would like to accomplish with this. This will get you started:
You want to first add a new column to eav/attribute_option_value table. Here is the setup script for that:
$installer = $this;
$installer->startSetup();
$installer->run("
ALTER TABLE `{$this->getTable('eav/attribute_option_value')}` ADD COLUMN `sort_order` INT UNSIGNED NULL DEFAULT 0;
");
$installer->endSetup();
Next, you need to rewrite Mage_Eav_Model_Mysql4_Entity_Attribute_Option_Collection. When performing the join for the store filter, you need to add your sort_order there:
public function setStoreFilter($storeId=null, $useDefaultValue=true)
{
if (is_null($storeId)) {
$storeId = Mage::app()->getStore()->getId();
}
$sortBy = 'store_default_value';
if ($useDefaultValue) {
$this->getSelect()
->join(array('store_default_value'=>$this->_optionValueTable),
'store_default_value.option_id=main_table.option_id',
array('default_value'=>'value'))
->joinLeft(array('store_value'=>$this->_optionValueTable),
'store_value.option_id=main_table.option_id AND '.$this->getConnection()->quoteInto('store_value.store_id=?', $storeId),
array('store_value'=>'value',
'value' => new Zend_Db_Expr('IF(store_value.value_id>0, store_value.value,store_default_value.value)',
'sort_order'))) // ADDED
->where($this->getConnection()->quoteInto('store_default_value.store_id=?', 0));
}
else {
$sortBy = 'store_value';
$this->getSelect()
->joinLeft(array('store_value'=>$this->_optionValueTable),
'store_value.option_id=main_table.option_id AND '.$this->getConnection()->quoteInto('store_value.store_id=?', $storeId),
'value',
'sort_order') // ADDED
->where($this->getConnection()->quoteInto('store_value.store_id=?', $storeId));
}
$this->setOrder("store_value.sort_order", 'ASC'); // CHANGED
return $this;
}
To show what is going on: each attribute has a source model. The source model is responsible for providing the values in a frontend dropdown-type list (select, multiselect). If the source model is Mage_Eav_Model_Entity_Attribute_Source_Table, which it will be by default if the attribute type is select or multiselect, then this code retrieves the values:
$collection = Mage::getResourceModel('eav/entity_attribute_option_collection')
->setPositionOrder('asc')
->setAttributeFilter($this->getAttribute()->getId())
->setStoreFilter($this->getAttribute()->getStoreId())
->load();
As you can see, we are rewriting the setStoreFilter() function. This is the last one called. You might want to add an unshiftOrder('main_table.sort_order', 'ASC') at the beginning of the rewritten function, just for good measure that the `main_table.sort_order does not get in the way.
I'll leave it to you to make the necessary adjustments to the admin panel to provide the option for setting the sort order matrix.

Magento add new select value/option to products with upgrade script

I want to make a new select attribute option visible in all products.
I have products that each use a select box attribute called "bracket_size". That attribute has three options:
(/admin/catalog_product_attribute/edit/)
Most of the products only have two of these options selected:
(/admin/catalog_product/edit/)
If I select "18mm" in that screen then it shows on the frontend.
I want to create an upgrade script that will set all products to show the "18mm" option.
I had been doing it by selecting all products, fetching them and updating their attribute value:
$options = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'bracket_size')->getSource()->getAllOptions(false);
$option18mmId = $options[0]['value'];
foreach (Mage::getModel('catalog/product')->getCollection() as $product) {
// Get a writable product
$product = Mage::getModel('catalog/product')->load($product->getId());
// All products in these attribute sets should have bracket sizes
$bracketSizeValue = $product->getBracketSize(); // string containing option IDs - something like '645,345'
if (isset($bracketSizeValue)) {
// Get options currently selected for this product
$optionIds = explode(',', $bracketSizeValue);
// Check if the option is already included in this product
if (!in_array($option18mmId, $optionIds)) {
// If not, rebuild the attribute value to add it
array_unshift($optionIds, $option18mmId);
// Add it back to the product
$product->setData('bracket_size', implode(',', $optionIds));
$product->save();
}
}
}
But this doesn't work. It throws an error:
Warning: Invalid argument supplied for foreach() in /.../public/app/code/core/Mage/Eav/Model/Entity/Abstract.php on line 1068
at the $product->save() line.
How can I do this?
If you trying to save products in setup/update script then you need to disable update mode and set current store id first:
$app = Mage::app();
$app->setUpdateMode(false);
$app->setCurrentStore($app::ADMIN_STORE_ID);
Ideally it would be done exactly before saving and then reverted back after saving:
$app->setCurrentStore(null);
$app->setUpdateMode(true);
Then you could also optimise your code my removing loading and saving of each product and doing it on collection items instead.
Loading of collection with desired attribute:
$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToSelect('bracket_code');
Saving of changes on collection items:
$collection->save();

Magento 1.5.1.0 - While trying to update stock quantity on products, getStockData is returning NULL

I have products loaded in Magento that I am trying to bulk update the inventory qty on. I created all the products using Mage_Catalog_Model_Product and set the qty on them using setStockData like:
$product = new Mage_Catalog_Model_Product();
$product->setTypeId('simple');
$product->setStatus(1);
$product->setSku($sku);
$product->setStockData(array(
'is_in_stock' => 1,
'qty' => $record['stockstatus'],
'manage_stock' => 0,
));
...
So I've seen setStockData work ... 13,000+ times.
Now, as I said, I'm trying to update the inventory on the products I created using a variation on what I did to create the products ... a variation that I see here and virtually identically elsewhere on the web.
My problem is that I can use a variation of the code at the link above and get a valid product object, but when I call getStockData on the object, it returns NULL:
$product = Mage::getModel('catalog/product')
->loadByAttribute('product_code', '678910');
var_dump($product->getName()); // returns 'Hello My Name is Product'
var_dump($product->getProductCode()); // returns '678910'
var_dump($product->getSku()); // returns 'SKU1234'
var_dump($product->getStockData()); // returns NULL (and there is a qty of 52 set)
(I've also tried getting the product with no variations on the code at the link above and have had the same results as I expected.)
$product_id = Mage::getModel('catalog/product')->getIdBySku('SKU1234');
$product = Mage::getModel('catalog/product');
$product->load($product_id);
$stockData = $product->getStockData();
var_dump($product->getName()); // returns 'Hello My Name is Product'
var_dump($product->getProductCode()); // returns '678910'
var_dump($product->getSku()); // returns 'SKU1234'
var_dump($product->getStockData()); // returns NULL (and there is a qty of 52 set)
So, if I can't get the stock data with getStockData, I can't set the stock data like:
$product = Mage::getModel('catalog/product')
->loadByAttribute('product_code', $record['productcode']);
$stockData = $product->getStockData();
$stockData['qty'] = $record['stockstatus'];
$stockData['is_in_stock'] = ($record['stockstatus'] > 0) ? 1 : 0;
$product->setStockData($stockData);
$product->save();
Is there something I'm missing? I don't understand why getStockData is returning NULL. Can someone help me understand what I may be doing wrong?
Use getStockItem() instead of getStockData()
$stockData = $product->getStockItem();
$stockData->setData('qty',555);
$stockData->setData('is_in_stock',1);
$stockData->setData('manage_stock',1);
$stockData->setData('use_config_manage_stock',1);
$stockData->save(); // This enough to save stock data.
Use getData for arrays, use getItem for objects.
yeah no why getStockData() returns null.. But I was able to get the stock quantity using the following:
$qtyStock = Mage::getModel('cataloginventory/stock_item')->loadByProduct($product->getId())->getQty();
You should call save() on stock_item rather than product after changing qty. Following code worked for me:
$product = Mage::getModel('catalog/product')
->loadByAttribute('product_code', '678910');
$stock_obj = Mage::getModel('cataloginventory/stock_item')
->loadByProduct($product->getId());
$stockData = $stock_obj->getData();
$stockData['qty'] = $record['stockstatus'];
$stock_obj->setData($stockData);
$stock_obj->save();

Resources