Magento 2 Overriding Controller

This post walks through the process to override a controller in Magento 2.

There are a few steps to override a Magento 2 controller.

Step 1. Building a Magento 2 extension structure

Building directories as given following:

magento2 --- app --- code
                       |--- A2bizz --- Sample
                       | --- Controller
                       | --- etc
                              | --- module.xml
                              | --- di.xml

Creating module.xml to define a Magento2 extension:

<?xml version="1.0"?>
<!--
/**
 * Created by blog.a2bizz@gmail.com
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="A2bizz_Sample" setup_version="0.0.1"/>
</config>

Step 2. Setting preference in di.xml

Creating di.xml to refer the overriding class:

<?xml version="1.0"?>
<!--
/**
 * Created by blog.a2bizz@gmail.com
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
<preference for="Magento\Cms\Controller\Index\Index" type="A2bizz\Sample\Controller\Index\Index" /> 
</config>

A2bizz\Sample\Controller\Index\Index will be used to override Magento\Cms\Controller\Index\Index, which is the homepage in original Magento 2.

Step 3. Defining an overriding controller class

Under magento2/app/code/A2bizz/Sample/Controller, defining Index.php as following.

<?php
/**
 * Created by blog.a2bizz@gmail.com
 */
namespace A2bizz\Sample\Controller\Index;
class Index extends \Magento\Cms\Controller\Index\Index
{
    public function execute($coreRoute = null)
    {
        $this->messageManager->addSuccess('Message from new controller.');
        return parent::execute($coreRoute);
    }
} 

Index.php redefines function execute() to override the function in \Magento\Cms\Controller\Index\Index. The new execute() adds a message to homepage, but it may also implements a complex logic.

Magento2: Overriding Block

This post go through the process to extend a block in Magento2.

There are a few steps to override a Magento2 block as given below –

Step 1. Building a Magento 2 extension structure

Building directories as following:

magento2 --- app --- code
                       |--- A2bizz --- Sample
                                             | --- Block
                                             | --- etc
                                                    | --- module.xml
                                                    | --- di.xml

Creating module.xml to define a Magento2 extension:

<?xml version="1.0"?>
<!--
/**
 * Created by blog.a2bizz@gmail.com
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="A2bizz_Sample" setup_version="0.0.1"/>
</config>

Step 2. Setting preference in di.xml

Creating di.xml to refer the overriding block class:

<?xml version="1.0"?> 
<!-- /** * Created by blog.a2bizz@gmail.com */ --> 
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"> 
<preference for="Magento\Theme\Block\Html\Title" type="A2bizz\Sample\Block\HelloTitle" /> 
</config> 

A2bizz\Sample\Block\HelloTitle will be used to override Magento\Theme\Block\Html\Title.

Step 3. Defining an overriding class

Under magento2/app/code/A2bizz/Sample/Block, defining HelloTitle.php as following.

<?php
/**
 * Created by blog.a2bizz@gmail.com
 */
namespace A2bizz\Sample\Block;
use Magento\Framework\View\Element\Template;
class HelloTitle extends \Magento\Theme\Block\Html\Title
{
    public function getPageTitle()
    {
        return 'A2bizz Custom';
    }
    protected function _toHtml()
    {
        $this->setModuleName($this->extractModuleName('Magento\Theme\Block\Html\Title'));
        return parent::_toHtml();
    }
}

HelloTitle.php redefines function getPageTitle() to override the function in \Magento\Theme\Block\Html\Title. The new getPageTitle() just return a text string, but it may also implements a complex logic.

HelloTitle.php also redefines function _toHtml(). Although HelloTitle overrides \Magento\Theme\Block\Html\Title, the template file of \Magento\Theme\Block\Html\Title is still supposed to be used. And the real path of a template file is determined by both the module name of a block and the template attribute of the block. Therefore, the module name of HelloTitle is still Magento_Theme, rather than A2bizz_Sample.

This line

$this->setModuleName($this->extractModuleName('Magento\Theme\Block\Html\Title'));

sets the correct nominal module name. This module name is necessary to render with the template originally defined for Magento\Theme\Block\Html\Title.