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
1 |
Mage::getModel('core/url_rewrite')->rewrite(); |
The next type is rewriting via configuration files – it’s not as “big” as the previous one.
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.
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:
1 2 3 4 5 |
$request = $this->getRequest(); $config = Mage::getConfig()->getNode('global/rewrite'); if (!$config) { return; } |
If rules exist, the search will begin:
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:
1 |
$pathInfo = preg_replace($from, $to, $request->getPathInfo()); |
Because of use of preg_replace, rewriting rules can be described with templates. In this case:
1 2 |
$from = ‘#^catalog/category/#’ $to = ‘/test/category/’ |
then:
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.
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
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
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:
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:
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:
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
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:
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
1 |
<![CDATA[#^{mymodule}/action/#]]> |
Instead of this one:
1 |
<![CDATA[#^newname/action/#]]> |
One more way to change controller behavior is to use the before event:
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.
Thank you, miss.
I think ‘/’ is missing
/test/category/
because without ‘/’ preg_replace function seems not to work