我发现了Magento路由逻辑的一个问题,我想知道是否有人可以证实这一点。
Magento堆叠路由器admin,standard,然后默认并一次处理一个。 Magento根据URL获取当前模块名称(请参阅Mage_Core_Controller_Varien_Router_Standard::match())
,然后根据与Magento配置中的frontName匹配来检查该路由器是否应该处理该模块。如果找到匹配,则路由如果没有,它会继续到下一个路由器。
配置摘录:
<admin> <routers> <myroute> <use>admin</use> <args> <module>MyNamespace_MyModule</module> <frontName>myroute</frontName> </args> </myroute> </routers> </admin> <frontend> <routers> <myroute> <use>admin</use> <args> <module>MyNamespace_MyModule</module> <frontName>myroute</frontName> </args> </myroute> </routers> </frontend>
这意味着如果您的前端路由器使用与管理路由器相同的名称,则管理路由器将始终首先匹配,即使在前端页面上也是如此。您的前端页面现在将使用admin base_url
进行路由,如果是管理页面,则可能与您商店的网址不同导致重定向损坏。
请注意,在Magento实例中,此问题并不明显,其中管理基本URL与前端基本URL相同。
任何人都可以确认我对路由器逻辑的评估是否正确?
答案 0 :(得分:4)
您可能还需要查看Varien / Router / Standard.php:
/**
* checking if this admin if yes then we don't use this router
*
* @return bool
*/
protected function _beforeModuleMatch()
{
if (Mage::app()->getStore()->isAdmin()) {
return false;
}
return true;
}
这在方法match(Zend_Controller_Request_Http $request)
和collectRoutes($configArea, $useRouterName)
内调用,因为$useRouterName
有时会返回admin
,并且还会返回standard
作为前端请求。这个假设听起来很正确,因为它取决于magento如何在同一个类中构建和堆叠_routes
和_modules
私有数组:Mage_Core_Controller_Varien_Router_Standard
。
我相信在这种情况下,您希望将<use>
节点指定为standard
作为前端,将admin
指定为admin,或者重写<global>
节点中的控制器操作
我认为你最好的选择是阅读:
和/或使用X-debug逐步执行逻辑。
即使Alan Storm在他的文章中写道,用于前端和后端的相同路由器也不应该是相同的。
因此,如果由于某种原因,商店模型对象认为它处于管理模式,看起来此方法可以确保标准路由器对象失效。与标准/管理路由器关系一样,商店对象是另一个指向Magento开发过程的某些部分的东西,它们首先关注前端应用程序,然后在管理控制台上进行处理,并且必须进行后端端口更改
商店对象是一个真正只适用于前端/购物车应用程序的模型。但是,由于Magento中的大量代码假定存储对象存在,因此需要管理控制台应用程序可用。反过来,这会在路由器级别产生麻烦,这就是导致这样的检查的原因。许多抽象层,类/模块之间没有明确的契约,以及由于缺乏测试而产生的重构恐惧总会导致这些情况。
答案 1 :(得分:3)
这不是Magento的错误,但在编写模块或使用第三方代码时需要注意。我澄清了问题和决议here。本质上,应始终使用现有的adminhtml路由,而不是创建新的管理路由。这使得管理员中的网址保持一致并避免冲突。感谢Alan和Jared帮助我更好地理解Magento路由。
答案 2 :(得分:1)
只要把我的2美分投入其中;我今晚肯定注意到了这个问题!我正在构建一个自定义模块,我的 config.xml 路由器的定义如下:
<admin>
<routers>
<namespace_module>
<use>admin</use>
<args>
<module>Namespace_Module</module>
<frontName>namespace_module</frontName>
</args>
</namespace_module>
</routers>
</admin>
<frontend>
<routers>
<namespace_module>
<use>standard</use>
<args>
<module>Namespace_Module</module>
<frontName>namespace_module</frontName>
</args>
</namespace_module>
</routers>
</frontend>
我在前端遇到404错误,而后端路由器工作正常。我更改了前端名称并瞧瞧:
<admin>
<routers>
<namespace_module>
<use>admin</use>
<args>
<module>Namespace_Module</module>
<frontName>namespace_module</frontName>
</args>
</namespace_module>
</routers>
</admin>
<frontend>
<routers>
<namespace_module>
<use>standard</use>
<args>
<module>Namespace_Module</module>
<frontName>namespace_module_front</frontName>
</args>
</namespace_module>
</routers>
</frontend>
我猜是使用一个独特的名字是有道理的!