Magento tutorial – Adding Custom fields to the order and/or checkout page

Sometimes you need to add custom fields to order / checkout page to make it more interactive. Magento Custom fields are used to collect more information about your customer and product. This blog demonstrates how to add custom field to checkout in billing step and the method works for all Magento 1 versions. Following is a step by step example of adding a single custom field in the billing step.

Step 1: Adding HTML

The following code will add a text field to the billing.phtml file.
For magento 1.6(-) the file to edit is checkout/onepage/billing.phtml and for magento 1.6(+) you need to edit file persistent/checkout/onepage/billing.phtml. Open the phtml file, find the code

<?php if ($this->canShip()): ?>

and just above the line add this

<li class="fields">

<div class="field">

<label for="billing:ssn" class="required"><em>*</em><?php echo $this->__('SSN') ?></label>

<div class="input-box">

<input type="text" name="custom[ssn]" value="<?php echo $this->htmlEscape($this->getQuote()->getSsn()) ?>" title="<?php echo $this->__('SSN') ?>" class="input-text required-entry" id="billing:ssn" />

</div>

</div>

</li>

 

Step2: Save the field in Quote and Order Tables

Create two tables. ‘sales_quote_custom’ for sales and ‘sales_order_custom’for order. Open phpmyadmin and confirm if the quote and order tables are created. Next we need to write some event observers to capture quote save, and load events. So open your modules config.xml file and inside the <global> tag put in

<events>

<sales_quote_save_before> <!-- Event Called Before Quote Object is saved -->

<observers>

<save_before>

<type>singleton</type>

<class>Excellence_Custom_Model_Observer</class> <!-- Over Model Class -->

<method>saveQuoteBefore</method> <!-- name of function -->

</save_before>

</observers>

</sales_quote_save_before>

<sales_quote_save_after> <!-- Event called After Quote Object is saved -->

<observers>

<save_after>

<type>singleton</type>

<class>Excellence_Custom_Model_Observer</class> <!-- Over Model Class -->

<method>saveQuoteAfter</method> <!-- name of function -->

</save_after>

</observers>

</sales_quote_save_after>

<sales_quote_load_after> <!-- Event called when Quote Object is loaded -->

<observers>

<load_after>

<type>singleton</type>

<class>Excellence_Custom_Model_Observer</class> <!-- Over Model Class -->

<method>loadQuoteAfter</method> <!-- name of function -->

</load_after>

</observers>

</sales_quote_load_after>

<sales_model_service_quote_submit_after> <!-- Event called after order placed -->

<observers>

<sales_model_service_quote_submit_after>

<type>singleton</type>

<class>Excellence_Custom_Model_Observer</class> <!-- Over Model Class -->

<method>saveOrderAfter</method> <!-- name of function -->

</sales_model_service_quote_submit_after>

</observers>

</sales_model_service_quote_submit_after>

<sales_order_load_after> <!-- Event called after Order Object is loaded -->

<observers>

<sales_order_load_after>

<type>singleton</type>

<class>Excellence_Custom_Model_Observer</class> <!-- Over Model Class -->

<method>loadOrderAfter</method> <!-- name of function -->

</sales_order_load_after>

</observers>

</sales_order_load_after>

</events>

and next we need to create our Observer classes in Model folder. So create an Observer.php in your modules Model folder.

<?php
class Excellence_Custom_Model_Observer{ 

public function saveQuoteBefore($evt){

$quote = $evt->getQuote();

$post = Mage::app()->getFrontController()->getRequest()->getPost();

if(isset($post['custom']['ssn'])){

$var = $post['custom']['ssn'];

$quote->setSsn($var);

}

}

public function saveQuoteAfter($evt){

$quote = $evt->getQuote();

if($quote->getSsn()){

$var = $quote->getSsn();

if(!empty($var)){

$model = Mage::getModel('custom/custom_quote');

$model->deteleByQuote($quote->getId(),'ssn');

$model->setQuoteId($quote->getId());

$model->setKey('ssn');

$model->setValue($var);

$model->save();

}

}

}

public function loadQuoteAfter($evt){

$quote = $evt->getQuote();

$model = Mage::getModel('custom/custom_quote');

$data = $model->getByQuote($quote->getId());

foreach($data as $key => $value){

$quote->setData($key,$value);

}

}

public function saveOrderAfter($evt){

$order = $evt->getOrder();

$quote = $evt->getQuote();

if($quote->getSsn()){

$var = $quote->getSsn();

if(!empty($var)){

$model = Mage::getModel('custom/custom_order');

$model->deleteByOrder($order->getId(),'ssn');

$model->setOrderId($order->getId());

$model->setKey('ssn');

$model->setValue($var);

$order->setSsn($var);

$model->save();

}

}

}

public function loadOrderAfter($evt){

$order = $evt->getOrder();

$model = Mage::getModel('custom/custom_order');

$data = $model->getByOrder($order->getId());

foreach($data as $key => $value){

$order->setData($key,$value);

}

}

}

 

Step3: Display Our Field in My Account -> View Order

After the order is placed by the customer, our custom fields needs to be visible in My Account. So to do this in our module fronted layout file, in my case its custom.xml.

<?xml version="1.0"?>

<layout version="0.1.0">

<sales_order_view>

<reference name="my.account.wrapper">

<block type="custom/custom_order" name="custom.order" template="custom/order.phtml" after='sales.order.info' />

</reference>

</sales_order_view>

</layout>

 

This layout file is simple and understandable. Basically, we are taking reference of my.account.wrapper block and adding a child block to it. Our block type is custom/order_view and template file is custom/order.phtml.
So we need to create our block class

<?php

class Excellence_Custom_Block_Custom_Order extends Mage_Core_Block_Template{

public function getCustomVars(){

$model = Mage::getModel('custom/custom_order');

return $model->getByOrder($this->getOrder()->getId());

}

public function getOrder()

{

return Mage::registry('current_order');

}

}

and our order.phtml file

<div class="col-set order-info-box">

<div class="col">

<div class="box">

<div class="box-title">

<h2><?php echo $this->__('Custom Fields') ?></h2>

</div>

<div class="box-content">

<?php

$custom = $this->getCustomVars();

foreach($custom as $key => $value){

?>

<b><?php echo $this->__($key);?></b> : <?php echo $value;?> <br/>

<?php } ?>

</div>

</div>

</div>

</div>

 

Step4: Admin Order View Page

Next we need to show our custom field in Admin -> Order -> View Order page. To do this, in our adminhtml layout file, in my case custom.xml we will put in this code.

<?xml version="1.0"?>

<layout version="0.1.0">

<adminhtml_sales_order_view>

<reference name="order_info">

<action method='setTemplate'><template>custom/sales/order/info.phtml</template></action>

<block type="adminhtml/sales_order_view_info" name="order_info2" template="sales/order/view/info.phtml"></block>

<block type="custom/adminhtml_custom_order" name="custom.order" template='custom/order.phtml'/>

</reference>

</adminhtml_sales_order_view>

</layout>


So basically here we have added my block “custom.order” to the existing order_info block. So the code for block class custom/adminhtml_custom_order would be

<?php

class Excellence_Custom_Block_Adminhtml_Custom_Order extends Mage_Adminhtml_Block_Sales_Order_Abstract{

public function getCustomVars(){

$model = Mage::getModel('custom/custom_order');

return $model->getByOrder($this->getOrder()->getId());

}

}

and next we need to create their phtml files

custom/order.phtml

<?php $_order = $this->getOrder() ?>

<div class="box-left">

<div class="entry-edit">

<div class="entry-edit-head">

<h4 class="icon-head head-account"><?php echo Mage::helper('sales')->__('Custom Fields') ?></h4>

</div>

<div class="fieldset">

<table cellspacing="0" class="form-list">

<?php

$custom = $this->getCustomVars();

foreach($custom as $key => $value){

?>

<tr>

<td style="width:10%" class="label"><strong><?php echo Mage::helper('sales')->__($key) ?></strong></td>

<td class="value"><?php echo $value;?></td>

</tr>

<?php } ?>

</table>

</div>

</div>

</div>

<div class="clear"></div>

custom/sales/order/info.phtml

<?php echo $this->getChildHtml('order_info2');?>

<?php echo $this->getChildHtml('custom.order');?>

Step5: Adding Custom Fields to Order Email

To do this open the order email template located at
app\locale\en_US\template\email\sales\order_new.html
app\locale\en_US\template\email\sales\order_new_guest.html
add the below code where you want

{{depend order.hasCustomFields()}}

<table cellspacing="0" cellpadding="0" border="0" width="650">

<thead>

<tr>

<th align="left" width="325" bgcolor="#EAEAEA" style="font-size:13px; padding:5px 9px 6px 9px; line-height:1em;">Custom Fields:</th>

</tr>

</thead>

<tbody>

<tr>

<td valign="top" style="font-size:12px; padding:7px 9px 9px 9px; border-left:1px solid #EAEAEA; border-bottom:1px solid #EAEAEA; border-right:1px solid #EAEAEA;">

{{var order.getFieldHtml()}}

&nbsp;

</td>

</tr>

</tbody>

</table>

{{/depend}}

<br/>

So as per the above code, we need to two functions hasCustomFields() and getFieldHtml() in our Order class. So next we will override the Mage_Sales_Model_Order model. Open your config.xml file and inside <models> section put in this code

<sales>

<rewrite>

<order>Excellence_Custom_Model_Sales_Order</order>

</rewrite>

</sales>

and next create our new model class Excellence_Custom_Model_Sales_Order

<?php

class Excellence_Custom_Model_Sales_Order extends Mage_Sales_Model_Order{

public function hasCustomFields(){

$var = $this->getSsn();

if($var && !empty($var)){

return true;

}else{

return false;

}

}

public function getFieldHtml(){

$var = $this->getSsn();

$html = '<b>SSN:</b>'.$var.'<br/>';

return $html;

Leave a Reply

Your email address will not be published. Required fields are marked *