2

I'm trying to create a select list from a Magento collection using toOptionArray, but am unable to define the key => value relationship.

The lib/Varien/Data/Collection.php file contains the public & protected methods:

protected function _toOptionArray($valueField='id', $labelField='name', $additional=array())
    {
        $res = array();
        $additional['value'] = $valueField;
        $additional['label'] = $labelField;

        foreach ($this as $item) {
            foreach ($additional as $code => $field) {
                $data[$code] = $item->getData($field);
            }
            $res[] = $data;
        }
        return $res;
    }

    public function toOptionArray()
    {
        return $this->_toOptionArray();
    }

But it appears that the public function does not pass any arguments to the protected function, which would seem to limit the functionality of the method. Is this a bug, or is there a standard way to generate a select from a collection that does not inherit from the Collection class?

(it's easy enough to override the public method in my own class, but I'd like to know any insights on the design of the above)

3

The idea behind this design is simple (not that I completely agree with it).

You probably have not more than one way of representing your collection in <select /> list.

If you stick to convention, and your field primary key is 'id' and readable name is 'name' then you're good and can use generic Varien_Data_Collection (note: even magento core code doesn't stick to that convention very much e.g. 'entity_id')

If you don't stick to that convention - you should write one class for each mapping case: i.e.

class Acme_Thisrtsizes_Data_Collection_Frontend
  extends Varien_Data_Collection {

public function toOptionArray() {
   return $this->_toOptionArray('short_name', 'short_name'; 
}

to get selects like

  <option value='s'>s</option>
  <option value='xl'>xl</option>

and

class Acme_Thisrtsizes_Data_Collection_Internal
  extends Varien_Data_Collection {

public function toOptionArray() {
   return $this->_toOptionArray('short_name', 'internal_name'; 
}

to get selects like

  <option value='s'>skinny</option>
  <option value='xl'>fatty</option>

And all this so you can define what you want in your xml config:

<rewrite>
    <sizes_collection>

To have different representations in frontend and admin i.e.

So to summarize - I think magento main philosophy is that it's easier to customize your shop with xml's configs. Also it's supposedly easier to write a plugin which adds some custom items that way (otherwise you would need to define somewhere which params to pass in admin and frontend context. And defining class to use is just simpler, and the cost of that is more writing for coder.

To finish: the proposed answer with overriding and allowing to pass two arguments is not good idea for two reasons: * it's against magento philosophy (you end up with custom code using your new Collection, but any other modules which you might want to use are not compatibile anymore) * you change interface, and this will get you to trouble.

You may not like it (I don't particularly like it), but this is a framework given and my opinnion is that - when you work with it - you still try to do it good style, with no quick hacks.

2

Rewrite in your class that extends Varien_Data_Collection the method _toOptionArray and make it use the field names you need:

protected function _toOptionArray($valueField='id_field_here', $labelField='name_field_here', $additional=array())
{
    return parent::_toOptionArray($valueField, $labelField, $additional);
}
  • Thanks Marius - but for large installs with many collections, you would have to do this for each collection? – dbcn Jan 6 '15 at 16:29
  • Actually, the idea is to override the public method toOptionArray() in your collection implementation, but this works as well :) – Fabian Schmengler Mar 2 '15 at 8:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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