This article introduces a best practice about magento admin grid customizations.
When you want to customize a magento grid (for instance, add new columns), you can use the magento rewrite mechanism to achieve your goal :

The old fashioned method


1. Declare the rewrite in your module config.xml file :

<sales_order_grid> MyCompany_MyModule_Block_Adminhtml_Sales_Order_Grid</ sales_order_grid >


2. Create the new class that extends the grid :

class MyCompany_MyModule_Block_Adminhtml_Sales_Order_Grid extends Mage_Adminhtml_Block_Sales_Order_Grid


3. Add your columns :

$this->addColumn(‘MyColumn’, array(
    ‘header’ => Mage::helper(MyModule )->__( ‘My Column’),
  ‘index’ => ‘entity_id’,
    ‘renderer’  => MyCompany_MyModule _Block_Widget_Grid_Column_Renderer_MyRenderer’ ,
  ‘sortable’  => false
));


4. It works :

Image

Even if this methods works perfectly, it causes a major issue : if another magento extension rewrites the same grid, there will be a conflict and one of the 2 extension will not properly work.
Hopefully, using Magento mechanism we can find a workaround

The smart method

The best method is too use Magento events rather than rewrites.

 

1. Listen to events raised when user displays the sales order grid page :

<events> <controller_action_layout_render_before_adminhtml_sales_order_index>
<
observers>

            < MyModule >
                < type>singleton</ type>
                                        < class>MyModule/Observer</ class>
                <method>controller_action_layout_render_before_adminhtml_sales_order_index </method>
            </ MyModule >
</observers>
</controller_action_layout_render_before_adminhtml_sales_order_index>

 

2. In the event handler, dynamically retrieve the grid block and raise a new event with that grid in parameters:

 

public function controller_action_layout_render_before_adminhtml_sales_order_index(Varien_Event_Observer $observer)
{

    $gridBlock = Mage::getSingleton( ‘core/layout’)->getBlock(‘sales_order.grid’);

    if ($gridBlock)

        Mage::dispatchEvent( ‘sales_order_grid_before_render’ , array( ‘grid’=>$gridBlock ));

    return $this;

 

}

 

3. Listen that event yourself (this part is optionnal, you can integrate the following code in #2) :

 
<sales_order_grid_before_render >
    <observers>
                  <MyModule >
            < type>singleton</ type>
                              < class>MyModule /Observer</ class>
            <method>sales_order_grid_before_render </method>
                 </MyModule >
    </observers>
</sales_order_grid_before_render >

 

4. Catch this event to add your own column :

 

public function sales_order_grid_before_render(Varien_Event_Observer $observer) {$grid = $observer->getEvent()->getgrid();

    $grid ->addColumnAfter(MyColumn , array(
        ‘header’=> Mage::helper( MyModule )->__(My Column ),
        ‘align’ => ‘center’,
‘entity’ => ‘order’,
‘filter’ => false,
‘sortable’ => false,
                 ‘width’ => ’60px’
    ),‘real_order_id’);
 
    return $this;
}

 

5. It works too :

 

Image

 

 

6. In fact, it partially works :

If you try to sort / filter or change the page on this grid, you’ll see that our column will disappear. The reason is that the grid is updated in ajax, and then request a diffferent url.
To fix the problem, add an additionnal listener to your config.xml :

<controller_action_layout_render_before_adminhtml_sales_order_grid >
<
observers>
<
AdvancedStock>
<
type>singleton</ type>
<
class>AdvancedStock/Observer</ class>
<
method>controller_action_layout_render_before_adminhtml_sales_order_index </method>
</
AdvancedStock>    </observers></controller_action_layout_render_before_adminhtml_sales_order_grid>

 
And now, it works perfectly !
 
 


Want to say something ?