1, 支援非rewrite即:
http://localhost/index.php/blog/view/5456-asdf.html
也可以被正确解析。。
-----------------------------------
2,增加:絕對位址生成 隻要
rurl('myFirstRouter', array('id' => '33', 'name' => 'thename'), true);
最後多加一個true,預設為false即相對位址。
生成絕對位址如:網站根目錄/fleaphp/test/blog/view/33-thename.html
修改自ZendFramework的Router_Regexp類。
花了點時間整理的,水準有限,希望有高人能完善一下。
定義一個路由跟定義DSN一樣的方法:
return array(
'routers' =>array(
'myFirstRouter' => array(
'blog/view(?:/(\d+)-(.+))\.html',
array(
'id' => '1',
'controller' => 'default',
'action' => 'index'
),
1 => 'id',
2 => 'name'
'blog/view/%d-%s.html'
),
'mySecondRouter' => array(
'blog(?:/(\d+)-(.+))\.html',
'blog/%d-%s.html'
'myThirdRouter' => array(
'([a-z0-9]+)/([a-z0-9]+)',
array(),
1 => 'controller',
2 => 'action'
)
)
);
複制代碼
是一個二維數組,每一個值為一條路由規則。
其中第一項是正規表達式,第二項為:參數預設值(這裡可以設定controller,action,及其它參數的預設值。)
第三項為:參數的對應關系,與第一項的正則表達裡面比對元素對應。
第四項用于生成連結時候使用的格式。如果沒看明白,可以看ZF的Router一節。
先發改的My_Dispatcher_Regexp類的代碼:
<?php
/**
* Zend Framework
*
* LICENSE
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
* @package Zend_Controller
* @subpackage Router
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
* @version $Id$
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
// {{{ includes
FLEA::loadClass('FLEA_Dispatcher_Simple');
// }}}
* My_Dispatcher_Regexp
* @package My_Dispatcher
* @author tg8866
* @version 0.01
class My_Dispatcher_Regexp extends FLEA_Dispatcher_Simple
{
/**
* 儲存路由資訊的數組(二級數組)
*
* @var array
*/
var $_routers;
* 目前浏覽頁面的路由資訊
* @var array (一維數組)
var $_curRouter;
* 儲存baseurl資訊
* @var string
var $_baseUrl;
* 儲存requestURI資訊
var $_requestUri;
* 可用的路徑資訊 不包括 子目錄資訊
* 比如:http://localhost/index.php 是首頁
* 則 http://localhost/blog/view/123-abc.html
* 的路徑資訊為: /blog/view/123-abc.html
* @var unknown_type
var $_pathInfo;
* 構造函數
* @param array $request
* @return My_Dispatcher_Regexp
function My_Dispatcher_Regexp(& $request)
{
parent::FLEA_Dispatcher_Simple($request);
$this->loadRouters();
if (! is_array($this->_routers)) return false;
if (!$this->_pathInfo) $this->getPathInfo();
foreach (array_reverse($this->_routers) as $router) {
if (! is_array($router)) continue;
if ($router[0] == '' || !is_string($router[0])) continue;
$regexp = '#^' . $router[0]. '$#i';
if (! isset($router[1])) $router[1] = array();
if (! isset($router[2])) $router[2] = array();
if ($args = $this->match($regexp, $this->_pathInfo, $router[1], $router[2])) {
$this->_curRouter = $router;
$data['controller'] = $args['controller'];
$data['action'] = $args['action'];
$_GET = array_merge($_GET, $args);
break;
}
}
$this->_request = $data;
}
* 載入路由資料資訊
function loadRouters() {
static $routerLoaded;
if ($routerLoaded) return;
$routerLoaded = false;
$routerConfig = FLEA::getAppInf('routerConfig');
FLEA::loadAppInf($routerConfig);
$this->_routers = FLEA::getAppInf('routers');
$routerLoaded = true;
* 根據伺服器環境不同,取得RequestUri資訊
* @return unknown
function getRequestUri() {
if ($this->_requestUri) return $this->_requestUri;
if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // check this first so IIS will catch
$requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
} elseif (isset($_SERVER['REQUEST_URI'])) {
$requestUri = $_SERVER['REQUEST_URI'];
} elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI
$requestUri = $_SERVER['ORIG_PATH_INFO'];
if (!empty($_SERVER['QUERY_STRING'])) {
$requestUri .= '?' . $_SERVER['QUERY_STRING'];
}
} else {
$requestUri = null;
$this->_requestUri = $requestUri;
return $requestUri;
function getBaseUrl() {
if ($this->_baseUrl) return $this->_baseUrl;
$filename = basename($_SERVER['SCRIPT_FILENAME']);
if (basename($_SERVER['SCRIPT_NAME']) === $filename) {
$baseUrl = $_SERVER['SCRIPT_NAME'];
} elseif (basename($_SERVER['PHP_SELF']) === $filename) {
$baseUrl = $_SERVER['PHP_SELF'];
} elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $filename) {
$baseUrl = $_SERVER['ORIG_SCRIPT_NAME']; // 1and1 shared hosting compatibility
// Backtrack up the script_filename to find the portion matching
// php_self
$path = $_SERVER['PHP_SELF'];
$segs = explode('/', trim($_SERVER['SCRIPT_FILENAME'], '/'));
$segs = array_reverse($segs);
$index = 0;
$last = count($segs);
$baseUrl = '';
do {
$seg = $segs[$index];
$baseUrl = '/' . $seg . $baseUrl;
++$index;
} while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos));
// Does the baseUrl have anything in common with the request_uri?
$requestUri = $this->getRequestUri();
if (0 === strpos($requestUri, $baseUrl)) {
// full $baseUrl matches
$this->_baseUrl = $baseUrl;
return $this->_baseUrl;
if (0 === strpos($requestUri, dirname($baseUrl))) {
// directory portion of $baseUrl matches
$baseUrl = rtrim(dirname($baseUrl), '/');
if (!strpos($requestUri, basename($baseUrl))) {
// no match whatsoever; set it blank
$this->_baseUrl = '';
// If using mod_rewrite or ISAPI_Rewrite strip the script filename
// out of baseUrl. $pos !== 0 makes sure it is not matching a value
// from PATH_INFO or QUERY_STRING
if ((strlen($requestUri) >= strlen($baseUrl))
&& ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0)))
{
$baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
$baseUrl = rtrim($baseUrl, '/');
$this->_baseUrl = $baseUrl;
return $this->_baseUrl;
function getPathInfo () {
$baseUrl = $this->getBaseUrl();
if (null === ($requestUri = $this->getRequestUri())) {
return null;
// Remove the query string from REQUEST_URI
if ($pos = strpos($requestUri, '?')) {
$requestUri = substr($requestUri, 0, $pos);
if ((null !== $baseUrl)
&& (false === ($pathInfo = substr($requestUri, strlen($baseUrl)))))
// If substr() returns false then PATH_INFO is set to an empty string
$pathInfo = '';
} elseif (null === $baseUrl) {
$pathInfo = $requestUri;
$this->_pathInfo = $pathInfo;
return $pathInfo;
* Matches a user submitted path with a previously defined route.
* Assigns and returns an array of defaults on a successful match.
* @param string Path used to match against this routing map
* @return array|false An array of assigned values or a false on a mismatch
function match($regex, $path, $defaults, $map)
$path = trim(urldecode($path), '/');
$res = preg_match($regex, $path, $values);
if ($res === 0) return false;
foreach ($values as $i => $value) {
if (!is_int($i) || $i === 0) {
unset($values[$i]);
$values = $this->_getMappedValues($map, $values);
$defaults = $this->_getMappedValues($map, $defaults, false, true);
$return = $values + $defaults;
return $return;
* Maps numerically indexed array values to it's associative mapped counterpart.
* Or vice versa. Uses user provided map array which consists of index => name
* parameter mapping. If map is not found, it returns original array.
* Method strips destination type of keys form source array. Ie. if source array is
* indexed numerically then every associative key will be stripped. Vice versa if reversed
* is set to true.
* @param array Indexed or associative array of values to map
* @param boolean False means translation of index to association. True means reverse.
* @param boolean Should wrong type of keys be preserved or stripped.
* @return array An array of mapped values
function _getMappedValues($map, $values, $reversed = false, $preserve = false)
if (count($map) == 0) {
return $values;
$return = array();
foreach ($values as $key => $value) {
if (is_int($key) && !$reversed) {
if (array_key_exists($key, $map)) {
$index = $map[$key];
} elseif (false === ($index = array_search($key, $map))) {
$index = $key;
}
$return[$index] = $values[$key];
} elseif ($reversed) {
$index = (!is_int($key)) ? array_search($key, $map, true) : $key;
if (false !== $index) {
$return[$index] = $values[$key];
} elseif ($preserve) {
$return[$key] = $value;
* Assembles a URL path defined by this route
* @param array An array of name (or index) and value pairs used as parameters
* @return string Route path with user submitted parameters
function assemble($defaults, $map = array(), $reverse, $data = array())
if ($reverse === null) {
return '建構網址失敗!路由參數錯誤!';
}
$data = $this->_getMappedValues($map, $data, true, false);
$data += $this->_getMappedValues($map, $defaults, true, false);
//$data += $this->_values;
ksort($data);
$return = @vsprintf($reverse, $data);
if ($return === false) {
return '建構網址失敗!';
* 使用路由建構網址
function url($routerName, $urlOptions, $absolute) {
$this->loadRouters();
if (isset($this->_routers[$routerName])) $curRouter = $this->_routers[$routerName];
elseif (isset($this->_curRouter)) $curRouter = $this->_curRouter;
if (is_array($curRouter) && count($curRouter) == 4 && is_string($curRouter[3])) {
$defaults = $curRouter[1];
$map = $curRouter[2];
$reverse = $curRouter[3];
} else {
return '建構網址失敗!路由參數錯誤!';
}
if (is_array($map) && is_string($reverse))
if (!$absolute) return $this->assemble($defaults, $map, $reverse, $urlOptions);
else {
if (!$this->_baseUrl) $this->getBaseUrl();
return $this->_baseUrl . '/' .$this->assemble($defaults, $map, $reverse, $urlOptions);
}
}
這裡要說一個比較好的自定義類的命名規則及檔案放置位置。
在FLEA下面建一個My的目錄裡面放自已的類。比如My_Dispatcher_Regexp放在:
My/Dispatcher/Regexp.php
同時為友善寫一個生成網址助手:
My_Helper_Router
My/Helper/Router.php
代碼如下:
* 路由網址助手
function rurl($routerName, $urlOptions, $absolute = false) {
$routerHelper =& FLEA::getSingleton('My_Dispatcher_Regexp');
echo $routerHelper->url($routerName, $urlOptions, $absolute);
使用方法:
/* 修改預設的Dispatcher為自定義的Dispatcher類*/
FLEA::setAppInf('dispatcher','My_Dispatcher_Regexp');
/* 設定路由配置資訊的檔案位置*/
FLEA::setAppInf('routerConfig', './APP/config/router.php');
其它代碼跟任何一個普通的例子一樣。
controller裡面代碼如下:
class Controller_Default extends FLEA_Controller_Action
function actionIndex()
FLEA::loadFile('My_Helper_Router');
include('APP/View/PostIndex.php');
我們在view中用下面代碼:
dump($_GET);
rurl('myFirstRouter', array('id' => '33', 'name' => 'thename'));
就可以看到$_GET得到正确的參數,
rurl也生成我們期望的網址:
blog/view/33-thename.html
絕對網址生成方法如下:
rurl('myFirstRouter', array('id' => '33', 'name' => 'thename'),true);
//将生成如下的網址:
/other/fleaphp/test/blog/view/33-thename.html
如果沒有使用apache的mod_rewrite功能生成的網址如下:
/fleaphp/test/index.php/blog/view/33-thename.html