3

I often see two different methods in a source model that appear to do the same thing:

class Mypackage_Mymodule_Model_Source_Generic {

  /* I sometimes see this method */
  public function getAllOptions() {}

  /* And other times this method */
  public function toOptionArray() {}

}

In my experience, there's no rhyme or reason as to when which method name is employed; they both appear to return the same data structure.

Is there something I'm missing?

Is there semantic link between a source model's toOptionArray and Varien_Data_Collection::toOptionArray?

Rick Buczynski
  • 827
  • 8
  • 23

1 Answers1

11

Like so many of my answers, this is informed speculation.

The toOptionArray and getAllOptions "source model" split seems like another case of too many chefs in the Magento 1 kitchen. That is, a team of developers working with similar concepts, but with no one in charge of making sure the end result was a solid, consistent system. The problem is there's (at least) two kinds of "source models" in Magento.

First, there's a source model concept in the system configuration system (system.xml files, System -> Configuration, etc) which dictates the options for the system configuration forms. Second, there's a source model concept (more accurately, an attribute source) in the EAV system which, again, dictates options for UI forms, but this time for rendering user interfaces to edit object entries that have a particular attribute.

The system configuration system uses toOptionArray. The EAV system uses getAllOptions. This is reflected in the interfaces provided for the EAV system's source attribute objects.

#File: app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Interface.php
interface Mage_Eav_Model_Entity_Attribute_Source_Interface
{
    /**
     * Retrieve All options
     *
     * @return array
     */
    public function getAllOptions();

    /**
     * Retrieve Option value text
     *
     * @param string $value
     * @return mixed
     */
    public function getOptionText($value);
}

More importantly than that though is how the objects are used by the system. When Magento renders the UI in the system configuration tabs, it does so with this code

#File: app/code/core/Mage/Adminhtml/Block/System/Config/Form.php
//...
$optionArray = $sourceModel->toOptionArray($fieldType == 'multiselect');
//...

When Magento renders the UI for editing an EAV product object, it does so with code like this

#File: app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config/Simple.php

'values' => $attribute->getSource()->getAllOptions(true, true),

So that's two different system developers implementing a similar concept in different parts of Magento. So, when other developers need to create a UI with a select list and aren't intimately familiar with the system conventions, they pick the method they've seen before, which is what leads to the (seemingly) no rhyme or reason pattern you mentioned above. There's also a few cases where Magento core developers working on features have tried to marry the two methods.

#File: app/code/core/Mage/Tax/Model/Class/Source/Product.php
public function getAllOptions($withEmpty = false)
{
    //...
}
//...
public function toOptionArray()
{
    return $this->getAllOptions();
}

Finally, while there's no official semantic link between Varien_Data_Collection's toOptionArray and the toOptionArray used in the system configuration source models, it seems safe to speculate that since the source models are, in practice, collections of data, that a core developer chose toOptionArray as the method name so (in theory) a Varien_Data_Collection based object could be used as a source model. I suspect if not for performance considerations in PHP 5.2, the models in app/code/core/Mage/Adminhtml/Model/System/Config/Source all would have inherited from Varien_Data_Collection.

Oğuz Çelikdemir
  • 4,990
  • 4
  • 30
  • 56
Alana Storm
  • 164,128
  • 91
  • 395
  • 599
  • Alan, thanks for the detailed response. That cleared up questions I didn't even know I had about source models. I especially took note of your last bit, where except for performance considerations, source models would inherit from `Varien_Data_Collection`. I'm working on a new module which has a source model that technically builds an option array from a collection, and happened to notice that method `toOptionArray` in the collection abstract. – Rick Buczynski Dec 27 '13 at 20:13
  • @vbuck To clarify, a single source model that builds its values from a collection (either AS a data collection object or using one) isn't that big of a performance concern. It's when you have a page that might have 10 - 20 select fields to render, and each one needs to instantiate a `Varien_Data_Collection` object where performance might be a concern. Good luck with your extension! – Alana Storm Dec 27 '13 at 20:26
  • This was answered a while ago but I came across it today while searching for an explanation about the different source models. A great answer by Alan! I wanted to add the following link to another excellent resource with details about the differences: http://magecert.com/eav.html. – Mageician Dec 03 '14 at 18:53
  • @AlanStorm you guys make kids like us look silly lol. Great answer man! Much appreciated. – Gogol May 23 '15 at 11:20
  • can I rewrite a source model in my custom module? – saiid Oct 19 '16 at 10:52