Magento: Rewrite/Override Block Controller Model Helper

This article will show how you can override/rewrite Magento Block, Controller, Model and Helper files. We will be dealing with the config XML files and the class files to override.

We override Magento core classes to update/modify the core functionalities according to our need. We can directly makes changes in the core Magento classes but doing so will hamper us when we upgrade the Magento version. All our changes will go away then. Because, when we upgrade Magento, the new core files will replace the old core files which we had changed.

But when we override the Magento core class files, all changes will be done in our local files and the core files remain intact. So, this will not do affect our changes when we upgrade Magento.

Block Override

Scenario: I want to display 3 products per page in product listing.

For this we need to use setPageSize function.

Mage_Catalog_Block_Product_List class is responsible for getting product items in product listing page.

I will override this Block class with my module’s class MyNamespace_MyModule_Block_Product_List. So, the path of class MyNamespace_MyModule_Block_Product_List is MyNamespace/MyModule/Block/Product/List.php

Here is the xml code which is to be written in etc/config.xml for my custom module.


<global>
	<blocks>
		<catalog>
			<rewrite>
				<product_list>MyNamespace_MyModule_Block_Product_List</product_list>
			</rewrite>
		</catalog>
	</blocks>
<global>

MyNamespace_MyModule_Block_Product_List class.
I have used setPageSize(3). This means that, 3 products are displayed per page.


<?php
class MyNamespace_MyModule_Block_Product_List extends Mage_Catalog_Block_Product_List
{
	 /**
     * Retrieve loaded category collection
     *
     * @return Mage_Eav_Model_Entity_Collection_Abstract
     */
    protected function _getProductCollection()
    {
        if (is_null($this->_productCollection)) {
            $layer = Mage::getSingleton('catalog/layer');
            /* @var $layer Mage_Catalog_Model_Layer */
            if ($this->getShowRootCategory()) {
                $this->setCategoryId(Mage::app()->getStore()->getRootCategoryId());
            }

            // if this is a product view page
            if (Mage::registry('product')) {
                // get collection of categories this product is associated with
                $categories = Mage::registry('product')->getCategoryCollection()
                    ->setPage(1, 1)
                    ->load();
                // if the product is associated with any category
                if ($categories->count()) {
                    // show products from this category
                    $this->setCategoryId(current($categories->getIterator()));
                }
            }

            $origCategory = null;
            if ($this->getCategoryId()) {
                $category = Mage::getModel('catalog/category')->load($this->getCategoryId());
                if ($category->getId()) {
                    $origCategory = $layer->getCurrentCategory();
                    $layer->setCurrentCategory($category);
                }
            }
            $this->_productCollection = $layer->getProductCollection();

            $this->prepareSortableFieldsByCategory($layer->getCurrentCategory());

            if ($origCategory) {
                $layer->setCurrentCategory($origCategory);
            }
        }
        return $this->_productCollection->setPageSize(3);
    }
}

Controller Override

Scenario: I want to display products of ‘Living Room’ category to logged in customer only. When guest users try to view the ‘Living Room’ category, they should be redirected to login page.

For this I need to override the Mage_Catalog_CategoryController class.

config.xml

There are 2 ways to write the xml code for controller override. You can use any one of the following:-

The First way


<global>
	<routers>
		<catalog>
			<rewrite>
				<category>
					<to>MyNamespace_MyModule/catalog_category</to>
					<override_actions>true</override_actions>
					<actions>
					   <view><to>MyNamespace_MyModule/catalog_category</to></view>
					</actions>
				</category>
			</rewrite>
		</catalog>
	</routers>
<global>

The Second way


<global>
	<rewrite>
		<mynamespace_mymodule_catalog_category>
			<from><![CDATA[#^/catalog/category/#]]></from>
			<to>/mymodule/catalog_category/</to>
		</mynamespace_mymodule_catalog_category>
	</rewrite>
<global>

Now, you need to create a controller class MyNamespace_MyModule_Catalog_CategoryController
The path for the controller file will be MyNamespace/MyModule/Catalog/CategoryController.php


<?php
require_once('Mage/Catalog/controllers/CategoryController.php');
class MyNamespace_MyModule_Catalog_CategoryController extends Mage_Catalog_CategoryController
{
	/**
     * Initialize requested category object
     *
     * @return Mage_Catalog_Model_Category
     */
    protected function _initCatagory()
    {
        Mage::dispatchEvent('catalog_controller_category_init_before', array('controller_action'=>$this));
        $categoryId = (int) $this->getRequest()->getParam('id', false);
        if (!$categoryId) {
            return false;
        }

        $category = Mage::getModel('catalog/category')
            ->setStoreId(Mage::app()->getStore()->getId())
            ->load($categoryId);

        if (!Mage::helper('catalog/category')->canShow($category)) {
            return false;
        }
        Mage::getSingleton('catalog/session')->setLastVisitedCategoryId($category->getId());
        Mage::register('current_category', $category);
        try {
            Mage::dispatchEvent('catalog_controller_category_init_after', array('category'=>$category, 'controller_action'=>$this));
        } catch (Mage_Core_Exception $e) {
            Mage::logException($e);
            return false;
        }

		/**
		 * My Code
		 * Checking category name and customer logged in
		 * if category name is 'Living Room' and customer is not logged
		 * then redirect to customer login page
		 */

		if($category->getName() == 'Living Room' && Mage::helper('customer')->isLoggedIn() == false) {
			$this->_redirectUrl(Mage::getUrl('customer/account/login'));
		}

        return $category;
    }
}

Model Override

Scenario: I want to add some text e.g. ‘Product:’ in front of every product name. And, I want fixed price for every product e.g. 100.

For this you need to override Mage_Catalog_Model_Product class.

config.xml


<global>
	<models>
		<catalog>
			<rewrite>
				<product>MyNamespace_MyModule_Model_Catalog_Product</product>
			</rewrite>
		</catalog>
	</models>
<global>

Now, you need to create a model class MyNamespace_MyModule_Model_Catalog_Product
The path for the model file will be MyNamespace/MyModule/Model/Catalog/Product.php


<?php
class MyNamespace_MyModule_Model_Catalog_Product extends Mage_Catalog_Model_Product
{
     /**
     * Get product name
	 * Adding a text 'Product:' before product name
     *
     * @return string
     */
    public function getName()
    {
		return "Product: ".$this->_getData('name');
        //return $this->_getData('name');
    }

	/**
	 * Returning a fixed price '100' for every product
     *
     * @return unknown
     */
    public function getPrice()
    {
		return 100;
        //return $this->getPriceModel()->getPrice($this);
    }
}

Helper Override

Scenario: When any logged in customer reviews any product, his/her review (after admin approval) can be viewed from My Account –> My Product Reviews. In this page, you will see list of reviews done by the customer. The review detail is truncated to 50 characters. I want to display more. I want to truncate to 100 characters and display it.

For this you need to override Mage_Review_Helper_Data class.

config.xml


<global>
	<helpers>
		<review>
			<rewrite>
				<data>MyNamespace_MyModule_Helper_Review_Data</data>
			</rewrite>
		</review>
	</helpers>
<global>

Now, you need to create a helper class MyNamespace_MyModule_Helper_Review_Data
The path for the helper file will be MyNamespace/MyModule/Helper/Review/Data.php


<?php
class MyNamespace_MyModule_Helper_Review_Data extends Mage_Review_Helper_Data
{
	/**
	 * Truncating to 100 characters
	 * In core file, there is truncation to 50 characters
	 *
	 * @param string $origDetail
	 * @return string
	 */
	public function getDetail($origDetail){
        return nl2br(Mage::helper('core/string')->truncate($origDetail, 100));
    }
}

Hope this helps. Thanks.