Controller override and request rewrite in Magento

There are three ways to override controller in Magento. They fit for various purposes.

The first and easiest way can be used to route the request to more than one module. When a request arrives on a frontName, it usually is rounted to a module. For example, /cms/page/view is routed to cms module page controller view action. If I have developed a cms related module called “faq” with a brand new controller “QuestionController”, but I want it share the same cms frontName with cms module, i.e., I want /cms/question/any_action be routed to faq module.

It is very easy to achieve by a config.xml like the following:

<config>
	<frontend>
		<routers>
			<cms>
				<args>
					<modules>
						<any_name>MyNamespace_Faq</any_name>
					</modules>
				</args>
			</cms>
		</routers>
	</frontend>
</config>

Strictly speaking, no overriding in above example because it only activates a brand new controller. In a truly overriding example, if I want PageController of faq module override PageController in cms module, I can add before=”Mage_Cms” to make sure PageController of faq module supersede the same name controller in cms module. The complete configuration is shown below:

<config>
	<frontend>
		<routers>
			<cms>
				<args>
					<modules>
						<any_name before="Mage_Cms">MyNamespace_Faq</any_name>
					</modules>
				</args>
			</cms>
		</routers>
	</frontend>
</config>

The second way can be used to mass override controllers.

<config>
	<global>
		<rewrite>
			<any_name>
				<from><![CDATA[#^/cms/#]]></from>
				<to>/faq/</to>
				<complete></complete>
			</any_name>
		</rewrite>
	</global>
</config>

The above configuration makes all controllers in faq module override same name controllers in cms module. In class Mage_Core_Controller_Varien_Front, there is

$pathInfo = preg_replace($from, $to, $request->getPathInfo());

doing path info string replacement based on regular expression. And because it is based on regular expression, I can do mass replacement at a time.

The tag flags whether requested path info should be turned into new module path info. In other words, when the request arrives on /cms/page/view, it is rewritten to /faq/page/view. Without tag, the action layout handle is cms_page_view; with tag, the action layout handle is faq_page_view.

I can use this method to route the request to a brand new controller, i.e.

<config>
	<global>
		<rewrite>
			<any_name>
				<from><![CDATA[#^/cms/question/#]]></from>
				<to>/faq/question/</to>
				<complete></complete>
			</any_name>
		</rewrite>
	</global>
</config>

Note that cms module does not have question controller, but the above configuration will not cause any error.

The third way can be used to override individual actions.

<config>
	<global>
		<routers>
			<cms>
				<rewrite>
					<page>
						<to>faq/question</to>
						<override_actions>true</override_actions>
						<actions>
							<view_action><to>new_module/new_controller/new_action</view_action>
						</actions>
					</page>
				</rewrite>
			</cms>
		</routers>
	</global>
</config>

This method is documented in class Mage_Core_Controller_Varien_Action.

* This will override:
* 1. cms_module/page_controller/view_action to new_module/new_controller/new_action
* 2. all other actions of cms_module/page_controller to faq_module/question_module

It is very handy to precisely control the request rewrite to action level, but it can not route to a brand new controller. The following code will cause an error.

<config>
	<global>
		<routers>
			<cms>
				<rewrite>
					<question><!-- Error: cms module does not have question controller -->
						<to>faq/question</to>
						<override_actions>true</override_actions>
						<actions>
							<view_action><to>new_module/new_controller/new_action</view_action>
						</actions>
					</question>
				</rewrite>
			</cms>
		</routers>
	</global>
</config>

Leave a Reply

Your email address will not be published. Required fields are marked *