1

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?

4
  • Is it an EAV attribute? Is it a regular attribute that was created through the Magento admin interface (e.g. uses the table source model)?
    – Vinai
    Jul 19, 2013 at 10:57
  • Yes. With type dropdown. It is text that displays sizes in the Ft' In'' format, (e.g. 6' x 9' 2''). This sorts automatically pretty well except for when the size is something like (1' 10'' x 2' 11''). The 10'' and 11'' are sorted before the 1'' - 9''. Jul 19, 2013 at 11:43
  • Are you looking for a way to solve this without adding new code, or is a code solution acceptable? I don't think there is a way to do this just through the admin. If a code solution works, I can tell you how you would do it. Jul 19, 2013 at 15:42
  • I was looking for a code solution. Jul 19, 2013 at 15:44

2 Answers 2

3

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.

5
  • 1
    Ah yes, your answer is more correct than mine. I wasn't thinking. Mine blanket changes all attributes that use the original source. Changing one attribute is the correct answer. Jul 19, 2013 at 17:24
  • Getting a source model not found error, following your instructions. Care why ?
    – Niloct
    Oct 23, 2013 at 1:25
  • @Niloct, check the code, its tested and works if implemented correctly.
    – Vinai
    Oct 23, 2013 at 9:12
  • @Vinai I managed to track the issue: I used Magicento's 'rewrite class' from 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.
    – Niloct
    Oct 23, 2013 at 15:25
  • @Vinai I used usort instead of uksort, only usort compares array positions with value and label "indexes".
    – Niloct
    Oct 23, 2013 at 16:06
1

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.

1
  • You're welcome, but actually Vinai's answer below is a better answer. I would combine the caching elements of mine with the installer method he uses. My answer is going to affect all attributes that use the original source model. That is certainly too heavy handed. I wasn't thinking. Jul 19, 2013 at 17:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.