General warning — while ideally it should be supported, what you're trying to do isn't really meant to be done by a non-core Magento developer. The abstractions around routing are confusing, and possibly incomplete. It's relatively safe to introduce a new router object with a match
method, but (as you've seen) expecting it to behave in predicable ways with the system is asking Magento too much. Generally speaking, if you want a special URL in Magento, you use the rewrite system (either the rewrite models, or the configuration rewrites)
But that's not any fun.
So, the particular problem you're running into is a routername/frontName mismatch. Your router configuration is named customsearch
, but your frontName
is named lookfor
. This is a common problem when customizing system behavior, because most developers don't realize there's a difference between these two. That's because Magento core code always has them match each other. You see this this a lot in the various methods of replacing a controller action, and having the layout handles generated not match the layout handles Magento expects.
Looking at your specific problem, my guess (because it's hard to tell with the information provided) is your custom router class
`Namespace_Customsearch_Controller_Router`
in inheriting from the Mage_Core_Controller_Varien_Router_Abstract
class. If you look at the getFrontNameByRoute
method definition there
#File: app/code/core/Mage/Core/Controller/Varien/Router/Abstract.php
public function getFrontNameByRoute($routeName)
{
return $routeName;
}
You can see the method is essentially a placeholder. In the standard router
#File: app/code/core/Mage/Core/Controller/Varien/Router/Standard.php
public function getFrontNameByRoute($routeName)
{
if (isset($this->_routes[$routeName])) {
return $this->_routes[$routeName];
}
return false;
}
This method checks the configuration built up in the internal _routes
array, and returns the value it finds (which will be the frontName).
As I said, my guess is your router object inherits from the Abstract class, and doesn't have a custom getFrontNameByRoute
method. Your router object needs a similar/identical method, or needs to inherit from the standard router to have this functionality.
In this excellent post by Alan Storm, I found a hint to a possible solution. You should register your own router. An example can be found in Magento's CMS module.
In the CMS module's config.xml find this section:
<events>
<controller_front_init_routers>
<observers>
<cms>
<class>Mage_Cms_Controller_Router</class>
<method>initControllerRouters</method>
</cms>
</observers>
</controller_front_init_routers>
</events>
The method initControllerRouters()
registers a new router:
public function initControllerRouters($observer)
{
/* @var $front Mage_Core_Controller_Varien_Front */
$front = $observer->getEvent()->getFront();
$front->addRouter('cms', $this);
}
...that will be iterated in app/code/core/Mage/Core/Controller/Varien/Front.php:
while (!$request->isDispatched() && $i++<100) {
foreach ($this->_routers as $router) {
if ($router->match($this->getRequest())) {
break;
}
}
}
The match() method of the CMS-Router contains this code:
$page = Mage::getModel('cms/page');
$pageId = $page->checkIdentifier($identifier, Mage::app()->getStore()->getId());
if (!$pageId) {
return false;
}
$request->setModuleName('cms')
->setControllerName('page')
->setActionName('view')
->setParam('page_id', $pageId);
...which leads to the file Cms/controllers/PageController.php. The class inside is named Mage_Cms_PageController
and has a method viewAction()
that asks for the request's parameter page_id
. From here, you can look further at the method Mage::helper('cms/page')->renderPage($this, $pageId)
.
I think another big problem will be, if the configured frontName matches that of a system frontName, or the frontName defined by another module. I have no idea how this might work out.
Best Answer
If you want to load your custom router prior to all other routers in Magento, then try this one.
Define your custom router in
config.xml
File :
app\code\{codePool}\{Namespace}\{Module}\etc\config.xml
Now make
core
module depend on your moduleFile :
app\etc\modules\Namespace_Module.xml
Now clear your cache. You are done.
Why does This work
Router loading is happening inside front-controller1. The abbreviated form of router loading code is shown below.
This method simply grabs routers from various resources and add it to the protected property
$_routers
as an array2. As you can see, the priorities are like this:Routers which are defined via XML files will be added to
$_routers
firstRouters which are added via the event
controller_front_init_routers
go nextAt last, the Default router will be added to the array
Now, the standard router and admin router are defined in
app/code/core/Mage/Core/etc/config.xml
and hence they will be loaded first in the$_routers
array and thus they will be processed first.In order to change this intentional priority for the standard and admin router, you need to define your router via your module's
config.xml
file. This will bring your router to the priority level 1. Making core module depend on your module gives more priority to your module and hence Magento will consider your module first and hence load your router in$_routers
array first.Hope that makes sense.
1:
Mage_Core_Controller_Varien_Front::init()
2:
$this->addRouter()
is actually what populates$_routers
.