• Magento


    看一个url例子 
    http://localhost/magento/index.php/customer/account/login 
    这里假定http://localhost/magento/ 是magento安装目录。那么Magento将自动转而执行customer模块下名字AccountController的loginAction方法。这个是ZendFramework的默认重写规则。 

    另外一个产品详细页的例子 
    http://localhost/magento/index.php/catalog/product/view/id/1/category/3 

    Magento将寻址catalog模块的ProductController的viewAction方法,传入参数id和category. 

    为了搜索引擎更加友好化,我们可能希望用用下面的url同样访问到该产品 
    http://localhost/magento/index.php/basketball/tayshaun-prince-signed-auto-baketball-with-coa-gold.html 

    Magento重写了ZendFramework的机制完成这个功能,它的实现思路是:当发送请求的时候,Magento首先判断 basketball/tayshaun-prince-signed-auto-baketball-with-coa-gold.html是否在数据库core_url_rewrite表中是否有该route path和实际target path映射记录,没有的话,就使用Zend Framework的重写规则寻址相应的php执行代码。 


    为了窥视它的Rewrite机制, 还着实费了不少力气,但是也只是懂些皮毛。下面说说我分析这个机制的过程: 

    仍然以访问 

    Html代码  收藏代码
    1. http://localhost/magento/index.php/basketball/tayshaun-prince-signed-auto-baketball-with-coa-gold.html  


    为例 

    1. 从magento安装目录下的index.php开始,末尾的Mage::run();很显然是程序的入口。 
    2. 打开app/Magento.php查看run()函数尝试在不同的位置输出self::_$app属性(是一个类),看看有没有url关键字basketball,结果发现多处子对象有字符串属性包含它: 


    Java代码  收藏代码
    1. Mage_Core_Controller_Request_Http  
    2.  ->_originalPathInfo = "/basketball/tayshaun-prince-signed-auto-baketball-with-coa-gold.html"  
    3.  ->_requestString = "/basketball/tayshaun-prince-signed-auto-baketball-with-coa-gold.html"  
    4.  ->_requestUri = "/magento/index.php/basketball/tayshaun-prince-signed-auto-baketball-with-coa-gold.html"  
    5.  ->_pathInfo = "catalog/product/view/id/1/category/3"  



    那么为了完成映射,程序必须有一处读取其中一个属性(原始url串),然后进行解析和转换。这是着实有点迷惑了,四个属性,到底哪一个才是关键的呢? 

    3.打开Mage_Core_Controller_Request_Http类文件,先从_originalPathInfo入手(因为名字带了一个original),找到getOriginalPathInfo(), 该方法调用了setPathInfo(), 这么说这个方法应该是设置_pathInfo的函数了,结果这个发现该方法先调用getRequestUrl方法初始化属性 
    _requestUri,这个是url源头,然后运算出如下属性: 
    _originalPathInfo 
    _requestString 
    _pathInfo 

    4. 接着全目录搜索调用getOriginalPathInfo的类方法,找到类Mage_Core_Controller_Varien_Router_Standard。打开调用方法为match,浏览了下整个函数内容,发现了如下代码 

    Java代码  收藏代码
    1.    
    2. $request->setModuleName($module);  
    3.  $request->setControllerName($controller);  
    4.  $request->setActionName($action);  



    由此可以猜测出,对于该例子,这里应该有如下的映射: 

    Java代码  收藏代码
    1. $module = 'catalog';  
    2. $controller = 'ProductController';  
    3. $action = 'viewAction';  



    所以下面的就是要找出$moudle变量是如何计算出来的 

    5. 找到上面初始化$module的位置 
      $module = $request->getModuleName(); 
    一定是$request的属性被某处初始化,才使得 $request->getModuleName()返回module名字。 
    于是代码定位到前面的 
      $p = explode('/', trim($request->getPathInfo(), '/')); 

    6. $request是Mage_Core_Controller_Request_Http类的实例,打开它的getPathInfo方法。 
    ......哈哈 

    线索中断,其实这种分析方法是不推荐的,完全没有程序员逻辑:) 

    线索II. 
    1. 从Mage::run()方法开始,程序员可以敏感地意识到下面代码的关键性 

    Java代码  收藏代码
    1. Mage::run() {  
    2.   ...  
    3.   self::app()->getFrontController()->dispatch();  
    4.   ...  
    5. }  



    2.打开Mage_Core_Controller_Varien_Front的 dispatch方法 

    Java代码  收藏代码
    1. class Mage_Core_Controller_Varien_Front{  
    2.  function dispatch() {  
    3.    ....  
    4.    Mage::getModel('core/url_rewrite')->rewrite();  
    5.    ....  
    6.    while (!$request->isDispatched() && $i++<100) {  
    7.      foreach ($this->_routers as $router) {  
    8.         if ($router->match($this->getRequest())) {  
    9.           break;  
    10.         }  
    11.       }  
    12.    }  
    13.   
    14. }  



    3. Mage::getModel('core/url_rewrite')可以定位到Mage_Core_Model_Url_Rewrite类文件 

    Java代码  收藏代码
    1. class Mage_Core_Model_Url_Rewrite {  
    2.  public function rewrite() {  
    3.         $this->loadByRequestPath($requestCases);     
    4.         ......  
    5.         if (!$this->getId()) {  
    6.             // debug code  
    7.             var_dump($requestCases);  
    8.             exit();  
    9.   
    10.             return false;  
    11.         }  
    12.         ....  
    13.         $request->setPathInfo($this->getTargetPath());  
    14.         return true;  
    15.  }  
    16. }  



    如果 $this->loadByRequestPath($requestCases);从数据库中core_url_rewrite表查找是否有对应的target_path,如果找不到return false(用默认的rewrite机制),这里应该是可以找到targe path的,即 
    catalog/product/view/id/1/category/3 

    4. 继续回到dispatch()方法,代码 if ($router->match($this->getRequest()))中 
    $router 是Mage_Core_Controller_Varien_Router_Standard的实例,方法match如下: 

    Java代码  收藏代码
    1. public function match(Zend_Controller_Request_Http $request) {  
    2.    ....  
    3.     // set values only after all the checks are done  
    4.    $request->setModuleName($module);  
    5.   
    6.    $request->setControllerName($controller);  
    7.    $request->setActionName($action);  
    8. }  


    上面代码显而易见,到此代码分析结束。 

    结论:此次分析是推论+推测(瞎蒙,瞎蒙就是全文搜索匹配字符串确定调用和被调用关系),没有使用任何单步调式工具。 

    那么分析Rewrite机制对于扩展Magento的意义何在呢? 比如,如果你想为产品增加品牌分类,那么你可能需要定义如下的符合SEO的URL 
    http://localhost/magento/index.php/ibm/ 
    使之映射到 
    http://localhost/magento/index.php/catalog/brand/id/2 

    此时,你就要定义重写机制使两个URL的映射关系保存到数据库表中。 

    Flag Counter
  • 相关阅读:
    hdu4651(广义五边形数 & 分割函数1)
    Java基础面试题1
    Java8新特性--Lambda表达式
    Java中list在循环中删除元素的坑
    Java多线程面试题整理
    Java并发包--ConcurrentHashMap原理解析
    HashMap原理解析
    Java原子类--AtomicLongFieldUpdater
    Java原子类--AtomicReference
    Java原子类--AtomicLongArray
  • 原文地址:https://www.cnblogs.com/sunsoftware/p/3980662.html
Copyright © 2020-2023  润新知