How to create a custom grid from scratch

We received a request from a client where they wanted to implement an expanded order grid while still keeping the default Magento’s one. For this example we’ll create a new module named Inchoo Orders.
Step 1.
Create new module in etc/modules called Inchoo_Orders.xml
<?xml version="1.0"?>
<config>
<modules>
<Inchoo_Orders>
<active>true</active>
<codePool>community</codePool>
</Inchoo_Orders>
</modules>
</config>
Step 2.
Next thing we’ll do is create folder Inchoo/Orders inside app/code/community and inside we’ll make few folders: Block, controllers, etc, Helper.
Step 3.
Create config.xml inside etc folder.
<?xml version="1.0"?>
<config>
<modules>
<Inchoo_Orders>
<version>0.0.0.1</version>
</Inchoo_Orders>
</modules>
<global>
<models>
<inchoo_orders>
<class>Inchoo_Orders_Model</class>
<resourceModel>inchoo_orders_resource</resourceModel>
</inchoo_orders>
</models>
<resources>
<inchoo_orders_setup>
<setup>
<module>Inchoo_Orders</module>
</setup>
</inchoo_orders_setup>
</resources>
<blocks>
<inchoo_orders>
<class>Inchoo_Orders_Block</class>
</inchoo_orders>
</blocks>
<helpers>
<inchoo_orders>
<class>Inchoo_Orders_Helper</class>
</inchoo_orders>
</helpers>
</global>
<admin>
<routers>
<adminhtml>
<args>
<modules>
<inchoo_orders before="Mage_Adminhtml">Inchoo_Orders_Adminhtml</inchoo_orders>
</modules>
</args>
</adminhtml>
</routers>
</admin>
</config>
Step 4
Create adminhtml.xml file inside etc folder which will add a link to our orders page in magento admin panel.
<?xml version="1.0"?>
<config>
<menu>
<sales>
<children>
<inchoo_orders translate="title" module="inchoo_orders">
<sort_order>10</sort_order>
<title>Orders - Inchoo</title>
<action>adminhtml/order/</action>
</inchoo_orders>
</children>
</sales>
</menu>
</config>
Step 5
Create blank helper class.
<?php
class Inchoo_Orders_Helper_Data extends Mage_Core_Helper_Abstract
{
}
Step 6
Next step is to create controller for our grid.
<?php
class Inchoo_Orders_Adminhtml_OrderController extends Mage_Adminhtml_Controller_Action
{
public function indexAction()
{
$this->_title($this->__('Sales'))->_title($this->__('Orders Inchoo'));
$this->loadLayout();
$this->_setActiveMenu('sales/sales');
$this->_addContent($this->getLayout()->createBlock('inchoo_orders/adminhtml_sales_order'));
$this->renderLayout();
}
public function gridAction()
{
$this->loadLayout();
$this->getResponse()->setBody(
$this->getLayout()->createBlock('inchoo_orders/adminhtml_sales_order_grid')->toHtml()
);
}
public function exportInchooCsvAction()
{
$fileName = 'orders_inchoo.csv';
$grid = $this->getLayout()->createBlock('inchoo_orders/adminhtml_sales_order_grid');
$this->_prepareDownloadResponse($fileName, $grid->getCsvFile());
}
public function exportInchooExcelAction()
{
$fileName = 'orders_inchoo.xml';
$grid = $this->getLayout()->createBlock('inchoo_orders/adminhtml_sales_order_grid');
$this->_prepareDownloadResponse($fileName, $grid->getExcelFile($fileName));
}
}
Step 7
Next thing we do is create grid container in Block/Adminhtml/Sales/Order.php
<?php
class Inchoo_Orders_Block_Adminhtml_Sales_Order extends Mage_Adminhtml_Block_Widget_Grid_Container
{
public function __construct()
{
$this->_blockGroup = 'inchoo_orders';
$this->_controller = 'adminhtml_sales_order';
$this->_headerText = Mage::helper('inchoo_orders')->__('Orders - Inchoo');
parent::__construct();
$this->_removeButton('add');
}
}
Step 8
Last step is making grid class in Block/Adminhtml/Sales/Order/Grid.php
<?php
class Inchoo_Orders_Block_Adminhtml_Sales_Order_Grid extends Mage_Adminhtml_Block_Widget_Grid
{
public function __construct()
{
parent::__construct();
$this->setId('inchoo_order_grid');
$this->setDefaultSort('increment_id');
$this->setDefaultDir('DESC');
$this->setSaveParametersInSession(true);
$this->setUseAjax(true);
}
protected function _prepareCollection()
{
$collection = Mage::getResourceModel('sales/order_collection')
->join(array('a' => 'sales/order_address'), 'main_table.entity_id = a.parent_id AND a.address_type != \'billing\'', array(
'city' => 'city',
'country_id' => 'country_id'
))
->join(array('c' => 'customer/customer_group'), 'main_table.customer_group_id = c.customer_group_id', array(
'customer_group_code' => 'customer_group_code'
))
->addExpressionFieldToSelect(
'fullname',
'CONCAT({{customer_firstname}}, \' \', {{customer_lastname}})',
array('customer_firstname' => 'main_table.customer_firstname', 'customer_lastname' => 'main_table.customer_lastname'))
->addExpressionFieldToSelect(
'products',
'(SELECT GROUP_CONCAT(\' \', x.name)
FROM sales_flat_order_item x
WHERE {{entity_id}} = x.order_id
AND x.product_type != \'configurable\')',
array('entity_id' => 'main_table.entity_id')
)
;
$this->setCollection($collection);
parent::_prepareCollection();
return $this;
}
protected function _prepareColumns()
{
$helper = Mage::helper('inchoo_orders');
$currency = (string) Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE);
$this->addColumn('increment_id', array(
'header' => $helper->__('Order #'),
'index' => 'increment_id'
));
$this->addColumn('purchased_on', array(
'header' => $helper->__('Purchased On'),
'type' => 'datetime',
'index' => 'created_at'
));
$this->addColumn('products', array(
'header' => $helper->__('Products Purchased'),
'index' => 'products',
'filter_index' => '(SELECT GROUP_CONCAT(\' \', x.name) FROM sales_flat_order_item x WHERE main_table.entity_id = x.order_id AND x.product_type != \'configurable\')'
));
$this->addColumn('fullname', array(
'header' => $helper->__('Name'),
'index' => 'fullname',
'filter_index' => 'CONCAT(customer_firstname, \' \', customer_lastname)'
));
$this->addColumn('city', array(
'header' => $helper->__('City'),
'index' => 'city'
));
$this->addColumn('country', array(
'header' => $helper->__('Country'),
'index' => 'country_id',
'renderer' => 'adminhtml/widget_grid_column_renderer_country'
));
$this->addColumn('customer_group', array(
'header' => $helper->__('Customer Group'),
'index' => 'customer_group_code'
));
$this->addColumn('grand_total', array(
'header' => $helper->__('Grand Total'),
'index' => 'grand_total',
'type' => 'currency',
'currency_code' => $currency
));
$this->addColumn('shipping_method', array(
'header' => $helper->__('Shipping Method'),
'index' => 'shipping_description'
));
$this->addColumn('order_status', array(
'header' => $helper->__('Status'),
'index' => 'status',
'type' => 'options',
'options' => Mage::getSingleton('sales/order_config')->getStatuses(),
));
$this->addExportType('*/*/exportInchooCsv', $helper->__('CSV'));
$this->addExportType('*/*/exportInchooExcel', $helper->__('Excel XML'));
return parent::_prepareColumns();
}
public function getGridUrl()
{
return $this->getUrl('*/*/grid', array('_current'=>true));
}
}
Our new custom orders page can be accessed by going to Sales -> Orders – Inchoo in admin panel.
End result should be something like this:
However, if you’re having trouble with Magento development, we would be happy to help. Our team of experts can check out your site and get you a detailed report based on a personalized technical audit. Feel free to get in touch!
93 comments
Works like a charm, thanks! =)
July 6, 2018 and still works magento CE 1.9.3.8
However I need To add Product attributes please let me know if its possible
I have the blank screen error. I narroved it to the line
$this->_addContent($this->getLayout()->createBlock(‘inchoo_orders/adminhtml_sales_order’));
. If I comment out the line, I have at least Magento Header and footer and blank white between. So there’s something with the function or the Grid.php. Version is 1.9.0.1. What have changed?
THe filters for a custom collection does not work
Hi thanks for the tutorial I followed all steps exactly, refresh the admin page but no ‘Inchoo Orders’ item appearing under Sales menu ? Is something else needed (cache clearing / smth)? If yes, can you include it in the tutorial ?
ah ok got it had wrong codePool (should have been ‘local’ since I put my code under local not community, community should be reserved for 3rd party ‘community’ code)
renderLayout() is timing out:
https://magento.stackexchange.com/questions/192370/layout-getoutput-debugging
i could not get the inchoo orders in sales tab please help me to resolve this
Great article for some one who knows magento little bit.Please update the article with file paths too
hey I am getting the menu but admin panel table is not seen on click the menu
sir i have created module but it displaying only menu and not showing the table the grid is not working proper
Working great thanks. I have a dought.
Now i am able to see custom grid, instead of sales model i need to display my own table values into it(Product faqs). I have a product faqs table, i need to fetch from this table and display.
How can i do this please someone help.
regarding 404 page not found help in step 6
Regarding ” 404 Page Not found”..
Guys move “OrderController.php” to “controllers\Adminhtml\”
Thanks And Enjoy….
Regarding “Fatal error: Call to a member function setSaveParametersInSession() on a non-object in ”
Guys… this is happening becouse of folder path…
check
Order.php should in “\Block\Adminhtml\Sales”
AND
Grid.php should in “\Block\Adminhtml\Sales\Order”
Thanks Enjoy…..
Resolution for 404 Page Not found is to move your controller to adminhtml folder with-in the controllers folder.
hello guys help me in step 5.
which path of “Create blank helper class.”
and step 6
which path of “create controller for our grid”
I have followed all steps and Order – Inchoo sub menu is there in Sales menu but when I click on it, it leads to 404 Page Not found. could you tell what is the missing part.. I have checked it lots of time.
what is the importance of this function..?
public function gridAction()
it never called
Use this code to add ACL in adminhtml.xml
There are a few tweaks you can make that are helpful, including the ACL one you mentioned. I added some to a GitHub Repo a couple years ago if you’re interested magento-admin-custom-sales-order-grid. The ReadMe shows what edits I made.
How to make the row clickable , I mean, I used getrowurl for it but I want to make a custom sales_order/view block inside incho_orders module. how can i do that?
Nice tutorial, but what should I change if I want to use a different link than adminhtml/order/ for the grid?
So okay I found it. Would be nice if this was clearly mentioned in the tutorial.
For those of you who were also looking for this, in case if you want to add several custom grids, or you just want to have it a more suitable name. You CAN change the url route for the grid.
So for example if you want to change “adminhtml/order/” to “adminhtml/mygrid/”.
In the adminhtml.xml change adminhtml/order/ to adminhtml/mygrid/
Then change the file AND classname of the controller in controllers/Adminhtml/ from OrderController.php to MygridController.php (Yes you should put the controller in the Adminhtml subfolder for it to work, something they also didn’t mention in this tutorial)
Of course make sure you change the class name of the controller as well. That’s it.
hello my first question is where i can create helper class
and second is contoller
plz give path
Its working fine only we have to do is please place our controller in adminhtml folder
Change adminhtml.xml tag content like this :
adminhtml/sales_order/
This Will Work Fine
thnx bro…finally the o/p came 🙂
Try to use filter on Name or Products Purchased. There is a problem with filter index on these 2 columns:
When filter_index value is added to MySQL query it is wrapped inside “, what makes SQL error.
I am getting same error as below:
Unknown column ‘CONCAT(firstname, ‘ ‘, lastname)’ in ‘where clause’
Please provide solution.
Same problem with products filtering, solved with this (Grid.php):
protected function _productsFilter($collection, $column)
{
if (!$value = $column->getFilter()->getValue()) {
return $this;
}
$this->getCollection()->getSelect()->where(
"(SELECT GROUP_CONCAT(' ', x.name) FROM sales_flat_order_item x WHERE x.product_type !='configurable' AND main_table.entity_id = x.order_id ) LIKE ?"
, "%$value%");
return $this;
}
in _prepareColumns method:
$this->addColumn('products', array(
'header' => $helper->__('Prodotti Acquistati'),
'index' => 'products',
'filter_condition_callback' => array($this, '_productsFilter')
));
I see 404 too 🙁
Its Shows 404 only.not working
put controller in adminhtml folder
Hi, Thank You the code ..
Please Help Me i got a error Call to a member function setSaveParametersInSession() .
Please give a guidance for it ..
Working Like a charm , Thanks 🙂
Hi,
I followed all steps you defined above.But when i click on “Order-Inchoo” it shows 404 error.why?
I have followed all steps and Order – Inchoo sub menu is there in Sales menu but when I click on it, it leads to 404 Page Not found. could you tell what is the missing part.. I have checked it lots of time.
It’s is possible to add the acl role capabilities to this module ?
I run this module …. in first attempt. without any error.
Not working as all,
not even visible in menu.and many folks having same issue i can read that
help me
Latest Message: Second Reminder: Download and install Magento critical security patches now. Read details
I can see blank page with no content.
I have puth my controller on proper place, also try to put it in local folder with respective path.
still not getting any output .
Need your suggestions.
Hi guys! Thanks for you post. It helped me to understand grids building.
Here is precondition:
I had some rules form in admin, that was available by */*/edit url. Purpose was to integrate tabs and grid from a bit another location with own controller. This form moved to General tab, in the second one I integrated form with grid (like in quote_promo manage coupon codes in native Magento). As a result I got smth like that.
Faced with the next problem:
When I try to search smth in grid, f.e. coupon code by typing query and pressing Enter button, I see in Firebug console that query processing to (ajax) grid url is terminated and then redirect happens to Save action (form action), and since there is no rule_id in POST data, it redirects to rule index page with grid.
Do you have any idea why is that happen?
Seems like there is some bind to input that ‘trigger’ save action method.
Thanks for your reply!
Waiting for it so much!
Wonderful article works great on magento 1.9.1
For all those who are getting errors, make these changes only :
add your controller to app\code\local\Inchoo\Orders\controllers\Adminhtml\OrderController.php
And tell me if anyone interested to view order on click. I have managed to sort it out. Enjoy magento !
What should be the name of files of step 5 and 6,
Hi Vedran, Thank you for the nice tutorial and I installed it on my magento. Meanwhile, I would like to filter the results by Store wise(I have multiple stores). Could you please let me know, how can we place a store filter drop down in the top of the order lising.
Vedran, thank you very much for these great tutorial. I have one problem with this. If you click multiple times on the upper header to sort the fields an error message appears.
The error is:
Item (Mage_Sales_Model_Order) with the same id “1242” already exists.
Do you have any idea why this could happen. BTW: I haven’t changed anything to your sourcecode for this test.
Best regards
Martin
Hi,
I follow all instruction at last it showing page not found in localhost wamp which I newly installed, please help me
Is there any way to use the same grid in the frontend to display order details?
Really awesome … This is the exact code which i am searching. Thanks a lot.
Fatal error: Call to a member function setSaveParametersInSession() on a non-object in /opt/lampp/htdocs/layoutmagento/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Container.php on line 66
I have error in the same code you have writte above. Please help me
Hi
i have error in the same you have written above
Fatal error: Call to a member function setSaveParametersInSession() on a non-object in /opt/lampp/htdocs/layoutmagento/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Container.php on line 66
Please help.
how did you sort this out ,,, can you help me ,, i have same error , plz help
Fatal error: Call to a member function setSaveParametersInSession() on a non-object in /opt/lampp/htdocs/layoutmagento/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Container.php on line 66
I have the blank screen error. I narroved it to the line
. If I comment out the line, I have at least Magento Header and footer and blank white between. So there’s something with the fuction or the Grid.php. Version is 1.9.0.1. What have changed?
Hi Vedran
I have used this and it is working fine.
I want to make some checks in query by using my custom table. Could you please guide me how can i implement this in grid.php ?
Thanks in advance
Hai I am also seeking the requirement I need to display the orders from custom created tables. Did u got the idea Please share if any code available to implement. Thanks in advance
and can you please tell me how can i add import csv functionality in this
thanks
HI first of all thanks for such a nice post.It works perfect.
But i have a some confusion in the config.xml file.
in that there is a model
Inchoo_Orders_Model
inchoo_orders_resource
we have defined but we dont have a model class for this so why dont it has raise a errot .
Please tell me i just learning magento extensions
thanks
thanks mark its realy helpful to solve me that error
Hi Azhar,
its not working with me and i got 404 error. Can you please help me out.
Thanks
This helped so much!!! For those having issues with the 404 page, you most likely do not have the OrderController.php in the right folder. It should be controllers/Adminhtml/OrderController.php
Perfect – Was looking for something like this for ages. I can confirm this works perfectly on the new version of 1.8.1 as well.
i try to use this code but not working and give black screen.
please Vedran Sola why this not work??
thanks in advanced
For those getting a 404 Not Found Error when trying to access the grid, I found the issue was where I put my OrderController.php file. It needs to be Inchoo/Orders/controllers/Adminhtml/OrderController.php
Originally I had put it in Inchoo/Orders/controllers/OrderController.php and this doesn’t work.
Hi,
This is very good extension. In our custom grid orders are showing but it better link provide to the orders to the order detailed page. Can you please guide the hyperlink to redirect the order page when we click on that order.
I am gettign this error whenever I tried to open this module from admin site
Parse error: syntax error, unexpected ‘Â Â Â Â public’ (T_STRING), expecting function (T_FUNCTION) in C:\xampp\htdocs\magento\app\code\community\Inchoo\Orders\controllers\Adminhtml\OrderController.php on line 9
Can anyone help me for that
I make my own module using your concept but grid content are not shown… help me out to fix this problem
Thank you very much for your post!
Anyone know how to generate in a cronjob the csv with this content?
is for integration with a sales soft
thankyou in advance
Sam at RocketTheme helped me out with the database prefix issue.
Change out the table name:
With this:
That will retrieve any prefix for your current install.
Looks like this adds the row url, which I just pulled from the core Grid.php file:
public function getRowUrl($row)
{
if (Mage::getSingleton(‘admin/session’)->isAllowed(‘sales/order/actions/view’)) {
return $this->getUrl(‘*/sales_order/view’, array(‘order_id’ => $row->getId()));
}
return false;
}
That added just above the grid url code near the end.
Got things working and this is a great walk through.
Two things I noticed are that a database table prefix needs to be defined in the Grid.php file code and that the row does not link to the order details.
Is it possible to get the row linked to the order details?
how can i do same for managed products
Y i need to just make a file in helper when there is no data in it ? I am just declaring the file & not writing any content in it.
Thanks so much!
I’ve been trying to add the Customer group to the grid for days now…
Regards,
Seb
Hi,
I can see the Order – Inchoo under the Sales tab in the admin. However when I click on it, it gives me a 404 error.
Below is the link it is pointing to:
http://127.0.1.1/bakery/index.php/order/adminhtml_order/index/key/463b6f9049cf6c0eca7f56eba7a9b7ad/
Is this link correct? I have verified the file structure and it is same as mentioned above.
I am guessing something is wrong with my etc/adminhtml.xml.
10
Orders – Bakery
order/adminhtml_order
Please advice.
Thanks,
Neet
Hi,
I am running magento 1.7, and followed the steps above to create a new grid. However when I click on it from the admin page, I get a 404, page not found error. I don’t see the new grid details :((.
Please help.
Thanks,
Neet
I got same errors so I just changed few lines.
Wrong :
class Inchoo_Orders_Adminhtml_OrderController extends Mage_Adminhtml_Controller_Action
{
Right :
include(‘Mage/Adminhtml/controllers/Sales/OrderController.php’);
class Inchoo_Orders_Adminhtml_OrdersController extends Mage_Adminhtml_Sales_OrderController
{
and
in adminhtml.xml
10
Orders – Inchoo
order/adminhtml_orders
i did it but page load with empty screen there is no data or nothing no errors
Take a look at screenshot, perhaps you’re missing something: http://i.imgur.com/odIXoUz.png?1
@Kaysellers
Hi,
did you try to clear the cache?
Hi,
I am getting the same error as Hissam and Kaysellers.
What version does this work on?
i just implemented this on our of our projects and i must say it worked flawlessly.
Hello ,
I am facing the same problem as of Hissam Roohi.
What could be the issue?? I think that might be the issue due to some wrong configuration. Can you please let me know what could be the issue
When i click the Orders- Inchoo sub menu , i am getting the error ‘The page you requested was not found, and we have a fine guess why.’
After clicking it is redirecting the below url :
“https://inchoo.net/magento17/index.php/admin/order/index/key/1bce285af813fee9aa5d18881474c09e/”
@Vedran Sola -Can you please help me out
Nice!
Data.php is helper and controller class should go to controllers/Adminhtml/Order.php
Hey Vedran,
This looks very interesting. I got lost at steps 5 and 6. What files should contain the blank helper class and the controller for our grid?
Thanks,
@Kieran
gridAction is being called by getGridUrl method in Grid.php and its purpose is to enable grid filtering using ajax.
Hi,
I have followed your guide but when I click on the link it simple gives me a blank screen not showing the grid. One thing i was wondering, where does it call the gridAction from the controller?
Very interesting. For my experience a current problem is to create a master/details grid. Have you got a road to?
regards
filippo.
Congrats Vedran on your first post!