Magento - Query for Product Options - magento

I want to write a controller that finds the different options for a given product (eg. Large, Medium, Small, Red, Blue etc...).
Can anyone show me the code I would write into my controller?
Additional details
I'm getting closer, but I still can't figure it out. Here's the code I wrote in my controller
$db = Mage::getModel('catalog/product')->load($productId);
print_r($db->getOptions()); // returns an empty array
echo $db->getHasOptions(); // echos 1
But when I do the print_r() on the second line, the getOptions returns an empty array. The third line echo's the value 1, which means there SHOULD BE options.
Additional Details
I tried clockworkgeek's solution of $db->getProductOptions(), that returned nothing. I tried $db->getProductOptionsCollection(), and got this output
Array
(
[totalRecords] => 0
[items] => Array
(
)
)
What's wrong with my code such that it is not returning the allowable product options?

Instead of getOptions() please try getCustomOptions() or getProductOptionsCollection() or getProductOptionsCollection()->load().
Edit
I tried this on a product I knew had options.
<?php
require 'app/Mage.php';
Mage::app();
$product = Mage::getModel('catalog/product')->load($productId);
foreach ($product->getProductOptions() as $option) {
print_r($option->debug());
}
And got something like this:
Array
(
[option_id] => 37
[product_id] => 8
[type] => multidate
[is_require] => 1
[sku] =>
[image_size_x] => 0
[image_size_y] => 0
[sort_order] => 1
[default_title] => Dates
[title] => Dates
)
However, getOptions() also worked for me so I don't know what's going on.
Post-edit
The confusion was one of semantics. A simple product can have "custom options", they allow creation of a few form fields which are recorded as part of the order. A configurable product uses "associated products" to create a form with conditional fields.
For example you might be selling socks that are large-green, small-green or large-blue - but no small-blue ones. With a simple product you would have a field for large/small and a field for blue/green - which allows the customer to select small-blue and that is wrong.
So to find the component parts of a configurable you might do something like this:
if ($product->isConfigurable()) {
$configurable = $product->getTypeInstance();
$childProducts = $product->getUsedProducts($product);
foreach ($childProducts as $child) {
// You have a $child now
}
}
To find the equivalent of getOptions() you need this:
if ($product->isConfigurable()) {
$configurable = $product->getTypeInstance();
$attributes = $configurable->getConfigurableAttributes($product);
// $attributes is a Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Attribute_Collection
foreach ($attributes as $attribute) {
// $attribute is a Mage_Catalog_Model_Product_Type_Configurable_Attribute
print $attribute->getLabel();
}
}
Mage_Catalog_Model_Product_Type_Configurable_Attribute doesn't have much to reveal about itself.

The above solution is perfect and I solved my problem using it. I was
trying to display the colors on the list. Here is my solution
if ($_product->isConfigurable()) {
$configurable = $_product->getTypeInstance();
$childProducts = $configurable->getUsedProducts($_product);
foreach ($childProducts as $child) {
$sku = $child->getSku();
$skuarr = explode('-',$sku);
$col = trim($skuarr[1]);
?>
<span class="colorbar" style="background:<?php echo $col?>;" title="<?php echo $col?>"> </span>
}
}

Related

Magento Checkout count weight of products which match attribute

I need to count how many products of a specific type are in the checkout. But only(!) the products which are of a specific type. The type is defined in a drop down attribute.
This is a code counting the weight and works perfectly.
\template\checkout\cart.phtml
<?php $items = Mage::getSingleton('checkout/session')->getQuote()->getAllItems();
$weight = 0;
foreach($items as $item) {
$weight += ($item->getWeight() * $item->getQty()) ;
}
echo $weight;
?>
But how to count only the products which have a specific attribute value?
Like
=> "count only products which have Attribute color = green"
I found lot about collection and filter but it seems not to work for the shopping cart items.
Hope you can help me.
You have to load the product model as you're looping ( Expensive ) and then you're able to call attributes on it like so:
foreach( $oItems as $oItem )
{
$oProduct = $oItem->getProduct();
$oProductModel = Mage::getModel( 'catalog/product' )->load( $oProduct->getId() );
// For code...
$sColor = $oProductModel->getData( 'color' );
var_dump( $sColor );
// For text...
$sFormat = $oProductModel->getAttributeText( 'color' );
var_dump( $sFormat );
}
This is how you can get the attribute value (after loading your product):
$product = $item->getProduct();
$value = $product->getAttributeText($yourAttributeCode);
But notice for this in order to work you need to set: 'Show in Product Listing' or 'Used in Product Listing' to yes in the attribute editor from admin panel.
And for the grouping part, one possible way could be doing something like this (it makes sense only if you have a small number of values for your specific attribute):
$weights = array ('redWeight' => 0, 'blueWeight' => 0, 'yellowWeight' => 0, ..);
$groupRed = array();
$groupGreen = array();
...
foreach($items as $item) {
$product = $item->getProduct();
$value = $product->getAttributeText('yourAttributeCode');
$weight = ($item->getWeight() * $item->getQty());
if($value){ //Do all products have this attribute?
Switch($value){
case "red":
$Weights['redWeight'] += $weight;
$groupRed[] = $item;
break;
case "green":
....
}
} else {
continue;
}
}
....
HERE YOU HAVE GROUPS OF YOUR ITEMS ACCORDING TO THEIR SPECIFIC ATTRIBUTE VALUES

Magento Attribute Values - add description field

Looking for a way to add a description field to invididual attribute values in Magento. Please note I'm referring to Attribute Value options, not the actual Attribute itself.
As an example:
Attribute = colour
Attribute values:
Red, Green, Blue
I want to add a description field for each of the 3 colours (1 for Red, 1 for Green, 1 for Blue). The purpose of this is to show a tooltip on the frontend to give more information about each colour option.
Does anyone know how to do this? There are lots of solutions round which apply to the Attribute itself (colour) but not the individual options (Red, Green, Blue).
The descriptions should be editable from within the Admin panel. I don't want a solution which relies on editing these straight in the database using, for example, phpMyAdmin.
I understand that the values are stored in the 'eav_attribute_option_value' table and that a further column may be needed to store the Description. No idea how to get all that set up in the Admin panel. Ideas?
EDIT: I've added a screenshot of where the Description text would need adding. So next to each colour (on the screenshot: Black, Blue, Green, Grey, Red, White, etc) - each one needs to have a description next to it.
This maybe 11 months out of date, but for anyone else having this problem then perhaps this can assist you. I hope it will save you from the hours of head banging against a wall like myself and my colleague experienced. For my purpose, I was trying to create an Image URL field for Magento version 1.9 to support a product migration from an older platform.
This answer has been partially answered here - Creating new options for Magento attributes but there are some extra things I had to figure out:
1.) This answer assumes you have created your own module (if you do not know how then start here: http://www.smashingmagazine.com/2012/03/01/basics-creating-magento-module/)
2.) It also leaves you to create the extra fields in catalog/product/attribute/options.phtml yourself. But to save you time here are the amendments I made to to get it to appear in the admin. Create a new table head option on line 88:
<th><?php echo Mage::helper('catalog')->__('YOUR_ATTRIBUTE_NAME_HERE') ?></th>
Next create a new td on line 101:
<td class="a-left"><input class="input-text" type="text" name="option[YOUR_ATTRIBUTE_NAME_HERE][{{id}}]" value="{{TABLE_COLUMN_NAME_HERE}}" <?php if ($this->getReadOnly()):?> disabled="disabled"<?php endif;?>/></td>
And also, most of the logic is done in Javascript so we need to replicate the field here on line 126:
'<td><input class="input-text" type="text" name="option[YOUR_ATTRIBUTE_NAME_HERE][{{id}}]" value="{{TABLE_COLUMN_NAME_HERE}}" <?php if ($this->getReadOnly()):?> disabled="disabled"<?php endif;?>/><\/td>'+
3.) The longest part for me was creating the custom logic for _saveOption method. I overrode the parent class, but to save you the trouble here is my logic:
protected function _saveOption(Mage_Core_Model_Abstract $object)
{
$option = $object->getOption();
if (is_array($option)) {
$adapter = $this->_getWriteAdapter();
$optionTable = $this->getTable('eav/attribute_option');
$optionValueTable = $this->getTable('eav/attribute_option_value');
$stores = Mage::app()->getStores(true);
if (isset($option['value'])) {
$attributeDefaultValue = array();
if (!is_array($object->getDefault())) {
$object->setDefault(array());
}
foreach ($option['value'] as $optionId => $values) {
$intOptionId = (int) $optionId;
if (!empty($option['delete'][$optionId])) {
if ($intOptionId) {
$adapter->delete($optionTable, array('option_id = ?' => $intOptionId));
}
continue;
}
$sortOrder = !empty($option['order'][$optionId]) ? $option['order'][$optionId] : 0;
$imgUrl = !empty($option['image_url'][$optionId]) ? $option['image_url'][$optionId] : 0;
if (!$intOptionId) {
$data = array(
'attribute_id' => $object->getId(),
'sort_order' => $sortOrder,
'image_url' => $imgUrl
);
$adapter->insert($optionTable, $data);
$intOptionId = $adapter->lastInsertId($optionTable);
} else {
$data = array('sort_order' => $sortOrder, 'image_url' => $imgUrl);
$where = array('option_id =?' => $intOptionId);
$adapter->update($optionTable, $data, $where);
}
if (in_array($optionId, $object->getDefault())) {
if ($object->getFrontendInput() == 'multiselect') {
$attributeDefaultValue[] = $intOptionId;
} elseif ($object->getFrontendInput() == 'select') {
$attributeDefaultValue = array($intOptionId);
}
}
// Default value
if (!isset($values[0])) {
Mage::throwException(Mage::helper('eav')->__('Default option value is not defined'));
}
$adapter->delete($optionValueTable, array('option_id =?' => $intOptionId));
foreach ($stores as $store) {
if (isset($values[$store->getId()])
&& (!empty($values[$store->getId()])
|| $values[$store->getId()] == "0")
) {
$data = array(
'option_id' => $intOptionId,
'store_id' => $store->getId(),
'value' => $values[$store->getId()]
);
$adapter->insert($optionValueTable, $data);
}
}
}
$bind = array('default_value' => implode(',', $attributeDefaultValue));
$where = array('attribute_id =?' => $object->getId());
$adapter->update($this->getMainTable(), $bind, $where);
}
}
return $this;
}
My custom field was named image_url so I added it to the $data variable to be inserted. This will insert values into the column "image_url" of the eav_attribute_option table, but you can manipulate it to store in eav_attribute_option_value in the same method.
4.) For some reason that stack overflow post stated that this _saveOption method would be fired on save but mine was not, therefore I also overrode the _afterSave method in the same class which looks like this:
protected function _afterSave(Mage_Core_Model_Abstract $object)
{
$this->_clearUselessAttributeValues($object);
$this->_saveStoreLabels($object)
->_saveAdditionalAttributeData($object)
->saveInSetIncluding($object)
->_saveOption($object);
return $this;
}
5.) Now it will attempt to save your new value. But it will cause an error since your custom table column most likely doesn't exist yet. You are welcome to create this manually if it is appropriate for you. Unfortunately I needed to create this programmatically for my situation, so for those of you in the same boat (this is a slightly unclean approach) but for speed I re-routed the app/code/core/Mage/Core/Model/Resource/Setup.php by creating the local revision here: app/code/local/Mage/Core/Model/Resource/Setup.php and add this to line 154 in the constructor class:
$installer = $this;
$installer->getConnection()->addColumn($installer->getTable('eav/attribute_option'), 'YOUR_COLUMN_NAME_HERE', 'VARCHAR(256) NULL');
$installer->endSetup();
6.) Okay, everything should now be saving to the database, but we still need to read the value into our <td> - this had me stumped for a while, but figured out that the Javascript is responsible for replacing the {{id}} and {{sort_order}} tags in the HTML on line 230. Therefore we need to add our new column to this getOptionsValues() method. I added the following code in on line 70 of catalog/product/attribute/options.phtml:
<?php foreach ($this->getOptionValues() as &$val) {
$imgUrl = $this->getImageUrl($val->id);
if ($imgUrl != "0") {
$val->_data["YOUR_TABLE_COLUMN_NAME_HERE"] = $imgUrl;
}
} ?>
Then, in your YOUR_MODULE_Block_Adminhtml_Options class add the method getImageUrl() that the above calls:
/**
* Retrieve results from custom column
*
* #return Mage_Core_Model_Mysql4_Store_Collection
*/
public function getImageUrl($option_id)
{
//Get the resource model
$resource = Mage::getSingleton('core/resource');
//Retrieve the read connection
$readConnection = $resource->getConnection('core_read');
//Retrieve our table name
$table = $resource->getTableName('eav/attribute_option');
$query = 'SELECT ' . $this->custom_col . ' FROM ' . $table . ' WHERE option_id = '
. (int)$option_id . ' LIMIT 1';
//Execute the query and store the result
$imgUrl = $readConnection->fetchOne($query);
return $imgUrl;
}
And there you have it. I really hope that this helps anyone in a similar situation.
Try this out
By default Magneto only provide custom options without any description, if you want to customize with description then you must change in following files:
Step 1:-
In File
app\design\adminhtml\default\default\template\catalog\product\edit\option\type\select.phtml
Find the below code:
'<th class="type-sku"><?php echo Mage::helper('catalog')->__('SKU') ?></th>'+
Add these after just after
'<th class="type-description"><?php echo Mage::helper('catalog')->__('Description') ?></th>'+
Find the below code:
'<td><input type="text" class="input-text" name="product[options][{{id}}][values][{{select_id}}][sku]" value="{{sku}}"></td>'+
Add these after just after
'<td><input type="text" class="input-text" name="product[options][{{id}}][values][{{select_id}}][description]" value="{{description}}"></td>'+
Step 2:-
In File
app\code\core\Mage\Adminhtml\Block\Catalog\Product\Edit\Tab\Options\Option.php
Find the below code:
$value['sku'] = $this->htmlEscape($option->getSku());
Add these code just after
$value['description'] = $this->htmlEscape($option->getDescription());
Find the below code:
'sku' => $this->htmlEscape($_value->getSku()),
Add these code just after
'description' => $this->htmlEscape($_value->getDescription()),
Step 3:-
Add field in “catalog_product_option_type_value” table description.
Let me know if you have some query.

Retrieve multiple products by custom attribute [magento]

I have a custom attribute for the products, and lets say I have 3-4 products that have the same value on that attribute. So, now I want to load these 3 products and store them in an array. Here's what I do:
$all_products = array();
$count = 0;
$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToSelect('ordernumber');
foreach($collection as $product)
{
$all_products[count] = array ('sku' => $product->getSku(), 'qty' => $this->getRequest()->get('qty'), 'size' => $product->getSize());
$count++;
}
return $all_products;
Note: ordernumber HAS a value, I just get it from another place.
Anyway, when I run it - I have no values. When I debug - the debugger terminates at $products[count] = ....
I tried loading a single product just by the custom attribute - Mage::...->loadByAttribute('ordernumber', $ordernumber); and it worked fine.
So, my guess is that I am not doing something correctly with the collection manipulation, or with the array, although, I saw some examples where I got the idea from.
What am I doing wrong?
Try it like this:
$all_products = array();
$count = 0;
$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToSelect('ordernumber');
//add a filter if needed - uncomment the next 2 lines and adjust the value or $ordernumber
//$ordernumber = '123';
//$addAttributeToFilter('ordernumber', $ordernumber)
foreach($collection as $product)
{
$all_products[$count] = array ('sku' => $product->getSku(), 'qty' => $this->getRequest()->get('qty'), 'size' => $product->getSize());
$count++;
}
return $all_products;

Magento Custom Options showing price in cart/checkout page

Im trying to show each price for custom option in cart-page and checkout-page.
so I have changed this file: app/code/core/Mage/Catalog/Helper/Product/Configuration.php
here at line 75
$options[] = array(
'label' => $option->getTitle(),
'value' => $group->getFormattedOptionValue($itemOption->getValue()),
'print_value' => $group->getPrintableOptionValue($itemOption->getValue()),
'option_id' => $option->getId(),
'option_type' => $option->getType(),
'custom_view' => $group->isCustomizedView(),
//##my changing
'my_price' => $option->getPrice()
);
but this works only with fields, not works when my custom option was a select-box or in radio-buttons.
can someone help, Thanks!
Open up your template file
app/design/frontend/default/theme/template/checkout/cart/item/default.phtml
Find the foreach loop:
<?php foreach ($_options as $_option) : ?>
Within that foreach loop, add this code:
<?php
$optionId = $_option['option_id'];
$product = $_item->getProduct();
$option = $product->getOptionById($optionId);
$itemOption = $_item->getOptionByCode('option_' . $option->getId());
$price = false;
foreach ($option->getValues() as $values) {
if ($values->getId() == $itemOption['value']) {
$price = $values->price;
}
}
if ($price !== false) {
echo Mage::helper('core')->currency($price);
}
?>
Not sure if you've solved your problem yet, but for reference here's what I did..
The custom option prices are only available from the product object, not from the item object (which is what's readily available from the cart/item/default.phtml template). You'll have to find the product id from the item ($_item->getProductId()) then load this product. From there you'll want to load the product options, iterate through the custom option select values (in my case) and pull out the price when the option value ids match from the product and item objects ( http://subesh.com.np/2009/12/custom-options-product-magento/ for more help ).
Hope this helps you get on your way :)

Get attributes and its values using single Collection in Magento?

How to get attributes and its values using single Collection in Magento?
Right now i am using below
$attributesInfo = Mage::getResourceModel('eav/entity_attribute_collection')
->setEntityTypeFilter(4)
->addFieldToFilter('frontend_input','multiselect')
->addSetInfo()
->getData();
to get attribute and below code to get attribute value
$product = Mage::getModel('catalog/product');
$collection = Mage::getResourceModel('eav/entity_attribute_collection')
->setEntityTypeFilter($product->getResource()->getTypeId())
->addFieldToFilter('attribute_code', $attributeName);
My attributes code out put is like below
Color :
Black
Blue
Green
Brand :
Hp
Dell
Apple
Size :
12
14
16
Thanks,
Balan
How about this:
$attributes = Mage::getSingleton('eav/config')
->getEntityType(Mage_Catalog_Model_Product::ENTITY)
->getAttributeCollection()
->addFieldToFilter('source_model', array('notnull' => true))
->addSetInfo();
foreach ($attributes as $attribute)
{
echo "{$attribute->getFrontendLabel()}:\n";
foreach ($attribute->getSource()->getAllOptions() as $option)
{
echo " {$option['label']}\n";
}
echo "\n";
}
By using the eav/config and eav/entity_type chances are you will be reusing an already loaded collection, which of course is more efficient then reloading the same data in new collections.
EDIT: Updated the answer to include the attribute collection filter suggested by Aleksandr Ryabov.

Resources