Joomla 1.5 RC3版本的SEF存在不少问题,前段时间架站的时候曾经仔细看过这部分,昨天做apache转向的时候,突然发现又都忘记了,再回忆一次,记录下来。
/index.php 中$mainframe->route(); 这一函数中实现了从URI中获取相关参数并填充到JRequest中,我们来看看这个函数的实现过程。
这个函数的代码清单如下:
function route()
{
// get the full request URI
$uri = clone(JURI::getInstance());
$router =& $this->getRouter();
$result = $router->parse($uri);
JRequest::set($result, 'get', false );
}
可以看到,首先克隆了一个JURI,然后$router->parse($uri),实现了uri的解析,返回的数组结果填充到了JRequest中。
先简略看一下 JURI::getInstance() ,代码在enviroment/uri.php中,这里略过了。代码大体的实际就是兼容了apache与IIS,组成完成的URL路径,传递给JURI的构造器,最终生成JURI对象作为返回结果。
接着我们来看看$result = $router->parse($uri) 实现了什么,以下是JRouterSite的parse函数的代码清单:
function parse(&$uri)
{
$vars = array();
// Get the path
$path = $uri->getPath();
//Remove the suffix
if($this->_mode == JROUTER_MODE_SEF)
{
// Get the application
$app =& JFactory::getApplication();
if($app->getCfg('sef_suffix') && !(substr($path, -9) == 'index.php' || substr($path, -1) == '/'))
{
if($suffix = pathinfo($path, PATHINFO_EXTENSION))
{
$path = str_replace('.'.$suffix, '', $path);
$vars['format'] = $suffix;
}
}
}
//Remove basepath
$path = substr_replace($path, '', 0, strlen(JURI::base(true)));
//Remove prefix
$path = str_replace('index.php', '', $path);
//Set the route
$uri->setPath(trim($path , '/'));
$vars += parent::parse($uri);
return $vars;
}
这段代码实际就是去掉了路径中的 index.php以及在SEF开启的状态下的后缀,并调用父类JRouter的parse函数。
JRouter的parse函数代码清单如下:
function parse(&$uri)
{
$vars = array();
// Process the parsed variables based on custom defined rules
$vars = $this->_processParseRules($uri);
// Parse RAW URL
if($this->_mode == JROUTER_MODE_RAW) {
$vars += $this->_parseRawRoute($uri);
}
// Parse SEF URL
if($this->_mode == JROUTER_MODE_SEF) {
$vars += $vars + $this->_parseSefRoute($uri);
}
return array_merge($this->getVars(), $vars);
}
我们来看看关键的两个函数,因为不会同时发生,我们只来看看 $this->_parseSefRoute($uri)函数。以下是JRouterSite的_parseSefRoute方法代码清单:
function _parseSefRoute(&$uri)
{
$vars = array();
$menu =& JSite::getMenu(true);
$route = $uri->getPath();
//Handle an empty URL (special case)
if(empty($route))
{
$item = $menu->getDefault();
//Set the information in the request
$vars = $item->query;
//Get the itemid
$vars['Itemid'] = $item->id;
// Set the active menu item
$menu->setActive($vars['Itemid']);
return $vars;
}
//Get the variables from the uri
$vars = $uri->getQuery(true);
/*
* Parse the application route
*/
if(substr($route, 0, 9) == 'component')
{
$segments = explode('/', $route);
$route = str_replace('component/'.$segments[1], '', $route);
$vars['option'] = 'com_'.$segments[1];
$vars['Itemid'] = null;
}
else
{
//Need to reverse the array (highest sublevels first)
$items = array_reverse($menu->getMenu());
foreach ($items as $item)
{
$lenght = strlen($item->route); //get the lenght of the route
if($lenght > 0 && strpos($route.'/', $item->route.'/') === 0 && $item->type != 'menulink')
{
$route = substr($route, $lenght);
$vars['Itemid'] = $item->id;
$vars['option'] = $item->component;
break;
}
}
}
// Set the active menu item
if ( isset($vars['Itemid']) ) {
$menu->setActive( $vars['Itemid'] );
}
//Set the variables
$this->setVars($vars);
/*
* Parse the component route
*/
if(!empty($route))
{
$segments = explode('/', $route);
array_shift($segments);
// Handle component route
$component = preg_replace('/[^A-Z0-9_\.-]/i', '', $this->_vars['option']);
// Use the component routing handler if it exists
$path = JPATH_BASE.DS.'components'.DS.$component.DS.'router.php';
if (file_exists($path) && count($segments))
{
//decode the route segments
$segments = $this->_decodeSegments($segments);
require_once $path;
$function = substr($component, 4).'ParseRoute';
$vars = $function($segments);
$this->setVars($vars);
}
}
else
{
//Set active menu item
if($item =& $menu->getActive()) {
$vars = $item->query;
}
}
return $vars;
}
这段代码比较长,不详细分析了,实际上首先做了菜单项的比较,然后接着调用$uri->getQuery(true)返回query中的所有名称/值对,接着在合适的条件下调用相应组件下的router.php中对应路径解析函数,比如对于content,就是com_content/router.php的ContentParseRoute函数,最终整个函数生成了包含option,view,layout等在内的散列数组并返回。
返回的数据经过merge后,返回给 JRequest::set($result, 'get', false )
至此全部的参数数值就写入到JRequest中了,注意这里只是 'get'方式传递的参数,不包括post方式提交的数据。
/index.php 中$mainframe->route(); 这一函数中实现了从URI中获取相关参数并填充到JRequest中,我们来看看这个函数的实现过程。
这个函数的代码清单如下:
function route()
{
// get the full request URI
$uri = clone(JURI::getInstance());
$router =& $this->getRouter();
$result = $router->parse($uri);
JRequest::set($result, 'get', false );
}
可以看到,首先克隆了一个JURI,然后$router->parse($uri),实现了uri的解析,返回的数组结果填充到了JRequest中。
先简略看一下 JURI::getInstance() ,代码在enviroment/uri.php中,这里略过了。代码大体的实际就是兼容了apache与IIS,组成完成的URL路径,传递给JURI的构造器,最终生成JURI对象作为返回结果。
接着我们来看看$result = $router->parse($uri) 实现了什么,以下是JRouterSite的parse函数的代码清单:
function parse(&$uri)
{
$vars = array();
// Get the path
$path = $uri->getPath();
//Remove the suffix
if($this->_mode == JROUTER_MODE_SEF)
{
// Get the application
$app =& JFactory::getApplication();
if($app->getCfg('sef_suffix') && !(substr($path, -9) == 'index.php' || substr($path, -1) == '/'))
{
if($suffix = pathinfo($path, PATHINFO_EXTENSION))
{
$path = str_replace('.'.$suffix, '', $path);
$vars['format'] = $suffix;
}
}
}
//Remove basepath
$path = substr_replace($path, '', 0, strlen(JURI::base(true)));
//Remove prefix
$path = str_replace('index.php', '', $path);
//Set the route
$uri->setPath(trim($path , '/'));
$vars += parent::parse($uri);
return $vars;
}
这段代码实际就是去掉了路径中的 index.php以及在SEF开启的状态下的后缀,并调用父类JRouter的parse函数。
JRouter的parse函数代码清单如下:
function parse(&$uri)
{
$vars = array();
// Process the parsed variables based on custom defined rules
$vars = $this->_processParseRules($uri);
// Parse RAW URL
if($this->_mode == JROUTER_MODE_RAW) {
$vars += $this->_parseRawRoute($uri);
}
// Parse SEF URL
if($this->_mode == JROUTER_MODE_SEF) {
$vars += $vars + $this->_parseSefRoute($uri);
}
return array_merge($this->getVars(), $vars);
}
我们来看看关键的两个函数,因为不会同时发生,我们只来看看 $this->_parseSefRoute($uri)函数。以下是JRouterSite的_parseSefRoute方法代码清单:
function _parseSefRoute(&$uri)
{
$vars = array();
$menu =& JSite::getMenu(true);
$route = $uri->getPath();
//Handle an empty URL (special case)
if(empty($route))
{
$item = $menu->getDefault();
//Set the information in the request
$vars = $item->query;
//Get the itemid
$vars['Itemid'] = $item->id;
// Set the active menu item
$menu->setActive($vars['Itemid']);
return $vars;
}
//Get the variables from the uri
$vars = $uri->getQuery(true);
/*
* Parse the application route
*/
if(substr($route, 0, 9) == 'component')
{
$segments = explode('/', $route);
$route = str_replace('component/'.$segments[1], '', $route);
$vars['option'] = 'com_'.$segments[1];
$vars['Itemid'] = null;
}
else
{
//Need to reverse the array (highest sublevels first)
$items = array_reverse($menu->getMenu());
foreach ($items as $item)
{
$lenght = strlen($item->route); //get the lenght of the route
if($lenght > 0 && strpos($route.'/', $item->route.'/') === 0 && $item->type != 'menulink')
{
$route = substr($route, $lenght);
$vars['Itemid'] = $item->id;
$vars['option'] = $item->component;
break;
}
}
}
// Set the active menu item
if ( isset($vars['Itemid']) ) {
$menu->setActive( $vars['Itemid'] );
}
//Set the variables
$this->setVars($vars);
/*
* Parse the component route
*/
if(!empty($route))
{
$segments = explode('/', $route);
array_shift($segments);
// Handle component route
$component = preg_replace('/[^A-Z0-9_\.-]/i', '', $this->_vars['option']);
// Use the component routing handler if it exists
$path = JPATH_BASE.DS.'components'.DS.$component.DS.'router.php';
if (file_exists($path) && count($segments))
{
//decode the route segments
$segments = $this->_decodeSegments($segments);
require_once $path;
$function = substr($component, 4).'ParseRoute';
$vars = $function($segments);
$this->setVars($vars);
}
}
else
{
//Set active menu item
if($item =& $menu->getActive()) {
$vars = $item->query;
}
}
return $vars;
}
这段代码比较长,不详细分析了,实际上首先做了菜单项的比较,然后接着调用$uri->getQuery(true)返回query中的所有名称/值对,接着在合适的条件下调用相应组件下的router.php中对应路径解析函数,比如对于content,就是com_content/router.php的ContentParseRoute函数,最终整个函数生成了包含option,view,layout等在内的散列数组并返回。
返回的数据经过merge后,返回给 JRequest::set($result, 'get', false )
至此全部的参数数值就写入到JRequest中了,注意这里只是 'get'方式传递的参数,不包括post方式提交的数据。
发表评论
-
joomla 模块modules开发教程
2010-05-12 14:16 2754模块是页面扩展轻量级方式,相对组件更为灵活。模块通常用来做页面 ... -
joomla 1.5——JDocument类用法
2010-04-22 14:46 1343文档类,提供一个容易 ... -
[翻译] Joomla XML 解析器规范 上
2010-04-22 14:45 1037概述 Joomla! 1.5 新增 JSimpleXML 类 ... -
Joomla插件开发规范
2010-04-22 14:44 1374概述:JPlugin Joomla 1.5的新功能 为了更好 ... -
joomla源代码探析续(三十一) JHTML 类常用的方法
2010-04-22 14:37 1706我曾经在几篇文章中涉及到JHTML的方法使用,这里不再说了,请 ... -
joomla源代码探析续(三十) JDate类参考
2010-04-22 14:36 1033JDate类与JString类一样是Joomla!中的基础类, ... -
joomla源代码探析续(二十九) JHTML 与JHTMLSelect 类的使用
2010-04-22 14:33 1164我们在form表单生成的过程中,经常需要有select 标签或 ... -
joomla源代码探析续(二十八) 如何扩展JTable类
2010-04-22 14:30 1021JTable类是Active Record设计模式(web应用 ... -
joomla源代码探析续(二十七)组件后台如何设置参数
2010-04-22 14:29 884以下的方法可以在管理后台中添加一个Parameters设置的按 ... -
joomla源代码探析续(二十六)JUser对象和用户权限判断
2010-04-22 14:23 1820每一个访问Joomla网站的用户都对应这一个JUser对象,通 ... -
joomla源代码探析续(二十四)JPagination类
2010-04-22 14:22 1091JPagination类是Joomla的通用分页功能的封装类, ... -
Joomla源代码解析(二十二) 模块是如何被调用执行并渲染(下)
2010-04-22 14:16 923上一文章中提到了getBuffer函数,在函数中实际上调用了r ... -
模块是如何被调用执行并渲染?
2010-04-22 14:12 809以前的文章中,关于/index.php我们已经分析完了 $ma ... -
Joomla源代码解析(二十) MVC组件的执行
2010-04-22 14:10 899以前的文章中,我们曾经说过 $mainframework-&g ... -
Joomla源代码解析(十九) JController
2010-04-22 14:05 862同样 JController 是MVC中重要的起点,正式这个类 ... -
Joomla源代码解析(十八) Jview
2010-04-22 14:03 927MVC模式中,重要的一环,JView 和 tmpl目录中的模板 ... -
Joomla源代码解析(十六) JTable是什么 不指定
2010-04-22 14:01 1426JTable是什么? JTable是数据库中数据表在程序中的表 ... -
Joomla源代码解析(十五) 组件是如何被调用并渲染的
2010-04-22 14:00 1407Joomla代码中, 组件是如 ... -
Joomla源代码解析(十四) JRequest类 不指定
2010-04-22 13:58 838这是另一个Joomla扩展中最常用的类,这个类封装了客户端提交 ... -
Joomla源代码解析(十三) JText类
2010-04-22 11:25 1188Joomla 最常用的类之一,使用方式JTEXT::_('JJ ...
相关推荐
joomla源代码探析,比较详细阐述了joomla框架
joomla 组件 开发 详解 (附带源代码) joomla 组件 开发 详解 (附带源代码) joomla 组件 开发 详解 (附带源代码)
Joomla模板,用于本地测试安装
joomlaQQ登录、微信登录等第三方登录等经验解析
比较详细的分析joomla1.5源码。可以对应着源码一起学习
joomla漏洞利用代码,影响版本joomla1.5-3.4.最开始检测到利用该漏洞实施入侵的是 Securi 安全团队
joomla代码分析 对于二次开发有帮助 喜欢的可以下
joomla 免费企业模版,精美模版
您可以在这里免费获得joomla资料,您也可以分享您的joomla心得,方便发大家互相学习。聚集Joomla爱好者,彻底改变Joomla在中国发展的面貌。我们的目标是让全世界最优秀的CMS系统—Joomla真正的走向中国,为Joomla在...
joomla表结构介绍 joomla表结构介绍 joomla表结构介绍 joomla表结构介绍 joomla表结构介绍 joomla表结构介绍 joomla表结构介绍 joomla表结构介绍 joomla表结构介绍 joomla表结构介绍 joomla表结构介绍 joomla表结构...
joomla模板仿制教程第二集,基础入门教程
Joomla CSS JS代码压缩插件 Joomla2.5 Joomla 3X可用
joomla
五步法创建Joomla框架模板,快速学会Joomla搭建网站
joomla七牛插件,加速网站的速度。系统会自动将你网站的静态内容同步到你的七牛空间,让你的Joomla网站飞起来!
Joomla! A User's Guide: Building a Successful Joomla! Powered Website中文版。 入门书籍。网友翻译。 关于本书 对于Joomla! 这个流行的、屡获大奖的开源CMS,本教程会教你用Joomla按你自己需求一步一步,最终...
对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步...
zmax程序人 将Joomla1.5版本的模板移植到Joomla2.5上的经验总结
Building.Websites.with.Joomla1.5 & joomla 1.5建站宝典 第一单元:术语,概念,和审议 joomla 1.5安装方法 第三单元 前台内容 第三单元 前台内容? 第三单元 后台 Joomla 管理配置! 帮助菜单 网站菜单 用户管理器...
joomla 标签云模块,使用于joomla!1.5,浏览器需要安装flash插件才可正常显示。