本文從源碼層面分析 Zend Framework 路由機制:Apache mod_rewrite → 前端控制器分發 → 路由器逆序匹配 → 參數注入請求物件的完整鏈路,並深度解讀 Zend_Controller_Router_Route 構造與匹配算法。
mod_rewrite 將請求導向 index.php。Zend_Controller_Front::dispatch() 分發請求。Zend_Controller_Router_Rewrite::route() 按加入順序逆序(後進先出)遍歷路由規則,調用 match() 匹配。$_currentRoute,解析參數注入 Zend_Controller_Request_Http。IndexController::indexAction()。public function __construct($route, $defaults=array(), $reqs=array()) {
$route = trim($route, $this->_urlDelimiter);
$this->_defaults = (array)$defaults;
$this->_requirements = (array)$reqs;
if ($route != '') {
foreach (explode($this->_urlDelimiter, $route) as $pos=>$part) {
if (substr($part,0,1) == $this->_urlVariable) { // 變量
$name = substr($part,1);
$regex = isset($reqs[$name]) ? $reqs[$name] : $this->_defaultRegex;
$this->_parts[$pos] = array('name'=>$name, 'regex'=>$regex);
$this->_vars[] = $name;
} else { // 靜態字符串
$this->_parts[$pos] = array('regex'=>$part);
if ($part != '*') $this->_staticCount++;
}
}
}
}
核心屬性:_parts(規則分段)、_vars(變量名列表)、_staticCount(靜態段計數)。
public function match($path) {
$path = trim($path, $this->_urlDelimiter);
$unique = array_combine(array_keys($this->_defaults), array_fill(0, count($this->_defaults), true));
if ($path != '') {
$path = explode($this->_urlDelimiter, $path);
foreach ($path as $pos=>$pathPart) {
if (!isset($this->_parts[$pos])) return false; // 路徑段超出規則
if ($this->_parts[$pos]['regex'] == '*') { // 通配符
$this->_getWildcardData(array_slice($path,$pos), $unique);
break;
}
$part = $this->_parts[$pos];
$name = isset($part['name']) ? $part['name'] : null;
$pathPart = urldecode($pathPart);
if ($name === null) { // 靜態段
if ($part['regex'] != $pathPart) return false;
$pathStaticCount++;
} elseif ($part['regex'] === null) { // 無正則變量
if (strlen($pathPart) == 0) return false;
} else { // 有正則變量
$regex = $this->_regexDelimiter . '^' . $part['regex'] . '$' . $this->_regexDelimiter . 'iu';
if (!preg_match($regex, $pathPart)) return false;
}
if ($name !== null) {
$this->_values[$name] = $pathPart;
$unique[$name] = true;
}
}
}
// 合併:路徑解析值 + 通配符值 + 默認值(後者不覆蓋前者)
$return = $this->_values + $this->_params + $this->_defaults;
// 靜態段全部匹配
if ($this->_staticCount != $pathStaticCount) return false;
// 所有定義變量必須出現
foreach ($this->_vars as $var) if (!array_key_exists($var, $return)) return false;
return $return;
}
+ 運算符合併參數,保證路徑解析值優先於默認值。* 支援動態「鍵/值」對傳遞。更多 Zend 相關技術請參考專題:《Zend Framework 入門教程》、《PHP 優秀開發框架總結》、《Yii 框架入門及常用技巧總結》、《ThinkPHP 入門教程》、《PHP 面向對象程序設計入門教程》、《PHP+MySQL 數據庫操作入門教程》及《PHP 常見數據庫操作技巧匯總》。