Magento – Flat Table Attributes and Backend Models

attributesbackendmodelorders

I created a new attribute for orders using the following:

$installer =  new Mage_Sales_Model_Mysql4_Setup('core_setup');
$installer->startSetup();

$installer->addAttribute('order', 'erp_associated_ids',  array(
    'user_defined'  => true,
    'type' => 'varchar',
    'backend' => 'mycompany_mymodule/adminhtml_system_config_backend_csv',
    'label' => 'Associated Order IDs',
    'input' => 'text',
    'source' => '',
    'visible' => true,
    'required' => false,
    'default' => '',
    'frontend' => '',
    'unique' => false,
    'note' => 'CSV of order IDs'
));

$installer->endSetup();

I then created a backend model:

app/code/local/Mycompany/Mymodule/Model/Adminhtml/System/Config/Backend/Csv.php

class Mycompany_Mymodule_Model_Adminhtml_System_Config_Backend_Csv extends Mage_Core_Model_Config_Data {

    protected function _afterLoad()
    {
        if (is_string($this->getValue())) {
            $value = $this->getValue();
            $this->setValue(empty($value) ? false : explode(',', $value));
        }
    }

    protected function _beforeSave()
    {
        if (is_array($this->getValue())) {
            $this->setValue(implode(',', $this->getValue()));
        }
    }
}

The idea being that I can do the following:

Mage::getModel('sales/order')
    ->load(25)
    ->setErpAssociatedIds(array('12345', '98765'))
    ->save();

And that the backend model would convert the array to a CSV string like '12345,98765'. (I want a CSV because it's easier to search using pure MySQL than a serialized array.)

However, when I try to save this attribute I just get Array in the database.

I would assume that this stems from attributes created for flat tables not having an entry in eav_attribute which would note which backend_model I want to use. However, I feel like I must be missing something. Do flat tables not use backend models at all? Am I going to have to extend Mage_Sales_Model_Order to pull this off?

Best Answer

You cannot add backend models to flat table columns.
For the entities that are mapped to flat tables (like the orders) you have to use some events to manipulate the data.
There is no way to make a connection between an attribute and a backend model because flat entities don't have attributes. They have fields.

You can use sales_order_save_before to turn the array into a string.

public function beforeOrderSave($observer) {
    $order = $observer->getEvent()->getOrder();
    $erpIds = $order->getErpAssociatedIds();
    if (is_array($erpIds)) {
         $order->setErpAssociatedIds(implode(',', $erpIds));
    }
    return $this;
}

and if you want to get your field value as an array when you load an order observe the event sales_order_load_after

public function afterOrderLoad($observer) {
    $order = $observer->getEvent()->getOrder();
    $erpIds = $order->getErpAssociatedIds();
    if (!is_array($erpIds)) {
         $order->setErpAssociatedIds(explode(',', $erpIds));
    }
    return $this;
}
Related Topic