You first need to answer the question what do you want to do with the new data.
Should it be stored with the order? Should it be sent somewhere by email?
For now, I'll just assume you want to store it with the order and display it in the backend with the order details.
You will have to take care of the following things:
- Add one attribute for each input field to the order
- Display the input field(s) on the review step
- Make sure the input fields are submitted when the order is saved
- Set the submitted values on the order
- Add a new tab to the order info page in the backend
- Display the field values
Lets go through one by one.
I'm assuming you know how to create a basic module. In the example code I'll assume the module Namespace_ReviewField
.
1. Add one attribute for each input field to the order
To add the order attribute, create a setup script with the following contents, after adding a setup resource and a version number to your module:
/* @var $installer Mage_Sales_Model_Resource_Setup */
$installer = Mage::getResourceModel('sales/setup', 'sales_setup');
$installer->startSetup();
$installer->addAttribute('order', 'my_field', array(
'label' => 'My Field',
'type' => 'varchar',
'input' => 'text',
'required' => false,
));
$installer->endSetup();
2. Display the input field(s) on the review step
To display the input field in the review step, first add a layout XML file to your module:
<frontend>
<layout>
<updates>
<namespace_reviewfieldield>
<file>namespace/reviewfield.xml</file>
</namespace_reviewfieldield>
</updates>
</layout>
</frontend>
Then create the layout XML file base/default/layout/namespace/reviewfield.xml with the following contents:
<?xml version="1.0"?>
<layout>
<checkout_onepage_review>
<reference name="checkout.onepage.review.info.items.after">
<block type="core/template" name="namespace.reviewField" template="namespace/reviewfield/form.phtml"/>
</reference>
</checkout_onepage_review>
</layout>
Finally you create the template base/default/template/namespace/reviewfield/form.phtml
<div class="checkout-agreements">
<input type="text" name="namespace_reviewfield" id="namespace_reviewfield"/>
<label for="namespace_reviewfield">Please specify Foo</label>
</div>
3. Make sure the input fields are submitted when the order is saved
Now the field will be displayed after the totals on the review step. But because the field is not inside of any form, you need to take care it is submitted when the order is saved.
Add the following JavaScript to your form.phtml template.
<script type="text/javascript">
// Add our field to the data submitted by Review.save()
Review.prototype.save = Review.prototype.save.wrap(function(orig) {
var form = this.agreementsForm ? this.agreementsForm : payment.form;
if (form) {
var myfield = $('namespace_reviewfield');
form.insert(myfield);
}
orig();
});
</script>
4. Set the submitted values on the order
Now the field value will be sent to Magento when the order is submitted. Only so far, nothing else happens with it. You have to set the submitted value on the order.
A good way to do that is using an event observer for the checkout_type_onepage_save_order
event.
<frontend>
<events>
<checkout_type_onepage_save_order>
<observers>
<namespace_reviewfield>
<type>model</type>
<class>namespace_reviewfield/observer</class>
<method>checkoutTypeOnepageSaveOrder</method>
</namespace_reviewfield>
</observers>
</checkout_type_onepage_save_order>
</events>
</frontend>
The observer class itself is very simple:
class NameSpace_ReviewField_Model_Observer
{
public function checkoutTypeOnepageSaveOrder(Varien_Event_Observer $observer)
{
/** @var Mage_Sales_Model_Order $order */
$param = Mage::app()->getRequest()->getParam('namespace_reviewfield', '');
$observer->getOrder()->setMyField((string) $param);
}
}
And that takes care of the frontend side of things.
5. Add a new tab to the order info page in the backend
Unfortunately, there is no "nice" way to add content to the general order info page. It's much more compatible to add a new tab with the new content you want to display.
To do that, you first need to add an adminhtml layout XML file:
<adminhtml>
<layout>
<updates>
<namespace_reviewfield>
<file>namespace/reviewfield.xml</file>
</namespace_reviewfield>
</updates>
</layout>
</adminhtml>
The new tab itself is then added in the layout XML declaration. There are several ways this can be done, but I suggest you use the probably most straightforward way by adding the following code to the file adminhtml/default/layout/namespace/reviewfield.xml
<?xml version="1.0"?>
<layout>
<adminhtml_sales_order_view>
<reference name="sales_order_tabs">
<action method="addTab">
<name>namespace_reviewfield</name>
<block>namespace_reviewfield/adminhtml_order_tab_reviewfield</block>
</action>
</reference>
</adminhtml_sales_order_view>
</layout>
6. Display the field values
Now you only need to create the block that you specified in the layout XML and a matching template. The block class has to implement Mage_Adminhtml_Block_Widget_Tab_Interface
, otherwise a "Wrong Tab Configuration" exception will be thrown.
Here is a simple example:
class NameSpace_ReviewField_Block_Adminhtml_Order_Tab_Reviewfield
extends Mage_Adminhtml_Block_Widget
implements Mage_Adminhtml_Block_Widget_Tab_Interface
{
protected function _prepareLayout()
{
$this->setTemplate('namespace/order/tab/reviewfield.phtml');
}
public function getOrder()
{
return Mage::registry('current_order');
}
public function getTabLabel()
{
return $this->__('Review Field');
}
public function getTabTitle()
{
return $this->getTabLabel();
}
public function canShowTab()
{
return true;
}
public function isHidden()
{
return false;
}
}
The final missing thing is the template adminhtml/default/template/namespace/order/tab/reviewfield.phtml. Just make sure you properly escape any user input to avoid XSS holes.
<?php /** @var NameSpace_ReviewField_Block_Adminhtml_Order_Tab_Reviewfield $this */ ?>
<div>
<?php echo $this->__('The customer entered: %s', $this->escapeHtml($this->getOrder()->getMyField())) ?>
</div>
Hope that helps you along the way to implement the functionality you require.