Adding A Custom Column In The Admin Grid In Magento 1.9

Adding A Custom Column In The Admin Grid In Magento 1.9

One of the best things about working in magento is that if you are comfortable with an object oriented style, you start seeing patterns everywhere. If a new functionality calls for it, you can add a child class and with a little bit of magento-xml-config-magic, you can add virtually (well, concretely) anything new by replacing the existing class. Recently, one of the interesting things one of our clients asked us to do was to add an extra column in the orders grid in the magento admin.

This translates into modifying the Mage_Adminhtml_Block_Sales_Order_Grid class. So if we do a little bit of OOP-ing over here, this just means that we have to override this class and add our own.

Step-1: Creating a module

1. Creating your own folder directory under local. I used local/RLTSquare/MyModule.

2. Registering your module with magento. This is a simple matter of creating an RLTSquare_MyModule.xml file under etc/modules, with the following text:

<config>
	<modules>
		<RLTSquare_MyModule>
			<active>true</active>
			<codePool>local</codePool>
		</RLTSquare_MyModule>
	</modules>
</config>

3. Create a config.xml file under local/RLTSquare/MyModule/etc, with the following text in it:

<config>
	<modules>
		<RLTSquare_MyModule>
			<version>0.1.0</version>
		</RLTSquare_MyModule>
	</modules>
</config>

Step-2: Overriding the class

1. Add a node in our config.xml file (just under the root ‘config’ node) that we created above:

<global>
	<blocks>
		<adminhtml>
			<rewrite>
				<sales_order_grid>RLTSquare_MyModule_Block_Sales_Order_Grid</sales_order_grid>
			</rewrite>
		<adminhtml>
	<blocks>
<global>

2. Create a file named Grid.php under local/RLTSquare/MyModule/Block/Sales/Order. I will skip the reasoning behind these particular names and directory structures, though magento veterans will recognize the order in this (apparent) chaos.

3.Finally, let’s bring our attention to the Grid.php file. This will contain our overridden class.

class RLTSquare_MyModule_Block_Sales_Order_Grid extends Mage_Adminhtml_Block_Sales_Order_Grid
{
	// In this function, we add the extra column that we want
	protected function _prepareColumns()
	{
		parent::_prepareColumns();
 
		//The new column will be added in the second place
		$this->addColumnAfter('column_name', array(
			'header'=> Mage::helper('sales')->__('Grid Header'),
			'width' => '80px',
			'type' => 'text',
			'index' => 'columns_name',
		), 'real_order_id');
 
		$this->sortColumnsByOrder();
 
		return this;
	}
 
	protected function _prepareCollection()
	{
		//Adding code to populate the column. Here, we are assuming that the new
		//column is in the 'order' table
		$collection = Mage::getResourceModel($this->_getCollectionClass());
		$collection->join(array('rTable' => 'sales/order'), 
			'main_table.entity_id=rTable.entity_id', 
			array(self::OLD_ORDER_ID=>self::OLD_ORDER_ID), null,'left');
		$this->setCollection($collection);
 
		return parent::_prepareCollection();
	}
}

And this is where the trouble will begin.

 

The Problem with the Solution

You see, the problem is that in the last line of _prepareCollection, when you call the parent class function to in the end to let it do what it wants with the $collection variable, it completely overwrites it, thus rendering our extra lines of code irrelevant. A little bit of debugging will show that our code in this function, despite being run properly, is absolutely useless when the variable is reassigned in the parent class.

What to do now? A little bit of googling led me here, to this great blog piece by the people at Inchoo. The solution described here works perfectly, with one very nagging issue: Instead of overriding the class that actually needs to be overridden, they override its parent and then copy all the relevant code into their own custom class, before adding their own. This seems horribly un-OOP-ish and I can’t come to terms with this. Not to mention the fact that if the original code changes due to a magento upgrade, our overridden file would have to be coded again.

So, is there a better way? The way I chose to do it was that instead of calling the parent class function at the end, I called the grandparent class function by the following line of code:

call_user_func(array(get_parent_class(get_parent_class($this)), '_prepareCollection'));

This way, my new class gets to have only the minimum amount of code that it needs, and the problematic piece of code (which I do not need) is bypassed. I think this is much more elegant solution.

Anyone have any better ideas? Is calling a grandparent function like this not a good idea? Do comment!

Back to blog