【问题标题】:Force Magento To Always Use Single Controller For Module强制 Magento 始终对模块使用单个控制器
【发布时间】:2013-03-30 09:11:37
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: magento


    【解决方案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-&gt;_request-&gt;setParam(key, value)

    【讨论】:

    • 调用未定义的方法 AJW_Best sell_indexController::hasAction()
    • 我对静态参数中应该包含的内容有点困惑,您能否进一步解释一下
    • 我能够做到这一点,但遇到了一个问题,请参阅:stackoverflow.com/questions/15711866/…
    【解决方案2】:

    上面的代码工作到一定程度,需要更多的理解和解释。以下是我在过去 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_Best sell_Controller_Router 的参数,使用同一模块充当多个模块的路由器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多