Magento: Make New Customer Attributes Visible in Backend Forms

If you add a new attribute to the customer entity in a a setup script, using addAttribute(), gets a surprise starting from Magento 1.5. The setup runs and database entries in customer_eav_attribute are created correctly but in the backend there is no new form element.

Which works well with other entities like categories and until Magento 1.4 also with customers, needs an additional setup step now, to add the attribute explicitly to the admin form (and/or other forms, like the registration form).

There is a new table for it, customer_form_attribute, which defines for each attribute, in which forms it can be used:

mysql> select * from customer_form_attribute;
+----------------------------+--------------+
| form_code                  | attribute_id |
+----------------------------+--------------+
| adminhtml_customer         |            1 |
| adminhtml_customer         |            3 |
| adminhtml_customer         |            4 |
| checkout_register          |            4 |
| customer_account_create    |            4 |
| customer_account_edit      |            4 |
| adminhtml_customer         |            5 |
| checkout_register          |            5 |
| customer_account_create    |            5 |
| customer_account_edit      |            5 |
| adminhtml_customer         |            6 |
| checkout_register          |            6 |
| customer_account_create    |            6 |
| customer_account_edit      |            6 |
| adminhtml_customer         |            7 |
| checkout_register          |            7 |
| customer_account_create    |            7 |
| customer_account_edit      |            7 |
[...]
+----------------------------+--------------+
88 rows in set (0.00 sec)

So much to for a better understanding, of course you don’t need to (and should not!) modify the database manually, it is sufficient to add the following lines after the addAttribute() call in your setup script:

    Mage::getSingleton('eav/config')
        ->getAttribute('customer', $attributeCode)
        ->setData('used_in_forms', array('adminhtml_customer'))
        ->save();

with $attributeCode being the unique code of the new attribute and 'adminhtml_customer' the code for the customer management form in the backend. To keep setup scripts more clear if you add multiple attributes, it helps to extend the entity setup class, like this:

class MyNamespace_ExtendableCustomer_Model_Entity_Setup
    extends Mage_Customer_Model_Entity_Setup
{
    public function addAttributeToForm($attributeCode, $formCode)
    {
    	Mage::getSingleton('eav/config')
            ->getAttribute('customer', $attributeCode)
            ->setData('used_in_forms', (array) $formCode)
            ->save();
    }
}

Now when you use this class for your setup scripts that add customer attributes, it’s as simple as:

$this->addAttribute('customer', 'new_attribute', array( /* ... */);
$this->addAttributeToForm('new_attribute', 'adminhtml_customer');

Of course you can add the attribute to other forms in the same way, for the codes see the list above.

Thank you to the Magento forums for the crucial hint.

Update

Pay attention, on save the field eav_entity_attribute.sort_order gets set, regardless being specified before!

See my comment on StackOverflow.

Furthermore sort_order only applies if user_defined => 0 was specified in the attribute setup because Magento sorts by user_defined first and then by sort_order.