For the custom options of simple prodcusts i have to add one text field for value of color. How to add it.
Magento – How to add Details field for Custom option in magento admin
admincustomfieldsetsmagento-1.9
Related Solutions
This maybe way 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 - https://stackoverflow.com/questions/21559681/creating-new-options-for-magento-attributesbut 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 - 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:
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.
This is because there is no code that will do this in the Magento core. The controller that does the product save action is in the file app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php
. Here you will find the code snippet.
/**
* Initialize product options
*/
if (isset($productData['options']) && !$product->getOptionsReadonly()) {
$product->setProductOptions($productData['options']);
}
$product->setCanSaveCustomOptions(
(bool)$this->getRequest()->getPost('affect_product_custom_options')
&& !$product->getOptionsReadonly()
);
All this is doing is setting the options on the product option and doing no image upload.
Then when you look at app/code/core/Mage/Catalog/Model/Product.php
there is the function _beforeSave
this function does the actual processing on options before saving them. What it does is loops through all the options and then adds them.
$this->getOptionInstance()->addOption($option);
So there is no code for uploading images or even saving them against the option itself. You will need to extend the options table to add your custom item, or use a custom model for storing option images.
Then what I would suggest is to listen to the admin event catalog_product_prepare_save
. This is fired after the options are set on the product. It has the product object and the request. You can use this event to perform the actual image upload and then update the product object if you need to.
Best Answer
I suggest that you use the SKU as the hex code and then sniff for it on the frontend, adding some template logic to the
catalog/product/view/options.phtml
instead of adding a new column and text option attribute.This may not be considered the "correct" approach - there are certainly better ways to address this - but it may be the easiest in your case with the requirement of using options.