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 [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 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里面代码如下:
- <?php
- class Controller_Default extends FLEA_Controller_Action
- {
- function actionIndex()
- {
- FLEA::loadFile('My_Helper_Router');
- include('APP/View/PostIndex.php');
- }
- }
复制代码
我们在view中用下面代码:
- <?php
- 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
|