路由表初始化
從入口文件index.php
開始
首先Typecho_Widget::widget('Widget_Init');
跟進(jìn)發(fā)現(xiàn)在\var\Widget\Widget_Options::execute()
自動(dòng)初始化路由表
public function execute()
{
$this->db->fetchAll($this->db->select()->from('table.options')
->where('user = 0'), array($this, 'push'));
/* 從數(shù)據(jù)庫(kù)中取出架诞,其中有序列化的routeTable */
...
/** 自動(dòng)初始化路由表 */
$this->routingTable = unserialize($this->routingTable);
if (!isset($this->routingTable[0])) {
/** 解析路由并緩存 */
/*
不存在 this->routingTable[0] 時(shí),
通過路由解析器來(lái)構(gòu)造規(guī)則斜筐,并把其存入數(shù)據(jù)庫(kù)中
*/
$parser = new Typecho_Router_Parser($this->routingTable);
$parsedRoutingTable = $parser->parse();
$this->routingTable = array_merge(array($parsedRoutingTable), $this->routingTable);
$this->db->query($this->db->update('table.options')->rows(array('value' => serialize($this->routingTable)))
->where('name = ?', 'routingTable'));
}
}
image.png
初始化路由類調(diào)用Typecho_Router::setRoutes($options->routingTable);
得到所有的路由表
image.png
路由解析器
不存在 $this->routingTable[0]
時(shí)
可以促發(fā)Typecho_Router_Parser($this->routingTable);
,
至于啥時(shí)候不存在 $this->routingTable[0]
,有多種情況存在,可以全局搜索routingTable\[0\]
查看unset函數(shù)
接下來(lái)看\var\Typecho\Router\Parser.php
//先初始化
public function __construct(array $routingTable)
{
$this->_routingTable = $routingTable;
$this->_defaultRegx = array(
'string' => '(.%s)',
'char' => '([^/]%s)',
'digital'=> '([0-9]%s)',
'alpha' => '([_0-9a-zA-Z-]%s)',
'alphaslash' => '([_0-9a-zA-Z-/]%s)',
'split' => '((?:[^/]+/)%s[^/]+)',
);
}
//定義路由規(guī)則
public function parse()
{
$result = array();
foreach ($this->_routingTable as $key => $route) {
$this->_params = array();
$route['regx'] = preg_replace_callback("/%([^%]+)%/", array($this, '_match'),
preg_quote(str_replace(array('[', ']', ':'), array('%', '%', ' '), $route['url'])));
/** 處理斜線 */
$route['regx'] = rtrim($route['regx'], '/');
$route['regx'] = '|^' . $route['regx'] . '[/]?$|';
$route['format'] = preg_replace("/\[([^\]]+)\]/", "%s", $route['url']);
$route['params'] = $this->_params;
$result[$key] = $route;
}
return $result;
}
然后通過\var\Widget\Widget_Options::execute()
更新數(shù)據(jù)庫(kù)
路由分發(fā)
在index.php
里調(diào)用Typecho_Router::dispatch();
以http://..../index.php/archives/1/
為例
public static function dispatch()
{
/** 獲取PATHINFO */
$pathInfo = self::getPathInfo();
/*
$_routingTable 路由表在上述步驟中獲得
每個(gè)路由都有一個(gè)自己的路由規(guī)則 酿矢,$route['regx']
不滿足直接返回flase
*/
foreach (self::$_routingTable as $key => $route) {
if (preg_match($route['regx'], $pathInfo, $matches)) {
self::$current = $key;
try {
/** 載入?yún)?shù) */
$params = NULL;
if (!empty($route['params'])) {
unset($matches[0]);
$params = array_combine($route['params'], $matches);
}
/* $params = {'cid':'1'} */
$widget = Typecho_Widget::widget($route['widget'], NULL, $params);
/* 通過這條獲得文章內(nèi)容 */
if (isset($route['action'])) {
$widget->{$route['action']}();
}
/*
$route['action'] = 'render'
此步獲取模板
*/
Typecho_Response::callback();
return;
} catch (Exception $e) {
if (404 == $e->getCode()) {
Typecho_Widget::destory($route['widget']);
continue;
}
throw $e;
}
}
}