In this post we are discussing about creating magento extension with custom database table. Follow step by step and if you encounter any error don’t hesitate to contact me

Document Conventions

I am going to use a few common conventions here that should make it easier to figure out what you need to replace as I am making this as generic as possible.

Anything in angled brackets (including the angled brackets): < >, needs to replaced with the appropriate text..

Anything in square brackets (including the square brackets): [ ], needs to replaced with the appropriate text.

The reason I am using two different conventions here are that XML files already use angled brackets so you will only see the square brackets in use in XML files.

I have changed the document conventions to use the naming conventions as Naviz_Dummy, Becuase of i have got somany comments regarding the output of this code

NOTE: All directory, file, class names are Case Sensitive unless otherwise noted.

Create Directories

Magento Modules follow a common naming scheme, Namespace_Module. This is very important to remember as you need to be careful about how you name your classes. Every custom module will be created in the directory:

/app/code/local

The first step in creating your custom module is determining the namespace and module name. The namespace is simply an extra division that you can create you module in. This means that you can have two modules named the same thing if they are in two different namespaces. One way to use namespaces is to use your company name or initials for all of your modules. If my company name is Naviz and I am creating a module called Dummy the full module name would be Acme_News. Magento uses the namespace Mage. There is nothing stopping you from using that namespace under local, i.e. you could create Mage_Dummy and that would work just fine.

Note : You can not use underscore within your module name

Note2: It seems that currently, if you use upper case characters in module names (expecting to show word starts since neither – nor _ is allowed)… the install will fail or rather the module will not work. Suggestion: use a single upper case character, at the beginning of the name.

Let’s setup our directory structure:

/app/code/local/Naviz/Dummy/
Block/
controllers/
etc/
Model/
    Mysql4/
        Dummy/
sql/
    dummy_setup/
/app/design/frontend/base/default/

template/
    dummy/

Activate Module

Magento requires there to be an XML file that tells Magento to look for and use your custom module.

/app/etc/modules/Naviz_Dummy.xml
<?xml version="1.0"?>
<config>
  <modules>
    <Naviz_Dummy>
      <active>true</active>
      <codePool>local</codePool>
      <version>0.1.0</version>
    </Naviz_Dummy>
  </modules>
</config>

Also you can disable your module in the Configuration menu on the backend via the Advanced tab.

NOTE: Due to a bug in Magento, whitespace is not treated correctly. This means that if you leave space in the values between node names (anything in angled brackets <> is a node), Magento will break.

As an explanation of the above code you will see that all you are changing is the Naviz_Dummy text and leaving everything else the same. Please note the capital P in codePool. If this is lowercase this module will not be active.

Create Controller

/app/code/local/Naviz/Dummy/controllers/IndexController.php
<?php
class Naviz_Dummy_IndexController extends Mage_Core_Controller_Front_Action{
    public function IndexAction() {
      
	  $this->loadLayout();   
	  $this->getLayout()->getBlock("head")->setTitle($this->__("Dummy"));
	        $breadcrumbs = $this->getLayout()->getBlock("breadcrumbs");
      $breadcrumbs->addCrumb("home", array(
                "label" => $this->__("Home Page"),
                "title" => $this->__("Home Page"),
                "link"  => Mage::getBaseUrl()
		   ));

      $breadcrumbs->addCrumb("dummy", array(
                "label" => $this->__("Dummy"),
                "title" => $this->__("Dummy")
		   ));

      $this->renderLayout(); 
	  
    }
}

NOTE: You may notice that there is no closing, ?>, PHP tag in the code. This is a common coding style that Magento core classes use. Magento Coding Standard is similar (with some exceptions) to Zend Framework PHP Coding Standard and you can find the detailed explanations of this rule in Zend Framework Documentation

Create Configuration XML

/app/code/local/Naviz/Dummy/etc/config.xml
<?xml version="1.0"?>
<config>
  <modules>
    <Naviz_Dummy>
      <version>0.1.0</version>
    </Naviz_Dummy>
  </modules>
  <frontend>
    <routers>
      <dummy>
        <use>standard</use>
          <args>
            <module>Naviz_Dummy</module>
            <frontName>dummy</frontName>
          </args>
      </dummy>
    </routers>
		<layout>
		  <updates>
			<dummy>
			  <file>dummy.xml</file>
			</dummy>
		  </updates>
		</layout>
  </frontend>
  <global>
    <helpers>
      <dummy>
        <class>Naviz_Dummy_Helper</class>
      </dummy>
    </helpers>
	<blocks>
	  <dummy>
		<class>Naviz_Dummy_Block</class>
	  </dummy>
	</blocks>
	<models>
	  <dummy>
		<class>Naviz_Dummy_Model</class>
		<resourceModel>dummy_mysql4</resourceModel>
	  </dummy>
	  <dummy_mysql4>
		<class>Naviz_Dummy_Model_Mysql4</class>
		<entities>		  
			  <dummy>
				<table>dummy</table>
			  </dummy>
        </entities>
	  </dummy_mysql4>
	</models>
	<resources>
	  <dummy_setup>
		<setup>
		  <module>Naviz_Dummy</module>
		</setup>
		<connection>
		  <use>core_setup</use>
		</connection>
	  </dummy_setup>
	  <dummy_write>
		<connection>
		  <use>core_write</use>
		</connection>
	  </dummy_write>
	  <dummy_read>
		<connection>
		  <use>core_read</use>
		</connection>
	  </dummy_read>
	</resources>
  </global>
  <admin>
	<routers>
	  <dummy>
	    <use>admin</use>
		<args>
		  <module>Naviz_Dummy</module>
		  <frontName>admin_dummy</frontName>
		</args>
	  </dummy>
	</routers>
  </admin>
  <adminhtml>
	<menu>
	  <dummy module="dummy">
		<title>Dummy</title>
		<sort_order>100</sort_order>
		<children>
		  <dummy module="dummy">
		    <title>Manage Dummy</title>
			<sort_order>0</sort_order>
			<action>admin_dummy/adminhtml_dummy</action>
		  </dummy>
		</children>
	  </dummy>
	</menu>
	<acl>
	  <resources>
		<all>
		  <title>Allow Everything</title>
		</all>
		<admin>
		  <children>
			<dummy translate="title" module="dummy">
			  <title>Dummy</title>
			  <sort_order>1000</sort_order>
			  <children>
		  <dummy translate="title">
			<title>Manage Dummy</title>
			<sort_order>0</sort_order>
		  </dummy>
			  </children>
			</dummy>
		  </children>
		</admin>
	  </resources>
	</acl>
	<layout>
	  <updates>
		<dummy>
		  <file>dummy.xml</file>
		</dummy>
	  </updates>
	</layout>
  </adminhtml>
</config> 

NB : You can use the frontName of your choice without any link to your module name. IE : Mage_Catalog could have “mycatalog” as a frontName.

Create Helper

/app/code/local/Naviz/Dummy/Helper/Data.php
<?php
class Naviz_Dummy_Helper_Data extends Mage_Core_Helper_Abstract
{
}

Create Models

If you are quite new to Magento you should pay attention to one of its specifics! The Constructors below are not the usual PHP-Constructors!! Keeping that in mind can save hours of frustrating crashes 😉

/app/code/local/Naviz/Dummy/Model/Dummy.php
<?php

class Naviz_Dummy_Model_Dummy extends Mage_Core_Model_Abstract
{
    protected function _construct(){

       $this->_init("dummy/dummy");

    }

}
	 
/app/code/local/Naviz/Dummy/Model/Mysql4/Dummy.php
<?php
class Naviz_Dummy_Model_Mysql4_Dummy extends Mage_Core_Model_Mysql4_Abstract
{
    protected function _construct()
    {
        $this->_init("dummy/dummy", "dummy_id");
    }
}

NOTE: The ‘_id’ refers to the PRIMARY KEY in your database table.

/app/code/local/Naviz/Dummy/Model/Mysql4/Dummy/Collection.php
<?php
 class Naviz_Dummy_Model_Mysql4_Dummy_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
    {

		public function _construct(){
			$this->_init("dummy/dummy");
		}

		

    }

SQL Setup

/app/code/local/Naviz/Dummy/sql/dummy_setup/mysql4-install-0.1.0.php
<?php
 
$installer = $this;
$installer->startSetup();
$sql=<<<SQLTEXT
create table dummy (dummy_id int not null auto_increment, title varchar(100), content text(200), status varchar(100),primary key(dummy_id));
   
SQLTEXT;

$installer->run($sql);
 
$installer->endSetup();

NOTE: Please note the text that needs to be replaced. This SQL structure is up to you, this is merely a starting point.

Note Important: If you add fields and couldn’t save data in these fields please try to go to System→Cache Management Then 1.Flush Cache Storage 2.Flush Magento Cache.

Template Design

/app/design/frontend/base/default/layout/dummy.xml
<?xml version="1.0"?>   
<layout version="0.1.0">   
  <dummy_index_index>   
    <reference name="root">   
      <action method="setTemplate"><template>page/1column.phtml</template></action>   
    </reference>   
    <reference name="content">   
      <block type="dummy/index" name="dummy_index" template="dummy/index.phtml"/>   
    </reference>   
  </dummy_index_index>   
</layout>  

NOTE: The block type will automatically figure out what template file to use based on the second dummy declaration.

/app/design/frontend/base/default/template/dummy/index.phtml
<h4><?php echo $this->__('Module List') ?></h4>
 
<?php   
        /*
        This will load one record from your database table.
        load(dummy_id) will load whatever ID number you give it.
        */
    /*
    $news = Mage::getModel('dummy/dummy')->load(1);
    echo $news->getDummyId();
    echo $news->getTitle();
    echo $news->getContent();
    echo $news->getStatus();
    */
 
        /*
        This block of code loads all of the records in the database table.
        It will iterate through the collection and the first thing it will do
        is set the Title to the current value of $i which is incremented each
        iteration and then echo that value back out.  At the very end it will
        save the entire collection.
        */
    /*
    $i = 0;
         
    $collection = Mage::getModel('dummy/dummy')->getCollection();
    $collection->setPageSize(5);
    $collection->setCurPage(2);
    $size = $collection->getSize();
    $cnt = count($collection);
    foreach ($collection as $item) {
        $i = $i+1;
        $item->setTitle($i);
        echo $item->getTitle();
    }
 
    $collection->walk('save');   
    */
 
        /*
        This shows how to load one value, change something and save it.
        */
 
    /*
    $object = Mage::getModel('dummy/dummy')->load(1);
    $object->setTitle('This is a changed title');
    $object->save();
    */
?>

NOTE: Uncomment anything that you would like to use and this is just a starting point and some common methods for you to try and pull the data out.

In this section I am utilizing the built-in Grid Widgets and form capabilities to create a form to allow editing and creating new items for your custom database.

Directory Additions

Here is the revised directory setup due to the additions and changes we need for the backend module.

/app/code/local/Naviz/Dummy/
Block/
    Adminhtml/
        Dummy/
            Edit/
                Tab/
controllers/
    Adminhtml/
etc/
Helper/
Model/
    Mysql4/
        Dummy/
sql/
    dummy_setup/
Blocks

These control the setup and appearance of your grids and the options that they display.

NOTE: Please note the fact that Block comes before Adminhtml in the class declaration. In any of the Magento modules in Adminhtml it is the opposite. For your module to work it has to be Block_Adminhtml otherwise you will get a ‘Cannot redeclare module…’ error.

/app/code/local/Naviz/Dummy/Block/Adminhtml/Dummy.php
<?php
 class Naviz_Dummy_Block_Adminhtml_Dummy extends Mage_Adminhtml_Block_Widget_Grid_Container{

	public function __construct()
	{

	$this->_controller = "adminhtml_dummy";
	$this->_blockGroup = "dummy";
	$this->_headerText = Mage::helper("dummy")->__("Dummy Manager");
	$this->_addButtonLabel = Mage::helper("dummy")->__("Add New Item");
	parent::__construct();
	
	}

}
/app/code/local/Naviz/Dummy/Block/Adminhtml/Dummy/Edit.php
<?php
	
class Naviz_Dummy_Block_Adminhtml_Dummy_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
{
		public function __construct()
		{

				parent::__construct();
				$this->_objectId = "dummy_id";
				$this->_blockGroup = "dummy";
				$this->_controller = "adminhtml_dummy";
				$this->_updateButton("save", "label", Mage::helper("dummy")->__("Save Item"));
				$this->_updateButton("delete", "label", Mage::helper("dummy")->__("Delete Item"));

				$this->_addButton("saveandcontinue", array(
					"label"     => Mage::helper("dummy")->__("Save And Continue Edit"),
					"onclick"   => "saveAndContinueEdit()",
					"class"     => "save",
				), -100);



				$this->_formScripts[] = "

							function saveAndContinueEdit(){
								editForm.submit($('edit_form').action+'back/edit/');
							}
						";
		}

		public function getHeaderText()
		{
				if( Mage::registry("dummy_data") && Mage::registry("dummy_data")->getId() ){

				    return Mage::helper("dummy")->__("Edit Item '%s'", $this->htmlEscape(Mage::registry("dummy_data")->getId()));

				} 
				else{

				     return Mage::helper("dummy")->__("Add Item");

				}
		}
}
/app/code/local/Naviz/Dummy/Block/Adminhtml/Dummy/Grid.php
<?php

class Naviz_Dummy_Block_Adminhtml_Dummy_Grid extends Mage_Adminhtml_Block_Widget_Grid
{

		public function __construct()
		{
				parent::__construct();
				$this->setId("dummyGrid");
				$this->setDefaultSort("dummy_id");
				$this->setDefaultDir("DESC");
				$this->setSaveParametersInSession(true);
		}

		protected function _prepareCollection()
		{
				$collection = Mage::getModel("dummy/dummy")->getCollection();
				$this->setCollection($collection);
				return parent::_prepareCollection();
		}
		protected function _prepareColumns()
		{
				$this->addColumn("dummy_id", array(
				"header" => Mage::helper("dummy")->__("ID"),
				"align" =>"right",
				"width" => "50px",
			    "type" => "number",
				"index" => "dummy_id",
				));
                
				$this->addColumn("title", array(
				"header" => Mage::helper("dummy")->__("Title"),
				"index" => "title",
				));
						$this->addColumn('status', array(
						'header' => Mage::helper('dummy')->__('Status'),
						'index' => 'status',
						'type' => 'options',
						'options'=>Naviz_Dummy_Block_Adminhtml_Dummy_Grid::getOptionArray2(),				
						));
						
			$this->addExportType('*/*/exportCsv', Mage::helper('sales')->__('CSV')); 
			$this->addExportType('*/*/exportExcel', Mage::helper('sales')->__('Excel'));

				return parent::_prepareColumns();
		}

		public function getRowUrl($row)
		{
			   return $this->getUrl("*/*/edit", array("id" => $row->getId()));
		}


		
		protected function _prepareMassaction()
		{
			$this->setMassactionIdField('dummy_id');
			$this->getMassactionBlock()->setFormFieldName('dummy_ids');
			$this->getMassactionBlock()->setUseSelectAll(true);
			$this->getMassactionBlock()->addItem('remove_dummy', array(
					 'label'=> Mage::helper('dummy')->__('Remove Dummy'),
					 'url'  => $this->getUrl('*/adminhtml_dummy/massRemove'),
					 'confirm' => Mage::helper('dummy')->__('Are you sure?')
				));
			return $this;
		}
			
		static public function getOptionArray2()
		{
            $data_array=array(); 
			$data_array[0]='Yes';
			$data_array[1]='No';
            return($data_array);
		}
		static public function getValueArray2()
		{
            $data_array=array();
			foreach(Naviz_Dummy_Block_Adminhtml_Dummy_Grid::getOptionArray2() as $k=>$v){
               $data_array[]=array('value'=>$k,'label'=>$v);		
			}
            return($data_array);

		}
		

}
/app/code/local/Naviz/Dummy/Block/Adminhtml/Dummy/Edit/Form.php
<?php
class Naviz_Dummy_Block_Adminhtml_Dummy_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
{
		protected function _prepareForm()
		{
				$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);
				return parent::_prepareForm();
		}
}

/app/code/local/Naviz/Dummy/Block/Adminhtml/Dummy/Edit/Tabs.php
<?php
class Naviz_Dummy_Block_Adminhtml_Dummy_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs
{
		public function __construct()
		{
				parent::__construct();
				$this->setId("dummy_tabs");
				$this->setDestElementId("edit_form");
				$this->setTitle(Mage::helper("dummy")->__("Item Information"));
		}
		protected function _beforeToHtml()
		{
				$this->addTab("form_section", array(
				"label" => Mage::helper("dummy")->__("Item Information"),
				"title" => Mage::helper("dummy")->__("Item Information"),
				"content" => $this->getLayout()->
                createBlock("dummy/adminhtml_dummy_edit_tab_form")->toHtml(),
				));
				return parent::_beforeToHtml();
		}

}

/app/code/local/Naviz/Dummy/Block/Adminhtml/Dummy/Edit/Tab/Form.php
<?php
class Naviz_Dummy_Block_Adminhtml_Dummy_Edit_Tab_Form extends Mage_Adminhtml_Block_Widget_Form
{
		protected function _prepareForm()
		{

				$form = new Varien_Data_Form();
				$this->setForm($form);
				$fieldset = $form->addFieldset("dummy_form", 
                array("legend"=>Mage::helper("dummy")->__("Item information")));

				
						$fieldset->addField("title", "text", array(
						"label" => Mage::helper("dummy")->__("Title"),
						"name" => "title",
						));
					
						$fieldset->addField("content", "textarea", array(
						"label" => Mage::helper("dummy")->__("Content"),
						"name" => "content",
						));
									
						 $fieldset->addField('status', 'select', array(
						'label'     => Mage::helper('dummy')->__('Status'),
						'values'   => Naviz_Dummy_Block_Adminhtml_Dummy_Grid::getValueArray2(),
						'name' => 'status',
						));

				if (Mage::getSingleton("adminhtml/session")->getDummyData())
				{
					$form->setValues(Mage::getSingleton("adminhtml/session")->getDummyData());
					Mage::getSingleton("adminhtml/session")->setDummyData(null);
				} 
				elseif(Mage::registry("dummy_data")) {
				    $form->setValues(Mage::registry("dummy_data")->getData());
				}
				return parent::_prepareForm();
		}
}

Controller

/app/code/local/Naviz/Dummy/controllers/Adminhtml/DummyController.php
<?php

class Naviz_Dummy_Adminhtml_DummyController extends Mage_Adminhtml_Controller_Action
{
		protected function _initAction()
		{
				$this->loadLayout()->
                _setActiveMenu("dummy/dummy")->_addBreadcrumb(Mage::helper("adminhtml")->
                __("Dummy  Manager"),Mage::helper("adminhtml")->__("Dummy Manager"));
				return $this;
		}
		public function indexAction() 
		{
			    $this->_title($this->__("Dummy"));
			    $this->_title($this->__("Manager Dummy"));

				$this->_initAction();
				$this->renderLayout();
		}
		public function editAction()
		{			    
			    $this->_title($this->__("Dummy"));
				$this->_title($this->__("Dummy"));
			    $this->_title($this->__("Edit Item"));
				
				$id = $this->getRequest()->getParam("id");
				$model = Mage::getModel("dummy/dummy")->load($id);
				if ($model->getId()) {
					Mage::register("dummy_data", $model);
					$this->loadLayout();
					$this->_setActiveMenu("dummy/dummy");
					$this->_addBreadcrumb(Mage::helper("adminhtml")->__("Dummy Manager"), Mage::helper("adminhtml")->__("Dummy Manager"));
					$this->_addBreadcrumb(Mage::helper("adminhtml")->__("Dummy Description"), Mage::helper("adminhtml")->__("Dummy Description"));
					$this->getLayout()->getBlock("head")->setCanLoadExtJs(true);
					$this->_addContent($this->getLayout()->
                    createBlock("dummy/adminhtml_dummy_edit"))->_addLeft($this->getLayout()->createBlock("dummy/adminhtml_dummy_edit_tabs"));
					$this->renderLayout();
				} 
				else {
					Mage::getSingleton("adminhtml/session")->
                    addError(Mage::helper("dummy")->__("Item does not exist."));
					$this->_redirect("*/*/");
				}
		}

		public function newAction()
		{

		$this->_title($this->__("Dummy"));
		$this->_title($this->__("Dummy"));
		$this->_title($this->__("New Item"));

        $id   = $this->getRequest()->getParam("id");
		$model  = Mage::getModel("dummy/dummy")->load($id);

		$data = Mage::getSingleton("adminhtml/session")->getFormData(true);
		if (!empty($data)) {
			$model->setData($data);
		}

		Mage::register("dummy_data", $model);

		$this->loadLayout();
		$this->_setActiveMenu("dummy/dummy");

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

		$this->_addBreadcrumb(Mage::helper("adminhtml")->
        __("Dummy Manager"), Mage::helper("adminhtml")->__("Dummy Manager"));
		$this->_addBreadcrumb(Mage::helper("adminhtml")->
        __("Dummy Description"), Mage::helper("adminhtml")->__("Dummy Description"));


		$this->_addContent($this->getLayout()->
        createBlock("dummy/adminhtml_dummy_edit"))->_addLeft($this->getLayout()->createBlock("dummy/adminhtml_dummy_edit_tabs"));

		$this->renderLayout();

		}
		public function saveAction()
		{

			$post_data=$this->getRequest()->getPost();


				if ($post_data) {

					try {

						

						$model = Mage::getModel("dummy/dummy")
						->addData($post_data)
						->setId($this->getRequest()->getParam("id"))
						->save();

						Mage::getSingleton("adminhtml/session")->
                        addSuccess(Mage::helper("adminhtml")->__("Dummy was successfully saved"));
						Mage::getSingleton("adminhtml/session")->setDummyData(false);

						if ($this->getRequest()->getParam("back")) {
							$this->_redirect("*/*/edit", array("id" => $model->getId()));
							return;
						}
						$this->_redirect("*/*/");
						return;
					} 
					catch (Exception $e) {
						Mage::getSingleton("adminhtml/session")->addError($e->getMessage());
						Mage::getSingleton("adminhtml/session")->setDummyData($this->getRequest()->getPost());
						$this->_redirect("*/*/edit", array("id" => $this->getRequest()->getParam("id")));
					return;
					}

				}
				$this->_redirect("*/*/");
		}



		public function deleteAction()
		{
				if( $this->getRequest()->getParam("id") > 0 ) {
					try {
						$model = Mage::getModel("dummy/dummy");
						$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 massRemoveAction()
		{
			try {
				$ids = $this->getRequest()->getPost('dummy_ids', array());
				foreach ($ids as $id) {
                      $model = Mage::getModel("dummy/dummy");
					  $model->setId($id)->delete();
				}
				Mage::getSingleton("adminhtml/session")->
                addSuccess(Mage::helper("adminhtml")->__("Item(s) was successfully removed"));
			}
			catch (Exception $e) {
				Mage::getSingleton("adminhtml/session")->addError($e->getMessage());
			}
			$this->_redirect('*/*/');
		}
			
		/**
		 * Export order grid to CSV format
		 */
		public function exportCsvAction()
		{
			$fileName   = 'dummy.csv';
			$grid       = $this->getLayout()->createBlock('dummy/adminhtml_dummy_grid');
			$this->_prepareDownloadResponse($fileName, $grid->getCsvFile());
		} 
		/**
		 *  Export order grid to Excel XML format
		 */
		public function exportExcelAction()
		{
			$fileName   = 'dummy.xml';
			$grid       = $this->getLayout()->createBlock('dummy/adminhtml_dummy_grid');
			$this->_prepareDownloadResponse($fileName, $grid->getExcelFile($fileName));
		}
}

XML Configuration Changes

/app/code/local/Naviz/Dummy/etc/config.xml
<?xml version="1.0"?>
<config>
  <modules>
    <Naviz_Dummy>
      <version>0.1.0</version>
    </Naviz_Dummy>
  </modules>
  <frontend>
    <routers>
      <dummy>
        <use>standard</use>
          <args>
            <module>Naviz_Dummy</module>
            <frontName>dummy</frontName>
          </args>
      </dummy>
    </routers>
		<layout>
		  <updates>
			<dummy>
			  <file>dummy.xml</file>
			</dummy>
		  </updates>
		</layout>
  </frontend>
  <global>
    <helpers>
      <dummy>
        <class>Naviz_Dummy_Helper</class>
      </dummy>
    </helpers>
	<blocks>
	  <dummy>
		<class>Naviz_Dummy_Block</class>
	  </dummy>
	</blocks>
	<models>
	  <dummy>
		<class>Naviz_Dummy_Model</class>
		<resourceModel>dummy_mysql4</resourceModel>
	  </dummy>
	  <dummy_mysql4>
		<class>Naviz_Dummy_Model_Mysql4</class>
		<entities>		  
			  <dummy>
				<table>dummy</table>
			  </dummy>
        </entities>
	  </dummy_mysql4>
	</models>
	<resources>
	  <dummy_setup>
		<setup>
		  <module>Naviz_Dummy</module>
		</setup>
		<connection>
		  <use>core_setup</use>
		</connection>
	  </dummy_setup>
	  <dummy_write>
		<connection>
		  <use>core_write</use>
		</connection>
	  </dummy_write>
	  <dummy_read>
		<connection>
		  <use>core_read</use>
		</connection>
	  </dummy_read>
	</resources>
  </global>
  <admin>
	<routers>
	  <dummy>
	    <use>admin</use>
		<args>
		  <module>Naviz_Dummy</module>
		  <frontName>admin_dummy</frontName>
		</args>
	  </dummy>
	</routers>
  </admin>
  <adminhtml>
	<menu>
	  <dummy module="dummy">
		<title>Dummy</title>
		<sort_order>100</sort_order>
		<children>
		  <dummy module="dummy">
		    <title>Manage Dummy</title>
			<sort_order>0</sort_order>
			<action>admin_dummy/adminhtml_dummy</action>
		  </dummy>
		</children>
	  </dummy>
	</menu>
	<acl>
	  <resources>
		<all>
		  <title>Allow Everything</title>
		</all>
		<admin>
		  <children>
			<dummy translate="title" module="dummy">
			  <title>Dummy</title>
			  <sort_order>1000</sort_order>
			  <children>
		  <dummy translate="title">
			<title>Manage Dummy</title>
			<sort_order>0</sort_order>
		  </dummy>
			  </children>
			</dummy>
		  </children>
		</admin>
	  </resources>
	</acl>
	<layout>
	  <updates>
		<dummy>
		  <file>dummy.xml</file>
		</dummy>
	  </updates>
	</layout>
  </adminhtml>
</config> 

XML Layout

/app/design/adminhtml/default/default/layout/dummy.xml
<?xml version="1.0"?>
<layout version="0.1.0">
  <dummy_adminhtml_dummy_index>
	<reference name="content">
	  <block type="dummy/adminhtml_dummy" name="dummy" />
	</reference>
  </dummy_adminhtml_dummy_index>
</layout>

Standard Magento Admin URLs, no rewrite needed

Also, rather than using a rewrite for the admin section described above, you can implement the same standard admin generated urls Magento uses. These look like: ‘/admin/dummy/index/’ instead of the above that would generate ‘/dummy/adminhtml_dummy/index/’.

To implement this different url structure you can change the following in your config.xml:

/app/code/local/Naviz/Dummy/etc/config.xml
    ...
    <admin>
        <routers>
            <!-- Includes our controller, so when we add the adminhtml menu item below, it is found! -->
            <adminhtml>
                 <args>
                     <modules>
                         <dummy before="Mage_Adminhtml">Naviz_Dummy_Adminhtml</dummy>
                     </modules>
                 </args>
             </adminhtml>
        </routers>
    </admin>
    <adminhtml>
        <menu>
            <dummy module="dummy">
                <title>[Module]</title>
                <sort_order>71</sort_order>               
                <children>
                    <items module="dummy">
                        <title>Manage Items</title>
                        <sort_order>0</sort_order>
                        <action>adminhtml/dummy</action>
                    </items>
                </children>
            </dummy>
        </menu>
    ...
    

Here i am attaching the completed module zip: Download Naviz_Dummy

Hopping this article helps you when creating magento extension with custom database table

46 Comments on “Creating magento extension with custom database table

  1. Anil
    December 13, 2014

    Thanks!
    a lot for good tutorial!!

  2. Highree
    February 2, 2015

    Hi,

    can you help me out here? I Have following error:

    2015-02-02T22:14:49+00:00 ERR (3): Recoverable Error: Argument 1 passed to Mage_Adminhtml_Controller_Action::_addContent() must be an instance of Mage_Core_Block_Abstract, boolean given, called in /site/app/code/local/MyNameSpace/Workouts/controllers/Adminhtml/WorkoutsController.php on line 37 and defined in /site/app/code/core/Mage/Adminhtml/Controller/Action.php on line 120
    2015-02-02T22:14:49+00:00 ERR (3): Recoverable Error: Argument 1 passed to Mage_Adminhtml_Controller_Action::_addLeft() must be an instance of Mage_Core_Block_Abstract, boolean given, called in /site/app/code/local/MyNameSpace/Workouts/controllers/Adminhtml/WorkoutsController.php on line 38 and defined in /site/app/code/core/Mage/Adminhtml/Controller/Action.php on line 126

    Thank you in advance

    • navaneeth
      February 4, 2015

      On which page did u get this error

  3. Mujtaba Mazhar
    May 5, 2015

    I did everything correctly an got the output but there are 2 grids in admin side with same values.

    • navaneeth
      May 12, 2015

      Pls recheck the code you done and verify if there is any change from i mentioned

  4. Ali
    May 12, 2015

    when i completed the codes above,,
    i tried input data from sql and the data displays in magento admin
    but when i clicked new item to add item,,it displays error like the following

    Fatal error: Class ‘Mage_Featech_Helper_Data’ not found in C:\xampp\htdocs\specs\app\Mage.php on line 547

    please help,,’
    thanks

    • navaneeth
      May 12, 2015

      Did u created helper files in /app/code/local///Helper/Data.php
      The content of the file must be like below
      class Mage_Featech_Helper_Data extends Mage_Core_Helper_Abstract
      {

      }

      Try this

  5. sandeep
    May 25, 2015

    Am also getting same error Fatal error: Class ‘Mage_Featech_Helper_Data’ not found in C:\xampp\htdocs\specs\app\Mage.php on line 547.

    • navaneeth
      June 9, 2015

      Can u check u have created the helper class correctly?

  6. Vinícius
    June 4, 2015

    Hello, thank you very much for this explanation!
    But the link that you’ve mentioned that contains the missing line in controller is broken. And the screen that was supposed to show the grid is blank. Could you help me, please?
    Thank you so much!

    • navaneeth
      July 2, 2015

      Could u pls check the code again

  7. Hari
    June 17, 2015

    Once created all folder structure is there anything to run from admin to display/run extension.

    I just completed all folder structure how can i proceed.

    • navaneeth
      June 17, 2015

      nothing to do more u can see them in admin
      pls refresh cache from cache management and reindex all

  8. Alphy
    June 29, 2015

    when i click on manage items on my dashboard it link don’t found

    • navaneeth
      July 2, 2015

      Clear cache and login again and try

  9. Anand
    July 29, 2015

    whenver I referesh the page admin side i get the error message like Fatal error: Class ‘Mage_Module_Helper_Data’ not found in E:\wamp\www\magento1.8.0.0\app\Mage.php on line 546

    • navaneeth
      December 9, 2015

      Pls check whether you have added helper class in helper folder

  10. rodge
    November 17, 2015

    Hello! Thanks for this tutorial.

    I followed everything from your tutorial however I got some problem. The page display the Grid Title and the Add Button however the Grid table is not displayed. What would be the problem?

    When I clicked on the add new button it display the forms and the side menu, however, when I try to save it pop up the error “Can’t retrieve entity config: mymodulename/mymodelname” and the records were not saved.

    The problems are:

    1. Grid is not displaying.

    2. Can’t save new data.

    Thanks!

    • navaneeth
      December 9, 2015

      Please check the code again, will assist you if the same problem exists

      • Rodge
        December 9, 2015

        Thanks @navaneeth for help and for your tutorial. I already figured out the problem why the grid wasn’t showing. I found out that I have a problem with my model folder structure and the class that it extends.

        The RESOURCE MODEL should extends Mage_Core_Model_Resource_Db_Abstract

        The COLLECTION MODEL should extends Mage_Core_Model_Resource_Db_Collection_Abstract

        These simple changes helps me overcome the problem.

        Thanks!

        • navaneeth
          December 15, 2015

          Happy to hear from you…..

  11. sam
    March 12, 2016

    i have copied this setup with a few changes . i removed the bits in the config.xml

    and omitted the frontend template files.

    however, when i install the files to the directories, the module does not appear on the admin pages.

    checking the database, the table isnt created as well.

    can you assist? i am using magento 1.9.2.

    • navaneeth
      March 16, 2016

      Can you share the code you have done in an archive format

    • navaneeth
      March 17, 2016

      I have updated the code pls check them

  12. Parthiban
    April 20, 2016

    Hi Navaneeth good tutorial thank u so much

    how to view the backend updated information on frontend (URL).

    • navaneeth
      April 21, 2016

      please see this section
      /app/design/frontend/base/default/template/dummy/index.phtml

      the code is commented there, you can use that code in your template file

  13. Charles Antony
    May 7, 2016

    Hi Navaneeth,

    Thank you for this most helpful article. I have worked this on my magento 1.9 version. It works fine.

  14. Sajeewa
    May 20, 2016

    thanks for sharing

  15. Arup Roy
    May 21, 2016

    Thank you so much.
    working fine but 1 thing is How to display data in frontend?

    • navaneeth
      May 23, 2016

      please see this section
      /app/design/frontend/base/default/template/dummy/index.phtml

      the code is commented there, you can use that code in your template file

      • Pradeep Gusain
        August 19, 2016

        As per your blog I have uncommented the code in template file for viewing in front end but nothing is happening.
        I am only getting the title : HOME PAGE/ DUMMY

        http://localhost:8080/magento/index.php/dummy/index

        This is my local access, is there anything wrong with the url?

        My admin side is working fine and I have a dummy item.

        • navaneeth
          October 10, 2016

          /dummy is enough to load the page.. please check whether the dummy.xml file is in the location of your theme layout folder

  16. Jose ramirez
    May 30, 2016

    I just did everything, but did all the files directly on my server. not sure if this have something to do. also my module name has two upper case: CatalogRoles

    I see it on the menu of the backend, but after going to the manager it gives me a 404 error. not sure what’s wrong.

    • navaneeth
      June 23, 2016

      Do these steps
      1. Flush magento cache
      2. Reindex data
      3. Logout from admin
      4. Login again

      And see whether it works

      • Shoaib
        October 15, 2016

        Its not working i got this error when go to the page

        There has been an error processing your request

        Exception printing is disabled by default for security reasons.

        Error log record number: 269170784

        • navaneeth
          October 15, 2016

          Do this
          Navigate to the “errors” folder.
          Change local.xml.sample to local.xml.
          This will print the actual errors
          And get me what is been shown there

  17. shams
    December 8, 2016

    Hi,

    Thank you so much for Tutorial.

    working fine but when i adding one extra field in form so getting error?

    • navaneeth
      December 19, 2016

      What was the error showing?

      • shams
        December 21, 2016

        Actually i want to upload image and save image path in table. so please help me.

        Getting Error => Fatal error: Class ‘Mage_Imageuploader_Helper_Data’ not found in C:\xampp\htdocs\magento\app\Mage.php on line 547

        File Path: app\code\local\Naviz\Dummy\Block\Adminhtml\Dummy\Edit\Tab\Form.php

        Code added in form for image upload:

        $fieldset->addField(‘image_1’, ‘file’, array(
        ‘label’ => Mage::helper(‘imageuploader’)->__(‘Upload’),
        ‘value’ => ‘image_1’,
        ‘disabled’ => false,
        ‘readonly’ => true,
        ));

        File Path: app\code\local\Naviz\Dummy\controllers\Adminhtml\DummyController.php

        Code for uploading in saveAction()

        public function saveAction()
        {
        $post_data=$this->getRequest()->getPost();

        if ($post_data) {

        try {
        // Code Added From Here //
        if(isset($_FILES[‘image_1’][‘name’]) and (file_exists($_FILES[‘image_1’][‘tmp_name’])))
        {
        try
        {
        $path = Mage::getBaseDir(‘media’) . DS . ‘banner’ . DS;
        $uploader = new Varien_File_Uploader(‘image_1’);
        $uploader->setAllowedExtensions(array(‘jpg’,’png’,’gif’,’jpeg’));
        $uploader->setAllowRenameFiles(false);
        $uploader->setFilesDispersion(false);
        $destFile = $path.$_FILES[$image][‘name’];
        $filename = $uploader->getNewFileName($destFile);
        $uploader->save($path, $filename);
        $data[‘img’] = $_FILES[‘image_1’][‘name’];
        }
        catch(Exception $e)
        {

        }
        }
        else
        {
        if(isset($data[‘image_1’][‘delete’]) && $postData[‘image_1’][‘delete’] == 1)
        $data[‘image_1’] = ”;
        else
        unset($data[‘image_1’]);
        }
        // Code Added From Here //
        $model = Mage::getModel(“dummy/dummy”)
        ->addData($post_data)
        ->setId($this->getRequest()->getParam(“id”))
        ->save();

        Mage::getSingleton(“adminhtml/session”)->addSuccess(Mage::helper(“adminhtml”)->__(“Dummy was successfully saved”));
        Mage::getSingleton(“adminhtml/session”)->setDummyData(false);

        if ($this->getRequest()->getParam(“back”)) {
        $this->_redirect(“*/*/edit”, array(“id” => $model->getId()));
        return;
        }
        $this->_redirect(“*/*/”);
        return;
        }
        catch (Exception $e) {
        Mage::getSingleton(“adminhtml/session”)->addError($e->getMessage());
        Mage::getSingleton(“adminhtml/session”)->setDummyData($this->getRequest()->getPost());
        $this->_redirect(“*/*/edit”, array(“id” => $this->getRequest()->getParam(“id”)));
        return;
        }

        }
        $this->_redirect(“*/*/”);
        }

  18. Akash Rai
    December 19, 2016

    Fatal error: Class ‘Chatbot_Assist_Block_Adminhtml_Assist_Edit_Form’ not found in C:\xampp\htdocs\magento_push\app\code\core\Mage\Core\Model\Layout.php on line 491

    Receiving above error.

    • navaneeth
      December 19, 2016

      Please check if there is file in this path Chatbot/Assist/Block/Adminhtml/Assist/Edit/Form.php
      If not create it with the lines below this one /app/code/local/Naviz/Dummy/Block/Adminhtml/Dummy/Edit/Form.php
      from this page

  19. Harshad
    May 4, 2017

    Hi Navneet,

    This is an interesting tutorial and covers a lot of functionality for custom modules. I have no experience with Magento but I am able to dabble with PHP.

    You are creating a lot of config files, but most of them are not explained. For eg. my current use case is where I need to create a data staging table where I will import Excel data from 3rd party vendors, and then I need to merge the data into Magento after performing some operations.

    After reading your tutorial, I am not able to hack the necessary files to accomplish this. Like I do not know that this XML config file will load my database setup, this one will load custom views, etc.

    • Harshad
      May 4, 2017

      Or this is the minimum code/config to setup a menubar entry of the plugin, etc.

  20. Idoia
    January 25, 2018

    Hi, thank you very much for this tutorial!! is perfect and it works great :), now I would like to add two related tables by a foreing key, could you please tell me if I can do that with your code, or the files I had to change to do that? thank you very much!!!

    • Idoia
      January 26, 2018

      I have already find the answer, thanks!

  21. harshil suvagiya
    April 9, 2018

    Hello, thank you very much for this explanation.i need some more example like this in magneto for more understanding.

Leave a Reply

Your email address will not be published. Required fields are marked *