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 2800模块是页面扩展轻量级方式,相对组件更为灵活。模块通常用来做页面 ... -
joomla 1.5——JDocument类用法
2010-04-22 14:46 1391文档类,提供一个容易 ... -
[翻译] Joomla XML 解析器规范 上
2010-04-22 14:45 1079概述 Joomla! 1.5 新增 JSimpleXML 类 ... -
Joomla插件开发规范
2010-04-22 14:44 1407概述:JPlugin Joomla 1.5的新功能 为了更好 ... -
joomla源代码探析续(三十一) JHTML 类常用的方法
2010-04-22 14:37 1740我曾经在几篇文章中涉及到JHTML的方法使用,这里不再说了,请 ... -
joomla源代码探析续(三十) JDate类参考
2010-04-22 14:36 1082JDate类与JString类一样是Joomla!中的基础类, ... -
joomla源代码探析续(二十九) JHTML 与JHTMLSelect 类的使用
2010-04-22 14:33 1207我们在form表单生成的过程中,经常需要有select 标签或 ... -
joomla源代码探析续(二十八) 如何扩展JTable类
2010-04-22 14:30 1063JTable类是Active Record设计模式(web应用 ... -
joomla源代码探析续(二十七)组件后台如何设置参数
2010-04-22 14:29 927以下的方法可以在管理后台中添加一个Parameters设置的按 ... -
joomla源代码探析续(二十六)JUser对象和用户权限判断
2010-04-22 14:23 1862每一个访问Joomla网站的用户都对应这一个JUser对象,通 ... -
joomla源代码探析续(二十四)JPagination类
2010-04-22 14:22 1126JPagination类是Joomla的通用分页功能的封装类, ... -
Joomla源代码解析(二十二) 模块是如何被调用执行并渲染(下)
2010-04-22 14:16 952上一文章中提到了getBuffer函数,在函数中实际上调用了r ... -
模块是如何被调用执行并渲染?
2010-04-22 14:12 852以前的文章中,关于/index.php我们已经分析完了 $ma ... -
Joomla源代码解析(二十) MVC组件的执行
2010-04-22 14:10 926以前的文章中,我们曾经说过 $mainframework-&g ... -
Joomla源代码解析(十九) JController
2010-04-22 14:05 893同样 JController 是MVC中重要的起点,正式这个类 ... -
Joomla源代码解析(十八) Jview
2010-04-22 14:03 971MVC模式中,重要的一环,JView 和 tmpl目录中的模板 ... -
Joomla源代码解析(十六) JTable是什么 不指定
2010-04-22 14:01 1460JTable是什么? JTable是数据库中数据表在程序中的表 ... -
Joomla源代码解析(十五) 组件是如何被调用并渲染的
2010-04-22 14:00 1443Joomla代码中, 组件是如 ... -
Joomla源代码解析(十四) JRequest类 不指定
2010-04-22 13:58 864这是另一个Joomla扩展中最常用的类,这个类封装了客户端提交 ... -
Joomla源代码解析(十三) JText类
2010-04-22 11:25 1224Joomla 最常用的类之一,使用方式JTEXT::_('JJ ...
相关推荐
**Joomla 2.5.16 源代码详解** Joomla,作为一个开源的内容管理系统(CMS),在网站开发领域有着广泛的应用。Joomla 2.5.16 是该系统的一个版本,提供了丰富的功能和易用性,适用于构建各种类型的网站,包括企业...
本篇将深入探讨Joomla组件开发的详细过程,并结合源代码进行解析。 一、Joomla组件概述 在Joomla中,组件是最大的功能单元,它由多个部分组成,包括模型、视图、控制器、模板和语言文件等。组件开发涉及以下几个...
### Joomla第三方登录开发详解 #### 一、概述 在当今互联网时代,为了提高用户体验和方便用户登录,许多网站都引入了第三方登录功能。对于使用Joomla构建的网站来说,实现第三方登录同样非常重要。本文将详细介绍...
9. **博客平台和CMS**:除了从头编写源代码,许多人也会选择使用WordPress、Joomla或Ghost等博客平台或内容管理系统,它们提供丰富的主题和插件,使得非程序员也能轻松搭建和管理博客。 10. **性能优化**:通过压缩...
总结来说,Joomla的代码分析是一个涵盖广泛的过程,涉及对MVC架构的理解、组件和模块的开发、数据库交互以及模板设计等多个方面。通过深入研究和实践,开发者可以充分利用Joomla的开放源代码特性,实现各种定制化...
比较详细的分析joomla1.5源码。可以对应着源码一起学习
Joomla API 中文手册是针对Joomla!框架的重要参考资料,由aivera倾力创作,填补了国内关于Joomla! API中文文档的空白。Joomla!框架是一个强大的内容管理系统(CMS)开发平台,其API提供了丰富的功能,方便开发者进行...
Joomla是一种开源的内容管理系统(CMS),它以其强大的功能和易用性在全球范围内受到广泛的欢迎。然而,尽管Joomla被公认为世界上最优秀的CMS之一,但在中国的普及和发展却面临着一些挑战。 首先,Joomla在中国的...
【Joomla模板仿制教程第二集】是一门针对初学者的基础入门课程,旨在教会学员如何在Joomla内容管理系统中创建和定制自己的模板。Joomla是一个流行的开源CMS平台,以其灵活性和丰富的功能闻名,广泛用于构建各种类型...
这些变量可以直接访问,以便获取关于Joomla系统的具体信息。 除了`JVersion`,`JFactory` 类是另一个重要的API组件,它是一个全局工厂类,用于创建Joomla框架中的其他核心对象,如权限管理、缓存管理和数据库操作等...
joomla漏洞利用代码,影响版本joomla1.5-3.4.最开始检测到利用该漏洞实施入侵的是 Securi 安全团队
### Joomla使用的API详解 ...通过以上介绍,我们可以看到`JVersion`类提供了获取Joomla版本信息的强大功能,而`JFactory`类则为创建和管理框架对象提供了便利。这两种类在Joomla的二次开发中具有极其重要的作用。
**Joomla 免费企业模板详解** Joomla 是一款开源的内容管理系统(CMS),它允许用户构建网站和在线应用程序,而无需深入的编程知识。在本文中,我们将详细探讨"Joomla 免费企业模板"这一主题,分析这些模板如何帮助...
3. **LICENSE.txt**: 这个文件包含了Joomla的许可协议,Joomla遵循GNU General Public License v2或更高版本,这意味着你可以自由地使用、修改和分发Joomla源代码,但需遵守其中的版权和开源规定。 4. **README.txt...
源代码的分析和理解对于想要深入研究网站开发或者计划使用Joomla!构建网站的人来说非常重要。通过掌握Joomla!的架构和功能,开发者能够更高效地利用这一强大的工具,创建出满足需求的网站。同时,持续关注和学习新...
- **MVC(Model-View-Controller)架构**:这是一种常见的软件设计模式,主要用于简化开发过程并提高代码可维护性。在Joomla中,它被广泛应用于组件开发。 - **Joomla中的MVC实现**:涉及到三个核心类: - **...
本文将聚焦于Joomla框架中的关键API——`Jversion`和`JFactory`,深入探讨这两个API的使用场景、方法及变量,旨在帮助开发者更好地掌握Joomla的核心机制。 #### Joomla框架的版本信息:`Jversion`类详解 `Jversion...