July 30th, 2009

Magento Adminhtml – Using the Same Backend to Frontend Structure

Category:Admin Panel | Posted By Mai Erne at 8:17 PM

The Magento adminhtml (or admin panel) is quite different from other modules for the frontend. The Adminhtml module has a distinct implementation of the Model-Controller-View scheme. In fact, forms, tables, graphs and etc. are usually stereotypical and highly repetitive comparing to the large varieties in the frondend. As a result, in Adminhtml page, such elements are generalized into block ‘widgets’ to boost coding efficiency.

However, when building a new module, we often need to modify the frontend and the backend together. And in many cases, since the we already build the functions in frontend module, it’s really a waste of energy if we have to rewrite everything in terms of ‘widget’ in the backend. Simply, we would like to migrate the controller and view to the backend and reuse the code.

Here, I’m going to go through the basic steps the Mage_Adminhtml_Block_Template rather than widgets.

(This is a developer’s guide.)

Let’s begin with creating a new menu in the Admin panel. We added to the config.xml to our new module:

[codesyntax lang="xml" lines="fancy"]

<adminhtml>
  <menu>
    <new_module translate="title" module="new_module">
      <title>New Module Name</title>
      <sort_order>50</sort_order>
      <action>new_module/new_controller</action>
    </new_module>
  </menu>
</adminhtml>

[/codesyntax]

After the config.xml, we start working on the controller:
_initAction() handles some basic menu preparation.

[codesyntax lang="php" lines="fancy"]

protected function _initAction() {
  $this->loadLayout()
      ->_setActiveMenu('new_module/new_controller')
      ->_addBreadcrumb(Mage::helper('new_module')->__('Menu Name'), Mage::helper('new_module')->__('Menu Name'));
  return $this;
}

[/codesyntax]

It’s always a good idea to have handy functions like _getSession(), so we can use addSuccess() and addError() functions in the session.

[codesyntax lang="php" lines="fancy"]

protected function _getSession() {
    return Mage::getSingleton('adminhtml/session');
}

[/codesyntax]

After that, the key is to explicitly add a block to the layout:

[codesyntax lang="php" lines="fancy"]

public function indexAction() {
    $this->_initAction()
        ->_addContent($this->getLayout()->createBlock('new_module/new_controller'))
        ->renderLayout();
}

[/codesyntax]

Up to here, we are done with the controller. Next we switch to the block .php file.

We create a new block .php file, extending Mage_Adminhtml_Block_Template, as defined in the controller, the class constructor:

[codesyntax lang="php" lines="fancy"]

public function __construct(){
    parent::__construct();
    //Let's stay clean and put the modifications under our own namespace, rather than the default
    Mage::getDesign()->setTheme('harapartners');
    $this->setTemplate('new_module/new_template_file.phtml');
    $action = Mage::app()->getFrontController()->getAction();
    if ($action) {
        $this->addBodyClass($action->getFullActionName('-'));
    }
}

[/codesyntax]

It’s usually a good practice to put the .phtml in a separate folder (i.e. namespace like ‘harapartners’). However, the Adminhtml is NOT going to look for the separate folder automatically. The design theme setting in the admin panel only works for the frontend modules. So something like  Mage::getDesign()->setTheme(‘harapartners’) is recommended here.

In addition, we should also do a favor to our fellow hardworking designers, by adding a body class (easier for future CSS or JS). We can include the Magento default function:

[codesyntax lang="php" lines="fancy"]

public function addBodyClass($className){
    $className = preg_replace('#[^a-z0-9]+#', '-', strtolower($className));
    $this->setBodyClass($this->getBodyClass() . ' ' . $className);
    return $this;
}

[/codesyntax]

Finally we can reuse the .phtml from the frontend. Rename the template file and put it in the correct template folder. Enjoy ;)

No Comments for Current Post.

Comments are closed.