knightly

Blog Archives

Returning Blocks from controllers without layout attached in Magento

When working in the admin environment of Magento i had to add a controller action that was called by an Ajax request. The problem however is that all layout data is returned as well when calling

$this->renderLayout();

from the controller. So my next attempt was to try to render the block separately and adding it to the layout.

$this->_initCustomer();
$this->getResponse()->setBody(
            $this->getLayout()->createBlock('block/location')
            ->setCustomerId(Mage::registry('current_customer')->getId())
            ->setData('list', $list)
            ->setUseAjax(true)
            ->toHtml()
);

This kinda worked. But now i had no more control over the template used. Or maybe i missed that part. But i don’t like to specify my Block anyway Magento should pick this up automatically.

Solving this issue is actually quite easy. The only thing we need to do is change the layout structure of the module. We change the name to root. And that’s it!


The name attribute tells Magento it is a root block so no need for the rest of the layout.

Override controllers in Magento

The last time i had to rewrite one of the core Magento blocks. And that turned out to be quite easy. My new challenge was to rewrite / overwrite one of the Core admin controllers. In this case the Mage_Adminhtml_CustomerController.

I had no idea where to start so i did some googling beforehand. And came to the conclusion that a lot of people are trying to do this. Because of this there is a long list of solutions to solve this. And in most cases developers just advice to drop the Core class in the local folder and work from there. But that doesn’t really make sense. First of all it code duplication in the worst form. And besides that all cool OO stuff like extending is gone.

And since Magento is such a flexible system. There must be a good clean way to solve this. One thread i found had some good info. And i used it as my starting point. There was one problem with this thread. The XML used seems to be an old form of rewriting in Magento.
I found a (lost it) post by one of the Magento devs that shows a new and more clean way of defining this in XML.

In the last post i already created the [Namespace]_All.xml module config. And we can use it for this as well. So we start by telling Magento we are using our own [Namespace_]_Adminhtml module.

<[namespace]_Adminhtml>
    true
    local
    
        
    

create local/Namespace/Adminhtml/controllers/CustomerController.php

The next thing to do is create the actual controller. And add an include line on top to the original file. Magento does not use autoloading for the controllers in this way.

include_once("Mage/Adminhtml/controllers/CustomerController.php");

class [namespace]_Adminhtml_CustomerController extends Mage_Adminhtml_CustomerController
{
	public function somenewAction()
	{

	}
}

Now the Core CustomerController is replaced by our own namespaced version. But it still retains all functionality of the parent.

The only thing left is to create the config file for this module. And tell it to rewrite to the new [namespace]

Create local/[namespace]/Adminhtml/etc/config.xml


	
        <[namespace]_Adminhtml>
            0.1.0
        <[namespace]_Adminhtml>
    

	
    	
    		
    			
    				
    					<[namespace]_Adminhtml before="Mage_Adminhtml">[namespace]_Adminhtml
    				
    			
    		
    	
    

The config section is placed inside the admin tags. because the controller in question is an admin controller. We basically tell Magento that we will be using our own Adminhtml module instead of the Core one. But it will of course fall back on the Core functionality when methods have not been overwritten.