在分析yii webapplication执行之前,我们先来看看yii的路由管理类CUrlManager,很多框架都有路由的功能,通常情况是将 controller和view的名称作为url的一部分传给入口程序,进而调用相应的controller和view进行处理,我们来分析一下yii是 如何完成这样的工作的。
关于UrlManager的使用,可以参考Yii官方文档:
(http://www.yiiframework.com/doc/guide/1.1/zh_cn/topics.url),先看一下这个component的初始化代码:
其中的rules是在配置文件中进行配置的,参考本文yii官方文档中的介绍,典型的配置文件形式如下,格式(pattern)必须是有效的正则表达式, 没有分隔符和修饰语。它是用于匹配网址的路径信息部分。还有route应指向一个有效的路线控制器(controllerID/actionID)。
'urlManager'=>array(
'urlFormat'=>'path',
'rules'=>array(
'pattern1'=>'route1',
'pattern2'=>'route2',
'pattern3'=>'route3',
),
),
rules的一个示例如下:
'pattern1'=>array('route1', 'urlSuffix'=>'.xml', 'caseSensitive'=>false)
yii的官方文档对此的解释如下:
• urlSuffix: 此规则使用的url后缀,默认使用CurlManger::urlSuffix,即为null。例如可以将此设置为.html,让url看起来“像”是一个静态页面。
• caseSensitive: 是否大小写敏感,默认使用CUrlManager::caseSensitive,即为null。
• defaultParams: 该规则使用的默认get参数。当使用该规则来解析一个请求时,这个参数的值会被注入到$_GET参数中。
• matchValue: 当创建一个URL时,GET参数是否匹配相应的子模式。默认使用CurlManager::matchValue,即为null。如果该属性为 false,那么意味着当路由和参数名匹配给定的规则时,将以此来创建一个URL。如果该属性为true,那么给定的参数值夜必须匹配相应的参数子模式。 注意:将此属性设置为true会降低性能。
那么,CUrlRule是如何实现url路由规则的呢?我们看一下CUrlRule的构造函数:
class CUrlRule extends CComponent
{
/**
* Constructor.
* @param string $route the route of the URL (controller/action)
* @param string $pattern the pattern for matching the URL
*/
public function __construct($route,$pattern)
{
if(is_array($route))
{
if(isset($route['urlSuffix']))
$this->urlSuffix=$route['urlSuffix'];
if(isset($route['caseSensitive']))
$this->caseSensitive=$route['caseSensitive'];
if(isset($route['defaultParams']))
$this->defaultParams=$route['defaultParams'];
if(isset($route['matchValue']))
$this->matchValue=$route['matchValue'];
$route=$this->route=$route[0];
}
else
$this->route=$route;
$tr2['/']=$tr['/']='\\/';
集装箱运费 if(strpos($route,'<')!==false && preg_match_all('/<(\w+)>/',$route,$matches2))
{
foreach($matches2[1] as $name)
$this->references[$name]="<$name>";
}
$this->hasHostInfo=!strncasecmp($pattern,'http://',7) || !strncasecmp($pattern,'https://',8);
if(preg_match_all('/<(\w+):?(.*?)?>/',$pattern,$matches))
{
$tokens=array_combine($matches[1],$matches[2]);
foreach($tokens as $name=>$value)
{
if($value==='')
$value='[^\/]+';
$tr["<$name>"]="(?P<$name>$value)";
if(isset($this->references[$name]))
$tr2["<$name>"]=$tr["<$name>"];
else
$this->params[$name]=$value;
}
赛尔号丽莎布布配招 }
$p=rtrim($pattern,'*');
$this->append=$p!==$pattern;
$p=trim($p,'/');
$this->template=preg_replace('/<(\w+):?.*?>/','<$1>',$p);
$this->pattern='/^'.strtr($this->template,$tr).'\/';
if($this->append)
$this->pattern.='/u';
else
$this->pattern.='$/u';
if($this->references!==array())
$this->routePattern='/^'.strtr($this->route,$tr2).'$/u';
if(YII_DEBUG && @preg_match($this->pattern,'test')===false)
throw new CException(Yii::t('yii','The URL pattern "{pattern}" for route "{route}" is not a valid regular expression.',
array('{route}'=>$route,'{pattern}'=>$pattern)));
}
/**
* Parses the user request.
* @param CHttpRequest $request the request application component
* @return string the route (controllerID/actionID) and perhaps GET parameters in path format.
*/
public function parseUrl($request)
{
if($this->getUrlFormat()===self::PATH_FORMAT)//如果是‘path’形式
{
$rawPathInfo=$request->getPathInfo();
$pathInfo=$this->removeUrlSuffix($rawPathInfo,$this->urlSuffix);
foreach($this->_rules as $rule)
{
if(($r=$rule->parseUrl($this,$request,$pathInfo,$rawPathInfo))!==false)
return isset($_GET[$this->routeVar]) ? $_GET[$this->routeVar] : $r;
}
if($this->useStrictParsing)
throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
array('{route}'=>$pathInfo)));
else
return $pathInfo;
}
else if(isset($_GET[$this->routeVar]))
return $_GET[$this->routeVar];
else if(isset($_POST[$this->routeVar]))
return $_POST[$this->routeVar];
else
return '';
}
}