有关magento控制器重写

最近这几天一直在仔细研究magento,发先一个小问题,不知道算不算bug,因为网络上流传的教程都是这么教的。

首先,我是想重写产品详细页,配置如下:

           
 <Edcy_Shopping_Product>
      <from><![CDATA[#^/catalog/product/#]]></from>
      <to>/shopping/product/</to>
 </Edcy_Shopping_Product>

控制器里面也并没有做什么东西,详细如下
    
public function viewAction(){
//        header("Content-Type: text/xml");
//        die(Mage::app()->getConfig()->getNode()->asXML());
//        exit;
        echo '覆盖过的....';
        parent::viewAction();
    }

这样开启模块的话,我们就可以访问了。但是产品详细页有重写的,所以存在两个url访问;如下

http://www.edcy.com/index.php/electronics/cameras/olympus-stylus-750-7-1mp-digital-camera.html

http://www.edcy.com/index.php/catalog/product/view/id/46/category/12

开启重写的话,一般我们也就访问第一url。

问题就来了,第一个url对于重写确实完全没有反应的。它访问的还是core里面的catalog模块里的东西。

仔细看magento的初始化文件mage.php文件,找到run方法,在run方法里调用了app/code/core/Mage/core/model/app.php文件里的run方法。

在这个方法里找到这一句

$this->getFrontController()->dispatch();

这里就是获取控制器显示视图的地方了。

在看看dispath方法,这个方法在app/code/core/Mage/core/controller/Varien/Front.php文件里面。

下面是这个方法的具体代码

    public function dispatch()
    {
        $request = $this->getRequest();

        // If pre-configured, check equality of base URL and requested URL
        $this->_checkBaseUrl($request);

        $request->setPathInfo()->setDispatched(false);
        //这里是去查数据库重写的
        if (!$request->isStraight()) {
            Varien_Profiler::start('mage::dispatch::db_url_rewrite');
            Mage::getModel('core/url_rewrite')->rewrite();
            Varien_Profiler::stop('mage::dispatch::db_url_rewrite');
        }
        //这里是查找xml里面对于模块重写的
        Varien_Profiler::start('mage::dispatch::config_url_rewrite');
        $this->rewrite();
        Varien_Profiler::stop('mage::dispatch::config_url_rewrite');
        Varien_Profiler::start('mage::dispatch::routers_match');
        $i = 0;
        //现在就比较奇怪的是重写了后没有执行第二个rewrite方法
        while (!$request->isDispatched() && $i++<100) {
            foreach ($this->_routers as $router) {
                if ($router->match($this->getRequest())) {
                    break;
                }
            }
        }
        Varien_Profiler::stop('mage::dispatch::routers_match');
        if ($i>100) {
            Mage::throwException('Front controller reached 100 router match iterations');
        }
        // This event gives possibility to launch something before sending output (allow cookie setting)
        Mage::dispatchEvent('controller_front_send_response_before', array('front'=>$this));
        Varien_Profiler::start('mage::app::dispatch::send_response');
        $this->getResponse()->sendResponse();
        Varien_Profiler::stop('mage::app::dispatch::send_response');
        Mage::dispatchEvent('controller_front_send_response_after', array('front'=>$this));
        return $this;
    }

我们再看看第二个rewrite方法到底是做了什么.


    public function rewrite()
    {
        $request = $this->getRequest();
        $config = Mage::getConfig()->getNode('global/rewrite');
        if (!$config) {
            return;
        }

    //前面是判断有无找到重写节点
    //下面循环节点preg_replace替换,然后设置pathinfo。

    foreach ($config->children() as $rewrite) {
            $from = (string)$rewrite->from;
            $to = (string)$rewrite->to;
            if (empty($from) || empty($to)) {
                continue;
            }
            $from = $this->_processRewriteUrl($from);
            $to   = $this->_processRewriteUrl($to);

            $pathInfo = preg_replace($from, $to, $request->getPathInfo());
            if (isset($rewrite->complete)) {
                $request->setPathInfo($pathInfo);
            } else {
                $request->rewritePathInfo($pathInfo);
            }
        }
    }


这下原因就很明显了,第二个url先是查找数据库里的重写,找到一条catalog/product/view/id/46/category/12这样的target_path(这里可以去core_url_rewrite数据表里查查看)。

同时因为你的配置文件里的正则表达式是写成这样的

#^/catalog/product/#

这样就匹配不到要查找的重写地址了。


改的话,我们可以把配置文件里的重写配置改成这样

            <Edcy_Shopping_Product>
                <from><![CDATA[#^/?catalog/product/#]]></from>
                <to>/shopping/product/</to>
            </Edcy_Shopping_Product>

这样就行了。我们就既可以匹配到以/开头的同时又可以匹配到没有/的,这里最好就加上斜杠,因为这样我们才好区分模块。理论上是一个模块是以/开头,这样更容易匹配(想如果catalog前面还有一些字母的话),也方便区分。


还有一种方法是修改第一个rewrite方法把/加上,就是core里的url文件夹里rewrite的model。核心代码这里就不建议修改了。

因为网上的教程都是把这个congfig.xml里重写的配置写成第一种,所以建议重写模块都写第二种配置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章