最终结果是我可以去http://www.mysite.com/frontname/something/something
我将捕获前面名称后的所有内容,并使用它来添加挂钩和设置数据。 这将以与类别如何工作类似的方式起作用,但我的前缀将被添加到url之前,以便我可以调用与该类别相关的布局中的不同块。
如果在完成这一切之后它会帮助其他人,你会使用_call方法来处理所有请求:Dynamic router name for magento controller
如果有更好的方法可以做到这一点。
答案 0 :(得分:1)
您应该创建一个自定义路由器,它将另外用于默认路由器。要在配置中添加新路由器,请使用以下XML:
<default>
<web>
<routers>
<arbitrary_name>
<area>frontend</area>
<class>Your_Module_Controller_Router_Something</class>
</arbitrary_name>
</routers>
</web>
<shorturls>
</shorturls>
</default>
路由器可能如下所示:
class Your_Module_Controller_Router_Something extends Mage_Core_Controller_Varien_Router_Abstract
{
private static $_module = 'your_module';
private static $_realModule = 'Your_Module';
private static $_controller = 'your_controller';
private static $_controllerClass = 'Your_Module_ControllerClassName';
private static $_action = 'your_action';
/**
* @var Zend_Controller_Request_Http
*/
protected $_request;
/**
* Front controller looks for collectRoutes() although it is not defined
* in abstract router class!
*
* (non-PHPdoc)
* @see Mage_Core_Controller_Varien_Router_Standard::collectRoutes()
*/
public function collectRoutes()
{
// nothing to do here
}
/* (non-PHPdoc)
* @see Mage_Core_Controller_Varien_Router_Abstract::match()
*/
public function match(Zend_Controller_Request_Http $request)
{
$this->_request = $request;
// here you will have to implement your matching:
// - detect if the request should be matched by this router
// (i.e. check for "frontname" after base url)
// - return false if not
// - otherwise:
$this->_setRequestRoute();
$this->_dispatch();
return true;
}
/**
* @return void
*/
protected function _setRequestRoute()
{
$this->_request->setModuleName(self::$_module);
$this->_request->setControllerName(self::$_controller);
$this->_request->setActionName(self::$_action);
$this->_request->setControllerModule(self::$_realModule);
}
/**
* @return void
*/
protected function _dispatch()
{
$this->_request->setDispatched(true);
$controller = Mage::getControllerInstance(
self::$_controllerClass, $this->_request, $this->_response
);
$controller->dispatch(self::$_action);
}
}
重要的方法是match()
,它将为每个请求调用,并且必须确定路由器是否负责该请求,如果是,则调度它。此路由器始终会调度相同的控制器操作your_controller/your_action
。
您可能还希望根据网址提供一些参数:$this->_request->setParam(key, value)
答案 1 :(得分:0)
以上代码适用于某一点,需要更多的理解和解释。这是我在过去10个小时左右的工具后想出的:
文件:config.xml中
<?xml version="1.0"?>
<config>
<modules>
<AJW_Bestselling>
<version>1.6.0.0.1</version>
</AJW_Bestselling>
</modules>
<frontend>
<routers>
<bestselling>
<use>standard</use>
<args>
<module>AJW_Bestselling</module>
<frontName>bestsellers</frontName>
</args>
</bestselling>
</routers>
<layout>
<updates>
<bestselling>
<file>bestselling.xml</file>
</bestselling>
</updates>
</layout>
</frontend>
<global>
<events>
<controller_front_init_routers>
<observers>
<bestselling>
<class>AJW_Bestselling_Controller_Router</class>
<method>initControllerRouters</method>
</bestselling>
</observers>
</controller_front_init_routers>
</events>
<models>
<bestselling>
<class>AJW_Bestselling_Model</class>
</bestselling>
</models>
<blocks>
<bestselling>
<class>AJW_Bestselling_Block</class>
</bestselling>
</blocks>
<helpers>
<bestselling>
<class>AJW_Bestselling_Helper</class>
</bestselling>
</helpers>
</global>
文件:控制器/ Router.php
<?php
class AJW_Bestselling_Controller_Router extends Mage_Core_Controller_Varien_Router_Abstract
{
private static $_module = 'bestsellers';
private static $_realModule = 'AJW_Bestselling';
private static $_controller = 'index';
private static $_controllerClass = 'AJW_Bestselling_Controller_Index';
private static $_action = 'view';
public function initControllerRouters($observer)
{
$front = $observer->getEvent()->getFront();
$front->addRouter('bestselling', $this);
}
public function match(Zend_Controller_Request_Http $request)
{
$this->_request = $request;
$identifier = trim($request->getPathInfo(), '/');
//If Magento Is Not Installed Reroute To Installer
if (!Mage::isInstalled()) {
Mage::app()->getFrontController()->getResponse()
->setRedirect(Mage::getUrl('install'))
->sendResponse();
exit;
}
//If we dont match our router then let another router take over
if(!substr($identifier,0,strlen('bestsellers')) == 'bestsellers'){
return false;
}
//If we do match the our router then lets add some data and dispatch our
controller
else{
$route_params = str_replace ( "bestsellers/" , "" , $identifier );
$rewrite = Mage::getModel('core/url_rewrite');
$rewrite->setStoreId(1);
$rewrite->loadByRequestPath($route_params);
$category_route = $rewrite->getIdPath();
//Check to see if the route exists before we do anything else
if(!$category_route != ""){
return false;
}//Otherwise send the parameters to the request
else{
$id = str_replace ( "category/" , "" , $category_route );
$this->_request->setParam('id',$id);
}
}
$this->_setRequestRoute();
return true;
}
protected function _setRequestRoute()
{
$this->_request->setModuleName(self::$_module)
->setControllerName(self::$_controller)
->setActionName(self::$_action)
->setControllerModule(self::$_realModule);
return true;
}
}
文件:控制器/ IndexController.php
class AJW_Bestselling_IndexController extends Mage_Core_Controller_Front_Action{
public function indexAction(){
echo "This is the index controller";
die();
}
public function viewAction(){
$this->loadLayout();
$this->renderLayout();
}
}
如果你去mysite.com/bestsellers/会发生什么?路由器将加载索引控制器。 但是,如果您转到畅销书/ some / category / url.html,它将触发viewAction,并且类别ID将被发送以供控制器使用。
这背后的概念是能够根据.com之后的网址的第一部分向每个类别显示内容。有些想法可能是畅销,最推荐,最受欢迎,类别问题......将与特定类别形成多对一(或多个)关系。
另请注意,您可以通过有条件地设置AJW_Bestselling_Controller_Router的参数来使用同一模块充当多个模块的路由器。