看一个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机制, 还着实费了不少力气,但是也只是懂些皮毛。下面说说我分析这个机制的过程:

仍然以访问

  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,结果发现多处子对象有字符串属性包含它:

  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,浏览了下整个函数内容,发现了如下代码

  1. $request->setModuleName($module);
  2. $request->setControllerName($controller);
  3. $request->setActionName($action);

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

  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()方法开始,程序员可以敏感地意识到下面代码的关键性

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

2.打开Mage_Core_Controller_Varien_Front的 dispatch方法

  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. }

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

  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. return false;
  10. }
  11. ....
  12. $request->setPathInfo($this->getTargetPath());
  13. return true;
  14. }
  15. }

如果 $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如下:

  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. $request->setControllerName($controller);
  6. $request->setActionName($action);
  7. }

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

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

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

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

Magento - Rewrite机制一窥的更多相关文章

  1. 页面静态化3 --- 伪静态技术之Apache的rewrite机制

      Apache的rewrite机制: 意思就是,你发送的地址,比如:http://localhost/news-id67.html会被Apache改写成http://localhost/news.p ...

  2. apache的rewrite机制

    当我们使用thinkphp的时候,比如说我们访问一个Test控制器的test方法,http://localhost/index.php/Test/test/1.html,那个这个1是用get方式传递的 ...

  3. Magento事件机制 - Magento Event/Observer

    为了扩展Magento的功能,我们可以重写Magento的代码,但因为代码只能被重写一次,所以当多个模块需要重写同一部分的代码时,就会引起冲突,好在Magento提供了另一种扩展功能的方法:事件机制, ...

  4. Magento 缓存机制简析

    在知道缓存机制前,首先需要知道,Magento的路由机制,这边就不做赘述了,百度一大堆. 下面一个简单的缓存生效流程: A:首先在页面开始时,Magento在app\code\core\Mage\Co ...

  5. apache的rewrite机制配置

    步骤: 1:启用rewrite模块,在默认情况下,没有启用 修改httpd.conf文件 #启动rewrite模块 LoadModule rewrite_module modules/mod_rewr ...

  6. 页面解耦—— 统跳协议和Rewrite引擎

    原文: http://pingguohe.net/2015/11/24/Navigator-and-Rewrite.html 解耦神器 —— 统跳协议和Rewrite引擎 Nov 24, 2015 • ...

  7. Redis提供的持久化机制(二)

    1.前言 Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服务器端计算集合的并,交和补集 ...

  8. redis持久化机制之AOF与RDB

    什么是redis Redis是一种面向“key-value”类型数据的分布式NoSQL数据库系统,具有高性能.持久存储.适应高并发应用场景等优势.它虽然起步较晚,但发展却十分迅速. redis为何需要 ...

  9. Redis数据持久化机制AOF原理分析一---转

    http://blog.csdn.net/acceptedxukai/article/details/18136903 http://blog.csdn.net/acceptedxukai/artic ...

随机推荐

  1. 仿windows8 开始菜单 实现HubTileBase 以及仿鲜果联播实现 PulsingTile(脉冲磁贴)

    http://blog.csdn.net/wangrenzhu2011/article/details/8750820 (转) 本文章将以如何实现 开始菜单上的tile 为主. 该控件代码经过测试可直 ...

  2. 二分查找算法java实现

    今天看了一下JDK里面的二分法是实现,觉得有点小问题.二分法的实现有多种今天就给大家分享两种.一种是递归方式的,一种是非递归方式的.先来看看一些基础的东西. 1.算法概念. 二分查找算法也称为折半搜索 ...

  3. 微博开发平台java SDK demo学习之friendships

    本文解释了在java SDK的demo中与feiendships有关的功能 截图如下: 关注一个用户(需要知道该用户uid) 取消关注一个用户(用户uid) 获取用户粉丝列表(授权用户的screen_ ...

  4. 使用安捷伦波形编辑软件产生GK101 任意波数据文件的方法(支持手绘)

    软件安装包下载地址: 链接: http://pan.baidu.com/s/1bn8Lmhx 密码: v5xz 一.安捷伦IO套件安装 1.将压缩包解压,首先双击IOLibSuite_16_3_179 ...

  5. 【液晶模块系列基础视频】1.1.iHMI43模块介绍

    [液晶模块系列基础视频]1.1.iHMI43模块介绍(上) [液晶模块系列基础视频]1.1.iHMI43模块介绍(下) ============================== 技术论坛:http ...

  6. 连连看beta发布

    组名:天天向上 组长:王森 组员:张政.张金生.林莉.胡丽娜 代码地址:HTTPS:https://git.coding.net/jx8zjs/llk.git SSH:git@git.coding.n ...

  7. NV SDK 9.5, 10 and 11

    NVIDIA SDK 10   Overview This all-new collection of DirectX 10 and OpenGL code samples teaches devel ...

  8. Web 在线文件管理器学习笔记与总结(6)jQuery UI 预览图片

    ① 查看文件内容,如果文件是图片类型,点击直接查看图片: ② 如果不是图片类型,显示文件中的内容: ③ 使用 jQuery UI 中的 Dialog 显示图片 a.引入: <script src ...

  9. RT-Thread的线程间同步

    禁止系统调度上一节< 多线程导致的临界区问题>中由于 test1 线程被 test2 线程打断,才导致了我们没有得到预期的结果,我们一般可通过关闭中断和调度器上锁这两种简单的途径来禁止系统 ...

  10. PHP文件操作 之读取一个文件(以二进制只读的方式打开)

    最近应用了文件的读取,顺便复习一下! //读取一个文件 $f = fopen($filename,'rb'); $f: 表示返回的一个资源句柄 $filename:要打开的文件路径 rb:参数,表示只 ...