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'? ?),? ?array(? ? 1 => 'id',? ? 2 => 'name'? ?),? ?'blog/view/%d-%s.html'??),??'mySecondRouter' => array(? ?'blog(?:/(\d+)-(.+))\.html',? ?array(? ? 'id'? ?=> '1',? ? 'controller'??=> 'default',? ? 'action'??=> 'index'? ?),? ?array(? ? 1 => 'id',? ? 2 => 'name'? ?),? ?'blog/%d-%s.html'??),??'myThirdRouter' => array(? ?'([a-z0-9]+)/([a-z0-9]+)',? ?array(),? ?array(? ? 1 => 'controller',? ? 2 => 'action'? ?),? ?'blog/%d-%s.html'??)??)); 復制代碼 是一個二維數組,每一個值為一條路由規則。 其中第一項是正則表達式,第二項為:參數默認值(這里可以設置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 license@zend.com 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*/// {{{ includesFLEA::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 string? ???*/? ? 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? ?? ???} else {? ?? ?? ?? ?// 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), '/');? ?? ?? ?? ?$this->_baseUrl = $baseUrl;? ?? ?? ?? ?return $this->_baseUrl;? ?? ???}? ?? ???if (!strpos($requestUri, basename($baseUrl))) {? ?? ?? ?? ?// no match whatsoever; set it blank? ?? ?? ?? ?$this->_baseUrl = '';? ?? ?? ?? ?return $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;? ?? ?? ?? ?}? ?? ???}? ?? ???return $return;? ? }? ? /**? ???* 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 '構建網址失敗!';??? ?? ???}? ?? ???return $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 代碼如下: <?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里面代碼如下: <?phpclass Controller_Default extends FLEA_Controller_Action{function actionIndex(){FLEA::loadFile('My_Helper_Router');include('APP/View/PostIndex.php');}} 復制代碼 我們在view中用下面代碼: <?phpdump($_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 |