I have a dropdown attribute with many options that need to be sorted.
I am wondering how best to sort them automatically?
If it can't be done automatically, is there a way to export the data from the database and sort them elsewhere?
I have a dropdown attribute with many options that need to be sorted.
I am wondering how best to sort them automatically?
If it can't be done automatically, is there a way to export the data from the database and sort them elsewhere?
First, create a module, lets call it My_AttributeSorter
.
In the modules etc/config.xml, declare a class group for your module:
<?xml version="1.0"?>
<config>
<modules>
<My_AttributeSorter>
<version>0.1.0</version>
</My_AttributeSorter>
</modules>
<global>
<models>
<my_attributesorter>
<class>My_AttributeSorter_Model</class>
</my_attributesorter>
</models>
<resources>
<my_attributesorter_setup>
<setup>
<module>My_AttributeSorter</module>
</setup>
</my_attributesorter_setup>
</resources>
</global>
</config>
Then create a source model extending the core default source model, Mage_Eav_Model_Entity_Attribute_Source_Table
.
Override the method getAllOptions()
, retrieve the option array from the parent, and then add the sorting logic as needed.
class My_AttributeSorter_Model_Entity_Attribute_Source_Table_Sorted
extends Mage_Eav_Model_Entity_Attribute_Source_Table
{
public function getAllOptions()
{
$options = parent::getAllOptions();
uksort($options, array($this, '_sortOptionsCallback'));
return $options;
}
protected function _sortOptionsCallback($a, $b)
{
// Adjust sorting logic as needed for your use case
if ($a['label'] > $b['label']) {
return 1;
} elseif ($a['label'] < $b['label']) {
return -1;
}
return 0;
}
}
The final missing part is assigning your custom sorted table source model to the attribute in question. If your attribute code would be, for example, color
, add a setup script sql/my_attributesorter_setup/install-0.1.0.php as follows:
$installer = Mage::getResourceModel('catalog/setup', 'catalog_setup');
$installer->startSetup();
$installer->updateAttribute(
'catalog_product',
'color',
'source_model',
'my_attributesorter/entity_attribute_source_table_sorted'
);
$installer->endSetup();
And thats it. You now can simply assign your source model to any select or multi-select attribute that you need to sort in that manner.
Mage_Eav_Model_Entity_Attribute_Source_Table
and the name of the class was different from the installer my_attributesorter/entity_attribute_source_table_sorted
. I learned that a source model is a simple model class and fixing this model grouped name on installer AND creating the correct directory tree for the class did work. Thanks.
usort
instead of uksort
, only usort
compares array positions with value
and label
"indexes".
You can change the way the options are sorted by rewriting the class: Mage_Eav_Model_Entity_Attribute_Source_Table. In this class, there is a method "getAllOptions(...)" that you can override, then sort the results before returning them.
1 Create a new module, and rewrite the class:
<config>
<modules>
<Example_Module>
<version>0.0.1</version>
</Example_Module>
</modules>
<global>
<models>
<eav>
<rewrite>
<entity_attribute_source_table>Example_Module_Model_Eav_Entity_Attribute_Source_Table</entity_attribute_source_table>
</rewrite>
</eav>
</models>
</global>
</config>
2 Create that class
class Example_Module_Model_Eav_Entity_Attribute_Source_Table
extends Mage_Eav_Model_Entity_Attribute_Source_Table
{
protected $_sorted_options = array();
public function getAllOptions($withEmpty = true, $defaultValues = false)
{
$storeId = $this->getAttribute()->getStoreId();
/* Pass FALSE for first parameter so we don't end up with the empty record */
$options = parent::getAllOptions(false, $defaultValues);
/* Test if we have already sorted this list for this store */
if(!$defaultValues
&& !isset($this->_sorted_options[$storeId])
|| !$this->_sorted_options[$storeId])
{
$options = $this->_sortOptions($options, $storeId);
$this->_sorted_options[$storeId] = true;
$this->_options[$storeId] = $options;
}
/* If we should have the empty record, add it now */
if($withEmpty)
{
array_unshift($options, array('label' => '', 'value' => ''));
}
return $options;
}
protected function _sortOptions($options, $storeId)
{
/* Add your sorting code */
/* ... */
return $options; /* Or a new array, you get the idea */
}
}
This should be a good starting point for you. I'm not sure how you want to sort these things, so that's for you to solve. The important thing here is we will only sort the set once regardless of how many times it is accessed. Performance! I can be done in PHP.
Hope this helps.