Question

I need to add custom text field to "add review" form, for example email.

There are already some threads on web where people are asking the same thing, but none of them has a solid answer. Most suggest to modify core files directly, or run manual SQL queries.

If you know some open-source plugin that adds such feature, or you already implemented this somewhere, please share how you did it.

Thank you!

Was it helpful?

Solution

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:

  1. Add one attribute for each input field to the order
  2. Display the input field(s) on the review step
  3. Make sure the input fields are submitted when the order is saved
  4. Set the submitted values on the order
  5. Add a new tab to the order info page in the backend
  6. 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.

OTHER TIPS

I know it's an old post, but there's a problem with the step 3. It should be like this:

var form = $(this.agreementsForm) ? $(this.agreementsForm) : $(payment.form);
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top