【问题标题】:Loading objects based on URL parameters in MagentoMagento 中基于 URL 参数加载对象
【发布时间】:2012-08-12 23:19:36
【问题描述】:

我在为我的 Magento 商店创建自定义模块时遇到问题。

我已成功添加路线 (/landing),并创建了在我的基本布局中显示模板内容的/布局文件。我现在需要超越这一点。

我希望能够从 URL 加载参数,根据该参数获取对象,并根据对象的内容显示内容。

示例:用户浏览器访问 domain.com/landing/cool/。这(希望)会调用着陆控制器。控制器将能够以某种方式拉取“cool”参数,并拉取与cool关联的着陆对象。然后,我的模板可以获取该对象并显示其元素。

我知道那里有很多东西,但我一直在努力解决这个问题,但一无所获。 Magento 必须为其所有类别、项目等执行此操作。有没有人知道我该怎么做?

【问题讨论】:

    标签: magento parameter-passing magento-1.5


    【解决方案1】:

    如果你做 domain.com/landing/[controller]/cool/[key]/[value],你可以通过 $this->getRequest()->getParam('[key]') 来获取 value [价值]。然后您可以基于此设置模板,但我认为这是一个不同的问题。如果您仍然感到困惑,请告诉我。

    【讨论】:

    • 我仍然很困惑 :) 理想情况下,它应该是 domain.com/landing/[variable](很酷是我的示例变量)。如何配置 magento 来执行此操作?
    • 我编辑了我的回复,因为我之前打错了。在当前示例中,您将在 LandingController 的 coolAction() 中获取您的请求。
    • 如果你必须使用那种 url 格式,我会让服务器从 /landing/* 重定向到 /landing/action/key/*。
    • 哇,今天完全没有了。它需要采用 domain.com/frontname/controller/action/key/value 格式。我的错。
    • 啊哈!这似乎是我需要的很大一部分。我假设 magento 重定向无法做到这一点,但我可以将自己的重定向粘贴在 htaccess 中
    【解决方案2】:

    以下解释假设您已经按照通常的方式定义了您的名称:

    <config>
        <modules>
            <Mycompany_Landing>
                <version>0.1.0</version>
            </Mycompany_Landing>
        </modules>
        <frontend>
            <routers>
                <landing>
                    <use>standard</use>
                    <args>
                        <module>Mycompany_Landing</module>
                        <frontName>landing</frontName>
                    </args>
                </landing>
            </routers>
        </frontend>
    </config>
    

    在这种情况下,Magento 标准路由器会将 URL landing/cool 映射到

    Mycompany_Landing_CoolController::indexAction()
    

    这是因为 Magento 标准路由器使用 frontname/controller/action 模式处理 URL,在您的情况下它知道

    • frontname为landing,映射到Mycompany_Landing模块
    • 控制器名称为cool,将转换为CoolController
    • 缺少动作名称,导致默认使用indexAction

    但您希望cool 成为参数,而不是控制器。

    我猜这背后的原因是,除了landing/cool,你还想拥有多个登陆区域,比如landing/awesomelanding/insane等等。这意味着您必须设置多个控制器,每个控制器用于不同的着陆区。

    在这种情况下避免多个控制器的一种可能解决方案是实现您的自己的路由器。

    实现你自己的路由器

    要实现自己的路由器,您需要挂钩controller_front_init_routers 事件,例如通过像这样扩展您的app/code/local/Mycompany/Landing/etc/config.xml

    <config>
        <global>
            <events>
                <controller_front_init_routers>
                    <observers>
                        <landing>
                            <class>Mycompany_Landing_Controller_Router</class>
                            <method>controllerFrontInitRouters</method>
                        </landing>
                    </observers>
                </controller_front_init_routers>
            </events>
        </global>
    </config>
    

    接下来创建一个合适的app/code/local/Mycompany/Landing/Controller/Router.php 文件:

    class Mycompany_Landing_Controller_Router extends Mage_Core_Controller_Varien_Router_Abstract
    {
    
        /**
         * Add own router to Magento router chain
         *
         * @param Varien_Event_Observer $oObserver
         */
    
        public function controllerFrontInitRouters($oObserver)
        {
            // Add this router to the current router chain
            $oObserver
                ->getEvent()
                ->getFront()
                ->addRouter('landing', $this);
        }
    
        /**
         * Match routes for the landing module
         *
         * @param Zend_Controller_Request_Http $oRequest
         * @return bool
         */
    
        public function match(Zend_Controller_Request_Http $oRequest)
        {
    
            $sPathInfo = trim($oRequest->getPathInfo(), '/');
            $aPathInfo = explode('/', $sPathInfo);
    
            // Cancel if the route request is for some other module
            if ($aPathInfo[0] != 'landing') {
                return false;
            }
    
            // Cancel if it's not a valid landing zone
            if (!in_array($aPathInfo[1], array('cool'))) {
                return false;
            }
    
            // Rewrite the request object
            $oRequest
                ->setModuleName('landing')
                ->setControllerName('index')
                ->setActionName('index')
                ->setParam('zone', $aPathInfo[1])
                ->setAlias(
                    'landing_router_rewrite',
                    true
                );
    
            // Tell Magento that this router can match the request
            return true;
    
        }
    
    }
    

    上面文件的controllerFrontInitRouters() 方法负责将您自己的路由器合并到Magento 路由器链中,使其看起来像这样:

    Mage_Core_Controller_Varien_Router_Admin
    Mage_Core_Controller_Varien_Router_Standard
    Mage_Cms_Controller_Router
    Mycompany_Landing_Controller_Router
    Mage_Core_Controller_Varien_Router_Default
    

    Magento 在调度时会按照给定的顺序循环这个链。这意味着,像您这样的自定义路由器总是最早在第 4 位被调用。只有在前三个路由器都不能匹配路由请求的情况下,才会调用您的路由器。

    当调用文件的match()方法并检测到有效路由时(目前只有landing/cool),它会改变请求对象,这样Mycompany_Landing_IndexController::indexAction()就会被调度,有一个参数zone和值cool

    请注意,这个match() 过于简单化了。它不包含消毒等。不要忘记修复这个^^

    最后创建一个app/code/local/Mycompany/Landing/controllers/IndexController.php文件:

    class Mycompany_Landing_IndexController extends Mage_Core_Controller_Front_Action
    {
    
        public function indexAction()
        {
    
            if (!$this->getRequest()->getAlias('landing_router_rewrite')) {
                $this->_forward('noRoute');
                return;
            }
    
            $sZone = $this->getRequest()->getParam('zone');
    
            die(__METHOD__ . ' called with zone = ' . $sZone);
    
        }
    
    }
    

    如果请求对象中没有设置 landing_route_rewrite 别名,indexAction 的第一个 if 块将取消操作(请参阅路由器的 match() 方法中的 setAlias())。

    这样做是因为用户也可以通过使用其他 URL(如 landinglanding/indexlandig/index/indexlanding/index/index/zone/cool 等)访问此 indexAction()

    我猜你不想让其他 URL 被 SEO 排名,也不想执行两次验证和清理,但如果你不需要它,只需删除 if 块。

    现在您可以扩展 indexAction() 以对您的着陆区做任何您喜欢做的事情。

    【讨论】:

      【解决方案3】:

      我稍后会在这里进一步研究它,但现在唯一想到的是在“/”上爆炸以抓住它们。

      【讨论】:

        【解决方案4】:

        以下是我通过 Javascript 为我的一个项目执行此操作的方法:

        function populateSelect(url, element, target) {
            var selectedValue = document.getElementById(element);
            var elementValue = selectedValue.options[selectedValue.selectedIndex].value;
        
            pathArray = url.split( '/' );
            pathArray.shift();
            pathArray.shift();
            pathArray.splice(5,0, element);
            pathArray.splice(6,0, elementValue);
            url = pathArray.join("/");
            url = 'http://' + url;
        
            new Ajax.Request(url, {
                method:    "POST",
                onSuccess:
                    function(transport) {
                        var json    = transport.responseText.evalJSON(true);
                        var options = '';
                        $(target).descendants().each(Element.remove);
        
                         for (var i = 0; i < json.length; i++) {
                            var opt = document.createElement('option');
                            opt.text = json[i].optionName;
                            opt.value = json[i].optionValue;
                            $(target).options.add(opt);
                        }
                    }
            });
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-04-03
          • 1970-01-01
          • 1970-01-01
          • 2018-12-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多