Magento Admin Module: A Comprehensive Guide

Posted on: 11 Feb 2020 by Admin

In this blog our developerswill show you how to add a grid with tab in an admin page. I have added a grid for showing news in admin side and there is an option for adding, editing and deleting news. I have implemented the WYSIWYG editor also. In the last of this tutorial, I have explained how to add the WYSIWYG editor also. You can check the screenshot to get basic idea of what we are going to do in this tutorial.

Let’s see more about Magento admin module development with Grid and Tab

The folder structure will be the grid.

Here is the first tab for adding new news and the second one is the second tab for adding the content with WYSIWYG editor.

Create the module News in the namespace of Threemauto.
Step 1: First we will create the directory structure for our module

app/code/local/Threemauto/News/Block
app/code/local/Threemauto/News/controllers
app/code/local/Threemauto/News/etc
app/code/local/Threemauto/News/Helper
app/code/local/Threemauto/News/Model
app/code/local/Threemauto/News/sql

 

Step 2 : Create a configuration file for the module in the location app/code/local/Threemauto/News/etc/config.xml

0.1.0

With the help of this file Magento will read our module News. Here Threemauto_News is the name of our module. Step 3: Newt we want to activate our module by creating Threemauto_News.xml in the location app/etc/modules/. The content of the file should be

true 
local

Step 4: Now we are going to configure the route. For that add the following code in thetag of the config.xml file

standard
Threemauto_News
news

Here inside the tag, what will be given you will be the name of the URL of your module. So here, it is, your URL becomes www.magentoproject.com/index.php/news. Step 5: Next we will add a helper configuration in our config.xml file. Because in the going forward steps, we will use some helper method in our module. So add this code in the config.xml file. Note that the code should be inside the tab.

Threemauto_News_Helper

Step 6: So we want create a helper class that we specified in the congig file. For that go to app/code/local/Threemauto/News/Helper and create a Data.php file there. That file should extend the Mage_Core_Helper_Abstract class of Magento. The file will be

class Threemauto_News_Helper_Data extends Mage_Core_Helper_Abstract {
}

Step 7: Create an action controller for our route. Go to app/code/local/Threemauto/News/controllers/IndexController.php. The code in this file will be

class Threemauto_News_indexController extends Mage_Core_Controller_Front_Action {

public function indexAction() {

echo $this->__('Our News module is ready');

}

}

Thats it. We created our module. Go to your browser and type www.yourproject.com/index.php/news. It will display ‘Our News module is ready’. Developing Model Next we are going to develop the model. The model is responsible for the database connectivity in Magento. In Magento, the model is divided into two. The first one is the Model file-which is responsible for the logical operations and the second one is the Resource file-which is responsible for the database queries. Update the config.xml file with the following code to get the model and resource in our module.

Threemauto_News_BlockThreemauto_News_Modeltest_mysql4Threemauto_News_Model_Mysql4

news

Threemauto_News

core_setup

core_write

core_read

There is one additional block is there (which is not related to the model and resource) in thetag. This is the path of our block folder, where all the PHP files for the view is located. Threemauto_News_Model is the location of our model class file and test_mysql4 is the location of our resource model. Also, we can see that news, here the news is the name of the table in the database. Next in thetag we are giving permission for the read and write operations for our module in the database. In the next step, we will create the model file. So create the News.php file in the location Threemauto/News/Model. The code for this file will be

class Threemauto_News_Model_News extends Mage_Core_Model_Abstract {

public function _construct() {

parent::_construct();

$this->_init('news/news');

}

}

We can see that $this->_init(‘news/news’) . This is actually the location of our resource file. So now we want to create the resource file. Let us create the Mysql4 folder in the Model folder and create the file News.php in it. The code for this file is

class Threemauto_News_Model_Mysql4_News extends Mage_Core_Model_Mysql4_Abstract {

public function _construct() {

$this->_init('news/news', 'news_id');

}

}

Here the news_id is the primary key in our table news. In the next step, we will create the SQL file for creating our database table. Our table name is ‘news’. So create the table news_setup in the SQL folder and create the file mysql4-install-0.1.0.php in it.

$installer = $this;
$installer->startSetup();
$installer->run("
-- DROP TABLE IF EXISTS {$this->getTable('news')};
CREATE TABLE {$this->getTable('news')} (
`news_id` int(11) unsigned NOT NULL auto_increment,
`title` varchar(255) NOT NULL default '',
`description` varchar(255) NOT NULL default '',
PRIMARY KEY (`news_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
");
$installer->endSetup();

Now we created our table. Refresh your project and check the table ‘core_resource’ in the database. There you can find ‘news_setup’ with version. So your table is created. Check table ‘news’ exists in the database. Developing Grid Here we are going to create the grid with tab in the admin side. For that create the folder Adminhtml in the Block folder of our module. Let us create the News.php file in it. The code for this file will be

class Threemauto_News_Block_Adminhtml_News extends Mage_Adminhtml_Block_Widget_Grid_Container {

public function __construct() {

$this->_controller = 'adminhtml_news';

$this->_blockGroup = 'news';

$this->_headerText = Mage::helper('news')->__('News Manager');

$this->_addButtonLabel = Mage::helper('news')->__('Add News');

parent::__construct();

}

}

Here we can see two variables. $this->_controller = ‘adminhtml_news’; $this->_blockGroup = ‘news’; This tells the path of our Grid file , so here the path will be news/adminhtml/news. So create our Grid.php file in the location Threemauto/News/Block/Adminhtml/News.

class Threemauto_News_Block_Adminhtml_News_Grid extends Mage_Adminhtml_Block_Widget_Grid {

public function __construct() {

parent::__construct();

$this->setId('news_grid');

$this->setDefaultSort('news_id');

$this->setDefaultDir('ASC');

$this->setSaveParametersInSession(true);

}




protected function _prepareCollection() {

$collection = Mage::getModel('news/news')->getCollection();

$this->setCollection($collection);

return parent::_prepareCollection();

}




protected function _prepareColumns() {

$this->addColumn('news_id', array(

'header' => Mage::helper('news')->__('ID'),

'align' => 'right',

'width' => '10px',

'index' => 'news_id',

));




$this->addColumn('title', array(

'header' => Mage::helper('news')->__('Title'),

'align' => 'left',

'index' => 'title',

'width' => '50px',

));







$this->addColumn('description', array(

'header' => Mage::helper('news')->__('Description'),

'width' => '150px',

'index' => 'description',

));




$this->addColumn('tag', array(

'header' => Mage::helper('news')->__('Tag'),

'width' => '150px',

'index' => 'tag',

));







$this->addColumn('date', array(

'header' => Mage::helper('news')->__('Posted On'),

'width' => '150px',

'index' => 'date',

));




return parent::_prepareColumns();

}







public function getRowUrl($row) {

return $this->getUrl('*/*/edit', array('id' => $row->getId()));

}

}

Note some few thisg here, $this->setId(‘news_grid’) : This is the grid id. $this->setDefaultSort(‘news_id’) : Indicates which column will be used for the default sorting. $this->setDefaultDir(‘ASC’) : Sorting order In the method _prepareColumns(), we are creating the columns . $this->addColumn(‘news_id’, array( ‘header’ => Mage::helper(‘news’)->__(‘ID’), ‘align’ => ‘right’, ‘width’ => ’10px’, ‘index’ => ‘news_id’, )); now we created the first column, that will display the ID in the grid. $this->addColumn(‘title’, array( ‘header’ => Mage::helper(‘news’)->__(‘Title’), ‘align’ => ‘left’, ‘index’ => ‘title’, ‘width’ => ’50px’, )); this will add the column Title, which will display the title and so on. Next we want to add this menu in admin page. So update the config.xml file with the following codes. Note that this should be in the tag of thetag
1212 news/adminhtml_news

10

xml

In the tag we should provide the dropdown menu details, in our case, it is ‘Mange News’. Note that in thetag we added news.xml. This is the layout file in our adminhtml layouts. So create the file news.xml in the location app/design/adminhtml/default/default/layout.

1%MINIFYHTMLcdf171a6eef920ea942b208e14741e167%%MINIFYHTMLcdf171a6eef920ea942b208e14741e168%%MINIFYHTMLcdf171a6eef920ea942b208e14741e169%%MINIFYHTMLcdf171a6eef920ea942b208e14741e1610%%MINIFYHTMLcdf171a6eef920ea942b208e14741e1611%%MINIFYHTMLcdf171a6eef920ea942b208e14741e1612%%MINIFYHTMLcdf171a6eef920ea942b208e14741e1613%js_css

prototype/windows/themes/default.css




js_css

prototype/windows/themes/magento.css




lib/prototype/windows/themes/magento.css

In the next step we will create the controller file. So create ‘Adminhtml’ folder in the controllers folder of our module. And create the file NewsController.php in it.

class Threemauto_News_Adminhtml_NewsController extends Mage_Adminhtml_Controller_action {




public function indexAction() {

$this->loadLayout();

$this->renderLayout();

}




public function newAction(){

$this->loadLayout();

$this->_addContent($this->getLayout()->createBlock('news/adminhtml_news_edit'))

->_addLeft($this->getLayout()->createBlock('news/adminhtml_news_edit_tabs'));

$this->renderLayout();

}




public function deleteAction() {

if ($this->getRequest()->getParam('id') > 0) {

try {

$model = Mage::getModel('news/news');




$model->setId($this->getRequest()->getParam('id'))

->delete();




Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Item was successfully deleted'));

$this->_redirect('*/*/');

} catch (Exception $e) {

Mage::getSingleton('adminhtml/session')->addError($e->getMessage());

$this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id')));

}

}

$this->_redirect('*/*/');

}




public function saveAction() {




if ($data = $this->getRequest()->getPost())

{

$model = Mage::getModel('news/news');

$id = $this->getRequest()->getParam('id');

foreach ($data as $key => $value)

{

if (is_array($value))

{

$data[$key] = implode(',',$this->getRequest()->getParam($key));

}

}




if ($id) {

$model->load($id);

}

$model->setData($data);




Mage::getSingleton('adminhtml/session')->setFormData($data);

try {

if ($id) {

$model->setId($id);

}




$model->save();




if (!$model->getId()) {

Mage::throwException(Mage::helper('news')->__('Error saving news details'));

}




Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('news')->__('Details was successfully saved.'));




Mage::getSingleton('adminhtml/session')->setFormData(false);




// The following line decides if it is a "save" or "save and continue"

if ($this->getRequest()->getParam('back')) {

$this->_redirect('*/*/edit', array('id' => $model->getId()));

} else {

$this->_redirect('*/*/');

}




} catch (Exception $e) {

Mage::getSingleton('adminhtml/session')->addError($e->getMessage());

if ($model && $model->getId()) {

$this->_redirect('*/*/edit', array('id' => $model->getId()));

} else {

$this->_redirect('*/*/');

}

}




return;

}

Mage::getSingleton('adminhtml/session')->addError(Mage::helper('news')->__('No data found to save'));

$this->_redirect('*/*/');

}







public function editAction() {




$id = $this->getRequest()->getParam('id', null);




$model = Mage::getModel('news/news');

if ($id) {

$model->load((int) $id);

if ($model->getId()) {

$data = Mage::getSingleton('adminhtml/session')->getFormData(true);

if ($data) {

$model->setData($data)->setId($id);

}

} else {

Mage::getSingleton('adminhtml/session')->addError(Mage::helper('news')->__('news does not exist'));

$this->_redirect('*/*/');

}

}

Mage::register('news_data', $model);




$this->_title($this->__('News'))->_title($this->__('Edit news'));

$this->loadLayout();

$this->getLayout()->getBlock('head')->setCanLoadExtJs(true);




$this->_addContent($this->getLayout()->createBlock('news/adminhtml_news_edit'))

->_addLeft($this->getLayout()->createBlock('news/adminhtml_news_edit_tabs'));

$this->renderLayout();

}

}

Note the function newAction() : This function is responsible for displaying the form in our controller. Here we addeded two blocks. One is for the ‘Tabs’ in the left side and other is the ‘content’ in the right side. Pease note the attached screen shot. There are so many methods are there. They are responsible for save the news, delete the news and edit the news. In the next step we will develop the form container. For that we will create the file Edit.php in the location Threemauto/News/Block/Adminhtml/News.

class Threemauto_News_Block_Adminhtml_News_Edit extends Mage_Adminhtml_Block_Widget_Form_Container {




public function __construct() {

parent::__construct();




$this->_objectId = 'id';

$this->_blockGroup = 'news';

$this->_controller = 'adminhtml_news';

$this->_mode = 'edit';

$this->_updateButton('save', 'label', Mage::helper('news')->__('Save News'));

$this->_updateButton('delete', 'label', Mage::helper('news')->__('Delete'));

$this->_addButton('saveandcontinue', array(

'label' => Mage::helper('news')->__('Save And Continue Edit'),

'onclick' => 'saveAndContinueEdit()',

'class' => 'save',

), -100);




$this->_formScripts[] = "

function toggleEditor() {

if (getInstanceById('form_content') == null) {

execCommand('mceAddControl', false, 'edit_form');

} else {

execCommand('mceRemoveControl', false, 'edit_form');

}

}




function saveAndContinueEdit(){

submit($('edit_form').action+'back/edit/');

}

";

}

/*

* This function is responsible for Including TincyMCE in Head.

*/

protected function _prepareLayout() {

parent::_prepareLayout();

if (Mage::getSingleton('cms/wysiwyg_config')->isEnabled()) {

$this->getLayout()->getBlock('head')->setCanLoadTinyMce(true);

$this->getLayout()->getBlock('head')->setCanLoadExtJs(true);

}

}







public function getHeaderText() {

if (Mage::registry('news_data') && Mage::registry('news_data')->getId()) {

return Mage::helper('news')->__('Edit News "%s"', $this->htmlEscape(Mage::registry('news_data')->getTitle()));

} else {

return Mage::helper('news')->__('New News');

}

}

}

Next we will create the form tag. So create the file Form.php in the location Threemauto_News_Block_Adminhtml_News_Edit

class Threemauto_News_Block_Adminhtml_News_Edit_Form extends Mage_Adminhtml_Block_Widget_Form {




protected function _prepareForm() {




if (Mage::registry('news_data')) {

$data = Mage::registry('news_data')->getData();

} else {

$data = array();

}




$form = new Varien_Data_Form(array(

'id' => 'edit_form',

'action' => $this->getUrl('*/*/save', array('id' => $this->getRequest()->getParam('id'))),

'method' => 'post',

'enctype' => 'multipart/form-data'

)

);




$form->setUseContainer(true);

$this->setForm($form);

$form->setValues($data);

return parent::_prepareForm();

}

}

Next we want to develop the form tabs. There are two tabs in our form.

class Threemauto_News_Block_Adminhtml_News_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs {




public function __construct() {

parent::__construct();

$this->setId('news_tabs');

$this->setDestElementId('edit_form'); // this should be same as the form id define above

$this->setTitle(Mage::helper('news')->__('News Information'));

}




protected function _beforeToHtml() {

$this->addTab('form_section', array(

'label' => Mage::helper('news')->__('News Information'),

'title' => Mage::helper('news')->__('News Information'),

'content' => $this->getLayout()->createBlock('news/adminhtml_news_edit_tab_form')->toHtml(),

));




$this->addTab('form_section1', array(

'label' => Mage::helper('news')->__('Content'),

'title' => Mage::helper('news')->__('Content'),

'content' => $this->getLayout()->createBlock('news/adminhtml_news_edit_tab_content')->toHtml(),

));




return parent::_beforeToHtml();

}

}

Note that there are two tabs that are there. One is ‘News Information’ and the other is ‘Content’.
So in the _beforeToHtml() function we specified the actual form field’s location. ie for the first tab, we want to create the file Form.php in the location Threemauto/News/Block/Adminhtml/News/Edit/Tab and for the second tab we want to create Content.php in the location Threemauto/News/Block/Adminhtml/News/Edit/Tab.
The code in the two files follows

class Threemauto_News_Block_Adminhtml_News_Edit_Tab_Form extends Mage_Adminhtml_Block_Widget_Form {




protected function _prepareForm() {




if (Mage::registry('news_data')) {

$data = Mage::registry('news_data')->getData();

} else {

$data = array();

}




$form = new Varien_Data_Form();

$this->setForm($form);

$fieldset = $form->addFieldset('news_news', array('legend' => Mage::helper('news')->__('news information')));




$fieldset->addField('title', 'text', array(

'label' => Mage::helper('news')->__('News Title'),

'class' => 'required-entry',

'required' => true,

'name' => 'title',

));




$fieldset->addField('tag', 'text', array(

'label' => Mage::helper('news')->__('Tag'),

'class' => 'required-entry',

'required' => true,

'name' => 'tag',

));




$form->setValues($data);




return parent::_prepareForm();

}

}

class Threemauto_News_Block_Adminhtml_News_Edit_Tab_Content extends Mage_Adminhtml_Block_Widget_Form {




protected function _prepareForm() {




if (Mage::registry('news_data')) {

$data = Mage::registry('news_data')->getData();

} else {

$data = array();

}




$form = new Varien_Data_Form();

$this->setForm($form);

$fieldset = $form->addFieldset('news_news', array('legend' => Mage::helper('news')->__('More information')));




/*

* Editing the form field in wysiwyg editor.

*/




$wysiwygConfig = Mage::getSingleton('cms/wysiwyg_config')->getConfig();

$wysiwygConfig->addData(array('add_variables' => false,

'add_widgets' => true,

'add_images' => true,

'directives_url' => Mage::getSingleton('adminhtml/url')->getUrl('adminhtml/cms_wysiwyg/directive'),

'directives_url_quoted' => preg_quote(Mage::getSingleton('adminhtml/url')->getUrl('adminhtml/cms_wysiwyg/directive')),

'widget_window_url' => Mage::getSingleton('adminhtml/url')->getUrl('adminhtml/widget/index'),

'files_browser_window_url' => Mage::getSingleton('adminhtml/url')->getUrl('adminhtml/cms_wysiwyg_images/index'),

'files_browser_window_width' => (int) Mage::getConfig()->getNode('adminhtml/cms/browser/window_width'),

'files_browser_window_height' => (int) Mage::getConfig()->getNode('adminhtml/cms/browser/window_height')

));







$fieldset->addField('description', 'editor', array(

'name' => 'description',

'label' => Mage::helper('news')->__('Description'),

'title' => Mage::helper('news')->__('Description'),

'style' => 'width:800px; height:500px;',

'config' => $wysiwygConfig,

'required' => false,

'wysiwyg' => true

));




$form->setValues($data);

}

}

Thats it…. Finally, we developed our module with Grid in admin page. Here I have added the WYSIWYG editor too. There are only 3 steps for implementing this editor in our module. These steps are already covered in this tutorial, but here is brief information about implementing wysiwyg editor
Step 1: Including WYSIWYG editor in head. Please note in the file app/code/local/Threemauto/News/Block/Adminhtml/News/Edit.php I have added the following code

protected function _prepareLayout() {

parent::_prepareLayout();

if (Mage::getSingleton('cms/wysiwyg_config')->isEnabled()) {

$this->getLayout()->getBlock('head')->setCanLoadTinyMce(true);

$this->getLayout()->getBlock('head')->setCanLoadExtJs(true);

}

}

this is enough.
Step 2 : Add the content filed in the Adminhtml form class Please go to app/code/local/Threemauto/News/Block/Adminhtml/News/Edit/Tab/Content.php there i have added

$wysiwygConfig = Mage::getSingleton('cms/wysiwyg_config')->getConfig();

$wysiwygConfig->addData(array('add_variables' => false,

'add_widgets' => true,

'add_images' => true,

'directives_url' => Mage::getSingleton('adminhtml/url')->getUrl('adminhtml/cms_wysiwyg/directive'),

'directives_url_quoted' => preg_quote(Mage::getSingleton('adminhtml/url')->getUrl('adminhtml/cms_wysiwyg/directive')),

'widget_window_url' => Mage::getSingleton('adminhtml/url')->getUrl('adminhtml/widget/index'),

'files_browser_window_url' => Mage::getSingleton('adminhtml/url')->getUrl('adminhtml/cms_wysiwyg_images/index'),

'files_browser_window_width' => (int) Mage::getConfig()->getNode('adminhtml/cms/browser/window_width'),

'files_browser_window_height' => (int) Mage::getConfig()->getNode('adminhtml/cms/browser/window_height')

));







$fieldset->addField('description', 'editor', array(

'name' => 'description',

'label' => Mage::helper('news')->__('Description'),

'title' => Mage::helper('news')->__('Description'),

'style' => 'width:800px; height:500px;',

'config' => $wysiwygConfig,

'required' => false,

'wysiwyg' => true

));