joomla源代码探析续(二十五)JRequest对象的变量获取过程

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方式提交的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值