Magento - Rewrite机制一窥
看一个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机制, 还着实费了不少力气,但是也只是懂些皮毛。下面说说我分析这个机制的过程:
仍然以访问
- 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,结果发现多处子对象有字符串属性包含它:
- Mage_Core_Controller_Request_Http
- ->_originalPathInfo = "/basketball/tayshaun-prince-signed-auto-baketball-with-coa-gold.html"
- ->_requestString = "/basketball/tayshaun-prince-signed-auto-baketball-with-coa-gold.html"
- ->_requestUri = "/magento/index.php/basketball/tayshaun-prince-signed-auto-baketball-with-coa-gold.html"
- ->_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,浏览了下整个函数内容,发现了如下代码
- $request->setModuleName($module);
- $request->setControllerName($controller);
- $request->setActionName($action);
由此可以猜测出,对于该例子,这里应该有如下的映射:
- $module = 'catalog';
- $controller = 'ProductController';
- $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()方法开始,程序员可以敏感地意识到下面代码的关键性
- Mage::run() {
- ...
- self::app()->getFrontController()->dispatch();
- ...
- }
2.打开Mage_Core_Controller_Varien_Front的 dispatch方法
- class Mage_Core_Controller_Varien_Front{
- function dispatch() {
- ....
- Mage::getModel('core/url_rewrite')->rewrite();
- ....
- while (!$request->isDispatched() && $i++<100) {
- foreach ($this->_routers as $router) {
- if ($router->match($this->getRequest())) {
- break;
- }
- }
- }
- }
3. Mage::getModel('core/url_rewrite')可以定位到Mage_Core_Model_Url_Rewrite类文件
- class Mage_Core_Model_Url_Rewrite {
- public function rewrite() {
- $this->loadByRequestPath($requestCases);
- ......
- if (!$this->getId()) {
- // debug code
- var_dump($requestCases);
- exit();
- return false;
- }
- ....
- $request->setPathInfo($this->getTargetPath());
- return true;
- }
- }
如果 $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如下:
- public function match(Zend_Controller_Request_Http $request) {
- ....
- // set values only after all the checks are done
- $request->setModuleName($module);
- $request->setControllerName($controller);
- $request->setActionName($action);
- }
上面代码显而易见,到此代码分析结束。
结论:此次分析是推论+推测(瞎蒙,瞎蒙就是全文搜索匹配字符串确定调用和被调用关系),没有使用任何单步调式工具。
那么分析Rewrite机制对于扩展Magento的意义何在呢? 比如,如果你想为产品增加品牌分类,那么你可能需要定义如下的符合SEO的URL
http://localhost/magento/index.php/ibm/
使之映射到
http://localhost/magento/index.php/catalog/brand/id/2
此时,你就要定义重写机制使两个URL的映射关系保存到数据库表中。
Magento - Rewrite机制一窥的更多相关文章
- 页面静态化3 --- 伪静态技术之Apache的rewrite机制
Apache的rewrite机制: 意思就是,你发送的地址,比如:http://localhost/news-id67.html会被Apache改写成http://localhost/news.p ...
- apache的rewrite机制
当我们使用thinkphp的时候,比如说我们访问一个Test控制器的test方法,http://localhost/index.php/Test/test/1.html,那个这个1是用get方式传递的 ...
- Magento事件机制 - Magento Event/Observer
为了扩展Magento的功能,我们可以重写Magento的代码,但因为代码只能被重写一次,所以当多个模块需要重写同一部分的代码时,就会引起冲突,好在Magento提供了另一种扩展功能的方法:事件机制, ...
- Magento 缓存机制简析
在知道缓存机制前,首先需要知道,Magento的路由机制,这边就不做赘述了,百度一大堆. 下面一个简单的缓存生效流程: A:首先在页面开始时,Magento在app\code\core\Mage\Co ...
- apache的rewrite机制配置
步骤: 1:启用rewrite模块,在默认情况下,没有启用 修改httpd.conf文件 #启动rewrite模块 LoadModule rewrite_module modules/mod_rewr ...
- 页面解耦—— 统跳协议和Rewrite引擎
原文: http://pingguohe.net/2015/11/24/Navigator-and-Rewrite.html 解耦神器 —— 统跳协议和Rewrite引擎 Nov 24, 2015 • ...
- Redis提供的持久化机制(二)
1.前言 Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服务器端计算集合的并,交和补集 ...
- redis持久化机制之AOF与RDB
什么是redis Redis是一种面向“key-value”类型数据的分布式NoSQL数据库系统,具有高性能.持久存储.适应高并发应用场景等优势.它虽然起步较晚,但发展却十分迅速. redis为何需要 ...
- Redis数据持久化机制AOF原理分析一---转
http://blog.csdn.net/acceptedxukai/article/details/18136903 http://blog.csdn.net/acceptedxukai/artic ...
随机推荐
- version `GLIBC_2.17' not found
@ 今天把一个linux程序布到线上服务器上时,运行不起来,下面是解决思路. @ 运行程序,报以下错误 root@iZ25uck2l28Z:/tmp/tmp# ./speed_test ./speed ...
- unserialize函数中的参数是否是污染数据
1.原理 在程序编写的时候,往往需要序列化一些运行时数据,所谓序列化就是按照一定的格式将运行时数据写入本地文件.这样做可以对数据进行本地保存,用的时候直接读文件就可以把运行时产生的数据读出.php中就 ...
- Acronis True Image Home 2011 PXE服务器配置_qxxz_新浪博客
想实现网络启动,并且Acronis启动菜单中带有Acronis True Image Home,需要安装以下软件: 1.安装Acronis True Image Home 2011及plush pac ...
- 《GK101任意波发生器》升级固件发布(版本:1.0.2build198)
一.固件说明: 硬件版本:0,logic.3 固件版本:1.0.2.build198 编译日期:2014-09-17 ====================================== 二. ...
- svchost.exe是什么?为什么一直在运行
原文:http://www.howtogeek.com/howto/windows-vista/what-is-svchostexe-and-why-is-it-running/ 自己简单翻译了下,图 ...
- 算法与数据结构题目的 PHP 实现:栈和队列 设计一个有 getMin 功能的栈
刚入手了一本<程序员代码面试指南>,书中题目的代码都是 Java 实现的,琢磨着把这些代码用 PHP 敲一遍,加深印象. 题目:设计一个有 getMin 功能的栈 —— 实现一个特殊的栈, ...
- Javascript 判断一个数字是否含有小数点
JavaScript 判断一个数字是否含有小数点,如果含有,则返回该数字:如果不含小数点,则小数点后保留两位有效数字: function hasDot(num){ if(!isNaN(num)){ r ...
- PHP 开发 APP 接口 学习笔记与总结 - Redis 缓存
Redis 可以定期将数据备份到磁盘中(持久化),同时不仅仅支持简单的key/value 类型的数据,同时还提供list,set,hash等数据结构的存储:Memcache 只是简单的key/valu ...
- PHP+jQuery 注册模块开发
/* ******* 环境: Apache2.2.8 + PHP5.2.6 + MySQL5.0.51b + jQuery-1.8.3.min.js ************** 其他组件:Zend_ ...
- PHP 随机显示
<?php print_r( array_rand( array( "新春快乐"=>"", " ...