Creating Custom Magento URL Rewrites

Posted on

When  you create modules in Magento and want to create fancy URL for your module without using .htaccess rewrites. Don’t worry, Magento has very easy way for URL rewrite using config.xml. 

Suppose there is a module you have developed to displays a list of all products belong to a particular manufacture. Here manufacturer is a product drop down product attribute, let us assume the frontend URL of our module is ‘manufacturer’. So the URL of a particular manufacturer page ideally would be something like this

www.your-website.com/manufacturer/index/index/brand/sony

This is how default URL’s are in Magento where,

manufacturer = module frontend url
index = IndexController
index = index Action function
brand/sony = request parameters
But suppose if we want a URL like this
www.your-website.com/manufacturer/sony

which works exactly the same work as above URL. This traditional way to do this is using .htaccess URL rewrites, but in this post we are going to see how to do this using config.xml controller rewrites.
Now lets see how to do this, open your config.xml file of your module and add this code inside the  <global> tag.

<rewrite>
<fancy_url>
<from><![CDATA[/manufacturer\/(.*)/]]></from>
<to><![CDATA[manufacturer/index/index/manufacturer/$1/]]></to>
<complete>1</complete>
</fancy_url>
</rewrite>

what we are doing here is tell Magento to rewrite /manufacturer\/(.*)/ to manufacturer/index/index/manufacturer/$1/
The <form> tag takes in any regular expression which is the source URL and in the <to> we put in the destination url. $1,$2 etc is used for variable substitution which works same as the php preg_match function.
The <complete>1</complete> is important, it make Magento use the correct layout handle which is used in layout xml files. what this means is if you don’t put <complete>1</complete>, then in your controller when you do
$this->loadLayout();
$this->renderLayout();

Magento will not read the xml tag related to <manufacturer_index_index> but will read something else depending on your URL.

If you’r wondering where exactly this rewrite magic happens inside Magento , the code is located in class Mage_Core_Controller_Varien_Front, rewrite() function.
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);
}
}
}

As you see Magento uses the preg_replace() function itself, so all rules applicable to preg_replace() can be used for our rewerites.

There is just one exception to the regular expression you can use here. Your regular expression’s cannot have ‘{‘ and ‘}’ in them, the curly bracket regex won’t work. The reason being Magento uses curly brackets for internal processing. If you see the code of the _processRewriteUrl() function, it replaces the content inside curly braces with route name.
public function rewrite()
{
$reprotected 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;
}

 

Hopefully it will work for you!

 

Leave a Reply

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