My previous post was dedicated to URL rewriting with rules located in a database. This part is about rewriting via configuration files. Here we go.

Let’s return to our dispatch() method. The address was rewritten with the help of



Mage::getModel('core/url_rewrite')->rewrite(); 1 Mage:: getModel ( 'core/url_rewrite' ) -> rewrite ( ) ;



The next type is rewriting via configuration files – it’s not as “big” as the previous one.



/** * Apply configuration rewrites to current url * * @return Mage_Core_Controller_Varien_Front */ public function rewrite() { $request = $this->getRequest(); $config = Mage::getConfig()->getNode('global/rewrite'); if (!$config) { return; } foreach ($config->children() as $rewrite) { $from = (string)$rewrite->from; $to = (string)$rewrite->to; if (empty($from) || empty($to)) { continue; } $from = $this->_processRewriteUrl($from); $to = $this->_processRewriteUrl($to); $pathInfo = preg_replace($from, $to, $request->getPathInfo()); if (isset($rewrite->complete)) { $request->setPathInfo($pathInfo); } else { $request->rewritePathInfo($pathInfo); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 /** * Apply configuration rewrites to current url * * @return Mage_Core_Controller_Varien_Front */ public function rewrite ( ) { $request = $this -> getRequest ( ) ; $config = Mage:: getConfig ( ) -> getNode ( 'global/rewrite' ) ; if ( ! $config ) { return ; } foreach ( $config -> children ( ) as $rewrite ) { $from = ( string ) $rewrite -> from ; $to = ( string ) $rewrite -> to ; if ( empty ( $from ) || empty ( $to ) ) { continue ; } $from = $this -> _processRewriteUrl ( $from ) ; $to = $this -> _processRewriteUrl ( $to ) ; $pathInfo = preg_replace ( $from , $to , $request -> getPathInfo ( ) ) ; if ( isset ( $rewrite -> complete ) ) { $request -> setPathInfo ( $pathInfo ) ; } else { $request -> rewritePathInfo ( $pathInfo ) ; } } }



This rewriting type allows “replacing” controllers. “Replacing” – because, in fact, in this rewriting type Zend_Controller_Request_Http object’s PATH_INFO is rewritten.

Let’s create a simple Test module, which rewrites the Category controller of the Catalog module, and define the rewrite rule.



<global> <rewrite> <belvg_test_catalog_view> <from><![CDATA[#^catalog/category/#]]></from> <to>test/category/</to> </belvg_test_catalog_view> </rewrite> </global> 1 2 3 4 5 6 7 8 < global > < rewrite > < belvg_test_catalog_view > < from > < ! [ CDATA [ #^catalog/category/#]]></from> < to > test / category / < / to > < / belvg_test_catalog_view > < / rewrite > < / global >



All the rewrite rules, defined in the configuration files, are first loaded:



$request = $this->getRequest(); $config = Mage::getConfig()->getNode('global/rewrite'); if (!$config) { return; } 1 2 3 4 5 $request = $this -> getRequest ( ) ; $config = Mage:: getConfig ( ) -> getNode ( 'global/rewrite' ) ; if ( ! $config ) { return ; }



If rules exist, the search will begin:



foreach ($config->children() as $rewrite) { $from = (string)$rewrite->from; $to = (string)$rewrite->to; if (empty($from) || empty($to)) { continue; } $from = $this->_processRewriteUrl($from); $to = $this->_processRewriteUrl($to); $pathInfo = preg_replace($from, $to, $request->getPathInfo()); if (isset($rewrite->complete)) { $request->setPathInfo($pathInfo); } else { $request->rewritePathInfo($pathInfo); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 foreach ( $config -> children ( ) as $rewrite ) { $from = ( string ) $rewrite -> from ; $to = ( string ) $rewrite -> to ; if ( empty ( $from ) || empty ( $to ) ) { continue ; } $from = $this -> _processRewriteUrl ( $from ) ; $to = $this -> _processRewriteUrl ( $to ) ; $pathInfo = preg_replace ( $from , $to , $request -> getPathInfo ( ) ) ; if ( isset ( $rewrite -> complete ) ) { $request -> setPathInfo ( $pathInfo ) ; } else { $request -> rewritePathInfo ( $pathInfo ) ; } }



Data for a further processing is prepared and PATH_INFO is replaced:



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



Because of use of preg_replace, rewriting rules can be described with templates. In this case:



$from = ‘#^catalog/category/#’ $to = ‘/test/category/’ 1 2 $from = ‘ #^catalog/category/#’ $to = ‘ / test / category / ’



then:



$pathInfo = preg_replace(‘#^catalog/category/#’, ‘/test/category/’, $request->getPathInfo()); 1 $pathInfo = preg_replace ( ‘ #^catalog/category/#’, ‘/test/category/’, $request->getPathInfo());

Tip: if you use this rewriting method, compose rules carefully. In this case, ‘#^/catalog/category/#’ rule will not work.

As soon as $pathInfo variable is defined, PATH_INFO is set.



if (isset($rewrite->complete)) { $request->setPathInfo($pathInfo); } else { $request->rewritePathInfo($pathInfo); } 1 2 3 4 5 if ( isset ( $rewrite -> complete ) ) { $request -> setPathInfo ( $pathInfo ) ; } else { $request -> rewritePathInfo ( $pathInfo ) ; }



app/code/core/Mage/Core/Controller/Request/Http.php



Partner With Us Let's discuss how to grow your business. Get a Free Quote.

/** * Specify new path info * It happen when occur rewrite based on configuration * * @param string $pathInfo * @return Mage_Core_Controller_Request_Http */ public function rewritePathInfo($pathInfo) { if (($pathInfo != $this->getPathInfo()) && ($this->_rewritedPathInfo === null)) { $this->_rewritedPathInfo = explode('/', trim($this->getPathInfo(), '/')); } $this->setPathInfo($pathInfo); return $this; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /** * Specify new path info * It happen when occur rewrite based on configuration * * @param string $pathInfo * @return Mage_Core_Controller_Request_Http */ public function rewritePathInfo ( $pathInfo ) { if ( ( $pathInfo != $this -> getPathInfo ( ) ) && ( $this -> _rewritedPathInfo === null ) ) { $this -> _rewritedPathInfo = explode ( '/' , trim ( $this -> getPathInfo ( ) , '/' ) ) ; } $this -> setPathInfo ( $pathInfo ) ; return $this ; }



And passed to dispatch() method for further proceeding.

As we can assume from the method, $this->_rewritedPathInfo is redefined the same way.

app/code/core/Mage/Core/Controller/Request/Http.php



/** * Path info array used before applying rewrite from config * * @var null || array */ protected $_rewritedPathInfo= null; protected $_requestedRouteName = null; protected $_routingInfo = array(); 1 2 3 4 5 6 7 8 /** * Path info array used before applying rewrite from config * * @var null || array */ protected $_rewritedPathInfo = null ; protected $_requestedRouteName = null ; protected $_routingInfo = array ( ) ;



This array takes part in the process of the current controller, path and action name definition. Methods:

getRequestedRouteName,

getRequestedControllerName,

getRequestedActionName

in the app/code/core/Mage/Core/Controller/Request/Http.php class return data based on this variable. It affects templates structure for the current request.

If complete variable is installed:



<global> <rewrite> <belvg_test_catalog_view> <from><![CDATA[#^catalog/category/#]]></from> <to>test/category/</to> <complete>1</complete> </belvg_test_catalog_view> </rewrite> </global> 1 2 3 4 5 6 7 8 9 < global > < rewrite > < belvg_test_catalog_view > < from > < ! [ CDATA [ #^catalog/category/#]]></from> < to > test / category / < / to > < complete > 1 < / complete > < / belvg_test_catalog_view > < / rewrite > < / global >



Rewrite takes place without $_rewritedPathInfo:



if (isset($rewrite->complete)) { $request->setPathInfo($pathInfo); } else { $request->rewritePathInfo($pathInfo); } 1 2 3 4 5 if ( isset ( $rewrite -> complete ) ) { $request -> setPathInfo ( $pathInfo ) ; } else { $request -> rewritePathInfo ( $pathInfo ) ; }



I.e. the original PATH_INFO will be used.

It is necessary to use the following rule to guarantee the stated module will be rewritten:



<global> <rewrite> <belvg_test_catalog_view> <from><![CDATA[#^{catalog}/category/#]]></from> <to>test/category/</to> <!--complete>1</complete--> </belvg_test_catalog_view> </rewrite> </global> 1 2 3 4 5 6 7 8 9 < global > < rewrite > < belvg_test_catalog_view > < from > < ! [ CDATA [ #^{catalog}/category/#]]></from> < to > test / category / < / to > < ! -- complete > 1 < / complete -- > < / belvg_test_catalog_view > < / rewrite > < / global >



Processing of this template type is located in the _processRewriteUrl method:

app/code/core/Mage/Core/Controller/Varien/Front.php



/** * Replace route name placeholders in url to front name * * @param string $url * @return string */ protected function _processRewriteUrl($url) { $startPos = strpos($url, '{'); if ($startPos!==false) { $endPos = strpos($url, '}'); $routeName = substr($url, $startPos+1, $endPos-$startPos-1); $router = $this->getRouterByRoute($routeName); if ($router) { $fronName = $router->getFrontNameByRoute($routeName); $url = str_replace('{'.$routeName.'}', $fronName, $url); } } return $url; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /** * Replace route name placeholders in url to front name * * @param string $url * @return string */ protected function _processRewriteUrl ( $url ) { $startPos = strpos ( $url , '{' ) ; if ( $startPos !== false ) { $endPos = strpos ( $url , '}' ) ; $routeName = substr ( $url , $startPos + 1 , $endPos - $startPos - 1 ) ; $router = $this -> getRouterByRoute ( $routeName ) ; if ( $router ) { $fronName = $router -> getFrontNameByRoute ( $routeName ) ; $url = str_replace ( '{' . $routeName . '}' , $fronName , $url ) ; } } return $url ; }



I.e. if we redefine for the frontName module:



<routers> <mymodule> <use>standard</use> <args> <module>Namespace_Mymodule</module> <frontName>newname</frontName> </args> </anymodule> </routers> 1 2 3 4 5 6 7 8 9 < routers > < mymodule > < use > standard < / use > < args > < module > Namespace_Mymodule < / module > < frontName > newname < / frontName > < / args > < / anymodule > < / routers >



It will be possible to use the following template



<![CDATA[#^{mymodule}/action/#]]> 1 < ! [ CDATA [ #^{mymodule}/action/#]]>



Instead of this one:



<![CDATA[#^newname/action/#]]> 1 < ! [ CDATA [ #^newname/action/#]]>



One more way to change controller behavior is to use the before event:



<frontend> <routers> <othermodule> <use>standard</use> <args> <modules> <Namespace_Mymodule before="Namespace_Othermodule">Namespace_Mymodule</Namespace_Mymodule> </modules> </args> </othermodule> </routers> </frontend> 1 2 3 4 5 6 7 8 9 10 11 12 < frontend > < routers > < othermodule > < use > standard < / use > < args > < modules > < Namespace_Mymodule before = "Namespace_Othermodule" > Namespace_Mymodule < / Namespace_Mymodule > < / modules > < / args > < / othermodule > < / routers > < / frontend >



After defining the path like this, it’s possible to use your own controller instead of a third-party one.