As well as Magento giving us the ability to add custom blocks, helpers, models and controllers, we also have the ability to safely rewrite these existing classes without affecting the Magento upgrade process or security patches that may overwrite some of these files.
If you haven’t already read the article about adding custom blocks, helpers, models, and controllers, it is recommended to do so to familiarise yourself with how to name Magento’s class files.
Similar to how we add our custom blocks etc. to Magento through config.xml
, rewrites also take place through this configuration file, albeit the syntax is a little different.
Let’s start with a block rewrite. First of all, let’s add our own module and add a module declaration file.
<?xml version="1.0"?> <config> <modules> <Custom_Somemodule> <codePool>local</codePool> <active>true</active> </Custom_Somemodule> </modules> </config>
Let’s dive into the config.xml
file, starting with a block rewrite. As an example, let’s rewrite Magento’s Mage_Page_Block_Html_Topmenu
class.
<?xml version="1.0"?> <config> <global> <blocks> <page> <rewrite> <html_topmenu>Custom_Somemodule_Block_Page_Html_Topmenu</html_topmenu> </rewrite> </page> </blocks> </global> </config>
Within the pair of blocks
nodes, we first specify the module of the class we are attempting to rewrite. In our example, it is Magento’s Page
module.
We then specify a pair or rewrite
nodes that tell Magento we are attempting to perform a rewrite.
The rewrite
nodes are checked for by Magento when using its factory methods.
The html_topmenu
nodes are from the location of the class file we are attempting to rewrite within the Mage_Page
module within its Block
directory. The full path to the class is Mage/Page/Block/Html/Topmenu.php
.
If we were rewriting the Breadcrumbs.php
block file found in Mage/Page/Block/Html/Breadcrumbs.php
, then the value within the rewrite
nodes would become html_breadcrumbs
.
The value within the html_topmenu
is the class that we will use to rewrite the Topmenu.php
class. With the class being called Custom_Somemodule_Block_Page_Html_Topmenu
, you are telling Magento that the class will be located within the Custom/Somemodule/Block/Page/Html/Topmenu.php
directory.
Now we can create the block class, ensuring that it extends from the original Topmenu.php
class we are wanting to rewrite.
<?php class Custom_Somemodule_Block_Page_Html_Topmenu extends Mage_Page_Block_Html_Topmenu { public function getHtml($outermostClass = '', $childrenWrapClass = '') { echo "Here is the override"; // Some more code to follow } }
You can override any method from the original block file by copying a method over to your custom block class, then editing it as you please.
Helper rewrites are similar to blocks in terms of the syntax used on config.xml
. Simply specify a helpers
node and follow the same steps.
<?xml version="1.0"?> <config> <global> .... <helpers> <tag> <rewrite> <data>Custom_Somemodule_Helper_Data</data> </rewrite> </tag> </helpers> </global> </config>
We can then add our helper class that will extend Mage_Tag_Helper_Data
.
<?php class Custom_Somemodule_Helper_Data extends Mage_Tag_Helper_Data { public function cleanTags(array $tagNamesArr) { echo "Here is an override"; // Some more code below } }
Model rewrites are also similar to blocks and helpers in terms of the syntax used in config.xml
. Simply specify a models
node and follow the same steps.
<?xml version="1.0"?> <config> <global> .... <models> <sales> <rewrite> <order>Custom_Somemodule_Model_Sales_Order</order> </rewrite> </sales> </helpers> </global> </config>
We can then add our model class that will extend Mage_Sales_Model_Order
.
<?php class Custom_Somemodule_Model_Sales_Order extends Mage_Sales_Model_Order { public function getTrackingNumbers() { echo "Here is an override"; // Some more code below } }
Rewriting controllers is slightly different as routers belong in either a pair of frontend
or admin
nodes, and the fact that router syntax is different to block, helper and model syntax within config.xml
anyway.
<?xml version="1.0"?> <config> <frontend> <routers> <customer> <args> <modules> <custom_somemodule before="Mage_Customer">Custom_Somemodule</custom_somemodule> </modules> </args> </customer> </routers> </frontend> </config>
The name of the module whose controller we are attempting to rewrite is names within the pair or routers
nodes. In this example, it is customer
as we’ll be rewriting a controller within the Mage_Customer
module.
The custom_somemodule
node name is just a unique alias given to our controller rewrite.
The before="Mage_Customer"
attribute means that Magento should look for a controller firstly in our custom module controller before it looks in the Mage_Customer
module. Because of this, we should ensure that the name of the controller that we are trying to rewrite matches the name of our custom controller. For this example, we will be rewriting the AccountController.php
class therefore our controller name should be AccountController.php
.
<?php require_once(Mage::getModuleDir('controllers','Mage_Customer').DS.'AccountController.php'); class Custom_Somemodule_AccountController extends Mage_Customer_AccountController { public function loginPostAction() { echo "Test"; exit(); } }
As controller classes are not included within the Magento autoload process, we have to explicitly require the original controller class file at the top of our custom controller class file.
If we now attempt to login to our customer account, we can see that the word Test
has been printed out.
Note: This article is based on Magento Community/Open Source version 1.9.