2

最终结果是我可以访问http://www.mysite.com/frontname/something/something

我将捕获 frontname 之后的所有内容,并使用它来添加挂钩和设置数据。这将以与类别的工作方式类似的方式起作用,但我的前名将被添加到 url,以便我可以在与该类别相关的布局中调用不同的块。

如果在这一切都弄清楚后它会帮助其他人,你会使用 _call 方法来处理所有请求:Dynamic router name for magento controller

如果有更好的方法可以做到这一点,我会全力以赴。

4

2 回答 2

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

您可能还希望根据 URL 提供一些参数:$this->_request->setParam(key, value)

于 2013-03-28T23:23:48.293 回答
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>

文件:控制器/路由器.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/ 会发生什么,路由器将加载索引控制器。但是,如果您访问 bestsellers/some/category/url.html,它将触发 viewAction 并且类别 ID 将被发送以供控制器使用。

这背后的概念是能够根据 .com 之后 URL 的第一部分向每个类别显示内容 - 一些想法可能是最畅销的、最推荐的、最受好评的类别问题 .. 任何会形成与特定类别的多对一(或多)关系。

另请注意,您可以通过有条件地设置 AJW_Bestsales_Controller_Router 的参数来使用同一个模块作为多个模块的路由器。

于 2013-03-29T18:52:29.170 回答