Add Custom Fields to Customer Account – Magento 1.7

Banners
In this blog post, we are going to see how to add new fields to customer account pages i.e registration,edit profile, checkout and admin manage customer.

In this blog will look at magento version 1.4.2(+) and 1.4.2(-) and how to add fields in different magento version.In magento 1.4.2 version, major changes were made in account management system, so we will look at both versions. It would be better to create a magento module for this purpose, but it is not necessary. Attached is the source files of magento module created.
Module also tested on Latest 1.7.0.2
Error... Unable to load download template. Search single-download-template.tpl in your plugin folder!
So lets start of, as an example will we add a drop down field called School in Customer Profile. The below codes are written only for 1 field, if you want to add multiple fields then you need to repeat the below for multiple attributes.

Step1: Create Attribute

So first we need to create a custom attribute called School.
If you have a magento module
If you have created a module, then in your mysql_install or mysql_upgrade files, you need to put in this code

<?php
$installer = $this;
$installer->startSetup();
$setup = Mage::getModel('customer/entity_setup', 'core_setup');
$setup->addAttribute('customer', 'school', array(
	'type' => 'int',
	'input' => 'select',
	'label' => 'School',
	'global' => 1,
	'visible' => 1,
	'required' => 0,
	'user_defined' => 1,
	'default' => '0',
	'visible_on_front' => 1,
        'source'=> 'profile/entity_school',
));
if (version_compare(Mage::getVersion(), '1.6.0', '<='))
{
      $customer = Mage::getModel('customer/customer');
      $attrSetId = $customer->getResource()->getEntityType()->getDefaultAttributeSetId();
      $setup->addAttributeToSet('customer', $attrSetId, 'General', 'school');
}
if (version_compare(Mage::getVersion(), '1.4.2', '>='))
{
	Mage::getSingleton('eav/config')
	->getAttribute('customer', 'school')
	->setData('used_in_forms', array('adminhtml_customer','customer_account_create','customer_account_edit','checkout_register'))
	->save();
}
$installer->endSetup();

and in your config.xml file

<profile_setup> <!-- Replace with your module name -->
 <setup>
  <module>Excellence_Profile</module> <!-- Replace with your module name -->
  <class>Mage_Customer_Model_Entity_Setup</class>
 </setup>
</profile_setup>

Note: Name of my module is Excellence_Profile
If you don’t have a module
In this case you do this

$setup = Mage::getModel('customer/entity_setup');
$setup->addAttribute('customer', 'school', array(
	'type' => 'int',
	'input' => 'select',
	'label' => 'School',
	'global' => 1,
	'visible' => 1,
	'required' => 0,
	'user_defined' => 1,
	'default' => '0',
	'visible_on_front' => 1,
        'source' => 'profile/entity_school',
));
if (version_compare(Mage::getVersion(), '1.6.0', '<='))
{
      $customer = Mage::getModel('customer/customer');
      $attrSetId = $customer->getResource()->getEntityType()->getDefaultAttributeSetId();
      $setup->addAttributeToSet('customer', $attrSetId, 'General', 'school');
}
if (version_compare(Mage::getVersion(), '1.4.2', '>='))
{
	Mage::getSingleton('eav/config')
	->getAttribute('customer', 'school')
	->setData('used_in_forms', array('adminhtml_customer','customer_account_create','customer_account_edit','checkout_register'))
	->save();
}

you need to place the above code in some phtml file, and run it only once. Remove the code once this code has run.
To check if this step is successful, open your database in phpmyadmin. Go to table ‘eav_attribute’ and search for the attribute code ‘school’ or whatever is the code of your attribute. If there is no entry for this attribute it means the above code was not executed. To fix, go to table ‘core_resource’, find the entry of your module there. You need to delete that entry so that the sql is executed.

Step2: Source Model

Since we are using a dropdown attribute, we need to tell magento where to look for the drop down options. This is where the source model comes into picture, in our case we have mentioned source_model as ‘profile/entity_school’
If you are using text attribute, just keep source_model as blank and skip this section
So our code for the source model would be

<?php
class Excellence_Profile_Model_Entity_School extends Mage_Eav_Model_Entity_Attribute_Source_Abstract
{
	public function getAllOptions()
	{
		if ($this->_options === null) {
			$this->_options = array();
			$this->_options[] = array(
                    'value' => '',
                    'label' => 'Choose Option..'
			);
			$this->_options[] = array(
                    'value' => 1,
                    'label' => 'School1'
			);
			$this->_options[] = array(
                    'value' => 2,
                    'label' => 'School2'
			);
			$this->_options[] = array(
                    'value' => 3,
                    'label' => 'School3'
			);
			
		}

		return $this->_options;
	}
}

This code is simpe, the getAllOptions() return the array with all our drop down options. If you want to fetch options, from database table, you can put a db query here as well.
By end of this step, you should see your attribute in the Admin -> Manage Customer -> Edit Customer section. If not, there is something wrong, you need to follow the Explanation at end of blog post.

Step3: Registration Form

Here we will add our attribute, to the customer registration form. In version 1.6.0(+) the phtml file used is persistance/customer/register.phtml and in version 1.6.0(-) the phtml file used is customer/form/register.phtml
So we need to open the phtml file, based on magento version and add this code in the <form> tag.

<li>
            	 	<?php 
            	 		$attribute = Mage::getModel('eav/config')->getAttribute('customer','school');
            	 	?>
                    <label for="school" class="<?php if($attribute->getIsRequired() == true){?>required<?php } ?>"><?php if($attribute->getIsRequired() == true){?><em>*</em><?php } ?><?php echo $this->__('School') ?></label>
                    <div class="input-box">
                        <select name="school" id="school" class="<?php if($attribute->getIsRequired() == true){?>required-entry<?php } ?>">
                        	<?php
                        		 $options = $attribute->getSource()->getAllOptions();
                        		 foreach($options as $option){
                        	?>
                        		<option value='<?php echo $option['value']?>' <?php if($this->getFormData()->getSchool() == $option['value']){ echo 'selected="selected"';}?>><?php echo $this->__($option['label'])?></option>
                        	<?php } ?>
                        </select>
                    </div>
                </li>		

For magento 1.4.2(+) that is all that is required for the registration step. If you create a user from here, you should see the selected drop down value in admin.
For magento 1.4.1(-), we need to do another thing open the your modules config.xml file and add

<global>
        <fieldsets>
            <customer_account>
                 <school><create>1</create><update>1</update><name>1</name></school>
            </customer_account>
        </fieldsets>
</global>
Step4: Edit Account Information

Once, user has created his account in the MyAccount->Account Information section he should be able to edit the school field as well. For this open the phtml file customer/form/edit.phtml and put in the code in the <form>

<?php 
            	 		<li>
            	 	<?php 
            	 		$attribute = Mage::getModel('eav/config')->getAttribute('customer','school');
            	 	?>
                    <label for="is_active" class="<?php if($attribute->getIsRequired() == true){?>required<?php } ?>"><?php if($attribute->getIsRequired() == true){?><em>*</em><?php } ?><?php echo $this->__('School') ?></label>
                    <div class="input-box">
                        <select name="school" id="school" class="<?php if($attribute->getIsRequired() == true){?>required-entry<?php } ?>">
                        	<?php
                        		 $options = $attribute->getSource()->getAllOptions();
                        		 foreach($options as $option){
                        	?>
                        		<option value='<?php echo $option['value']?>' <?php if($this->getCustomer()->getSchool() == $option['value']){ echo 'selected="selected"';}?>><?php echo $this->__($option['label'])?></option>
                        	<?php } ?>
                        </select>
                    </div>
                </li>	

Now, you the account information editing should be working.

Step5: Checkout Page Registration

A registration form also shows up at the checkout page in magento. To add you field here, you need to edit checkout/onepage/billing.phtml for magento version 1.6(-) and persistant/checkout/onepage/billing.phtml for magento version 1.6(+) file and then find the code

 <?php if(!$this->isCustomerLoggedIn()): ?>

inside this if condition add your field

<li>
            	 	<li>
            	 	<?php 
            	 		$attribute = Mage::getModel('eav/config')->getAttribute('customer','school');
            	 	?>
                    <label for="school" class="<?php if($attribute->getIsRequired() == true){?>required<?php } ?>"><?php if($attribute->getIsRequired() == true){?><em>*</em><?php } ?><?php echo $this->__('School') ?></label>
                    <div class="input-box">
                        <select name="billing[school]" id="school" class="<?php if($attribute->getIsRequired() == true){?>required-entry<?php } ?>">
                        	<?php
                        		 $options = $attribute->getSource()->getAllOptions();
                        		 foreach($options as $option){
                        	?>
                        		<option value='<?php echo $option['value']?>'><?php echo $this->__($option['label'])?></option>
                        	<?php } ?>
                        </select>
                    </div>
                </li>

Next open your module config.xml or any other config.xml file, add the following lines

<global>
	 <fieldsets>
	   <checkout_onepage_quote>
	   	 <customer_school>
		     <to_customer>school</to_customer>
	     </customer_school>
	   </checkout_onepage_quote>
		<customer_account>
			<school>
				<to_quote>customer_school</to_quote>
			</school>
		</customer_account>	   
	  </fieldsets>
	</global>

Next we need to make some changes in the quote table i.e sales_flat_quote table in magento. If you have a module then create an upgrade version of your sql file and put in this code

$tablequote = $this->getTable('sales/quote');
$installer->run("
ALTER TABLE  $tablequote ADD  `customer_school` INT NOT NULL
");

or if you don’t have a module, then just execute this query in phpmyadmin.

ALTER TABLE  `sales_flat_quote` ADD  `customer_school` INT NOT NULL

After doing this make sure to clear you magento cache, specifically “Flush Magento Cache” and “Flush Cache Storage”.
Now when you place order, the customer is created with the correct school attribute.

Detailed Explanation’s of Steps

The first step is creating an customer attribute. So there are the actual sql queries that get executed, through our code.
First entry it made in the eav_attribute table

INSERT INTO  `eav_attribute` (
`attribute_id` ,
`entity_type_id` ,
`attribute_code` ,
`attribute_model` ,
`backend_model` ,
`backend_type` ,
`backend_table` ,
`frontend_model` ,
`frontend_input` ,
`frontend_label` ,
`frontend_class` ,
`source_model` ,
`is_required` ,
`is_user_defined` ,
`default_value` ,
`is_unique` ,
`note`
)
VALUES (
NULL ,  '1',  'school', NULL , NULL ,  'int', NULL , NULL ,  'select',  'School', NULL ,  'profile/entity_school',  '1',  '0',  '0',  '0',  ''
);

EAV Attribute DB Entry

EAV Attribute DB Entry


After insert query, the attribute generated is my case is 121. Next this attribute needs to be associated to an attribute set, the sql for this is

INSERT INTO  `eav_entity_attribute` (
`entity_attribute_id` ,
`entity_type_id` ,
`attribute_set_id` ,
`attribute_group_id` ,
`attribute_id` ,
`sort_order`
)
VALUES (
NULL ,  '1',  '1',  '1',  '121',  '0'
);
The sort_order value in this table, specifies where the attribute will show in admin.

DB Entry

DB Entry


Next we need to make entry in a table “customer_eav_attribute”

INSERT INTO  `customer_eav_attribute` (
`attribute_id` ,
`is_visible` ,
`input_filter` ,
`multiline_count` ,
`validate_rules` ,
`is_system` ,
`sort_order` ,
`data_model`
)
VALUES (
'121',  '1', NULL ,  '1', NULL ,  '0',  '0', NULL
);

If your using multiple store, you need to make an entry in customer_eav_attribute_website as well, but this entry is not compulsary

INSERT INTO `customer_eav_attribute_website` (
`attribute_id` ,
`website_id` ,
`is_visible` ,
`is_required` ,
`default_value` ,
`multiline_count`
)
VALUES (
'121',  '0',  '1',  '0', NULL , NULL
);

Next we need to make entry in a table called “customer_form_attribute”

INSERT INTO  `customer_form_attribute` (
`form_code` ,
`attribute_id`
)
VALUES (
'adminhtml_customer',  '121'
), (
'checkout_register',  '121'
), (
'customer_account_create',  '121'
), (
'customer_account_edit',  '121'
)
;

Now, if you open magento Admin -> Manage Customers -> Edit Customer, you should be able to see your new attribute in admin.

Adding Multiple Fields

In this section we will see what all changes we need to do in order to add multiple fields to the user profile.

  • First we need to create multiple attributes in database. The create attribute Step1 needs to be repeated for all the attributes which you have. Right now i have done it only for school attribute, but it needs to be done for all attributes you want to add.
  • Ofcouse you need to have different source model’s if you have different drop down attributes. If you don’t have drop down attributes, you don’t need this.
  • The Step3: Registration step , Step4: Edit Account Information and Step5: Checkout Page , we need to change the phtml code to include all our attributes.
  • The entries made in the xml files for customer_account, checkout_onepage_quote fieldsets, needs to be made for all the attributes.
  • In the sales_flat_quote table we need to add columns for each of our attirbutes. Column name would be same as attribute code.

These are the steps required.