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一样的方法:

  1. return array(
  2. 'routers' =>array(
  3. 'myFirstRouter' => array(
  4. 'blog/view(?:/(\d+)-(.+))\.html',
  5. array(
  6. 'id'   => '1',
  7. 'controller'  => 'default',
  8. 'action'  => 'index'
  9. ),
  10. array(
  11. 1 => 'id',
  12. 2 => 'name'
  13. ),
  14. 'blog/view/%d-%s.html'
  15. ),
  16. 'mySecondRouter' => array(
  17. 'blog(?:/(\d+)-(.+))\.html',
  18. array(
  19. 'id'   => '1',
  20. 'controller'  => 'default',
  21. 'action'  => 'index'
  22. ),
  23. array(
  24. 1 => 'id',
  25. 2 => 'name'
  26. ),
  27. 'blog/%d-%s.html'
  28. ),
  29. 'myThirdRouter' => array(
  30. '([a-z0-9]+)/([a-z0-9]+)',
  31. array(),
  32. array(
  33. 1 => 'controller',
  34. 2 => 'action'
  35. ),
  36. 'blog/%d-%s.html'
  37. )
  38. )
  39. );

复制代码

是一个二维数组,每一个值为一条路由规则。
其中第一项是正则表达式,第二项为:参数默认值(这里可以设置controller,action,及其它参数的默认值。)
第三项为:参数的对应关系,与第一项的正则表达里面匹配元素对应。
第四项用于生成链接时候使用的格式。如果没看明白,可以看ZF的Router一节。

先发改的My_Dispatcher_Regexp类的代码:

  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @package    Zend_Controller
  16. * @subpackage Router
  17. * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @version    $Id$
  19. * @license    http://framework.zend.com/license/new-bsd     New BSD License
  20. */
  21. // {{{ includes
  22. FLEA::loadClass('FLEA_Dispatcher_Simple');
  23. // }}}
  24. /**
  25. * My_Dispatcher_Regexp
  26. *
  27. * @package My_Dispatcher
  28. * @author tg8866
  29. * @version 0.01
  30. */
  31. class My_Dispatcher_Regexp extends FLEA_Dispatcher_Simple
  32. {
  33. /**
  34. * 保存路由信息的数组(二级数组)
  35. *
  36. * @var array
  37. */
  38. var $_routers;
  39. /**
  40. * 当前浏览页面的路由信息
  41. *
  42. * @var array (一维数组)
  43. */
  44. var $_curRouter;
  45. /**
  46. * 保存baseurl信息
  47. *
  48. * @var string
  49. */
  50. var $_baseUrl;
  51. /**
  52. * 保存requestURI信息
  53. *
  54. * @var string
  55. */
  56. var $_requestUri;
  57. /**
  58. * 可用的路径信息 不包括 子目录信息
  59. * 比如:http://localhost/index.php 是主页
  60. * 则 http://localhost/blog/view/123-abc.html
  61. * 的路径信息为: /blog/view/123-abc.html
  62. * @var unknown_type
  63. */
  64. var $_pathInfo;
  65. /**
  66. * 构造函数
  67. *
  68. * @param array $request
  69. *
  70. * @return My_Dispatcher_Regexp
  71. */
  72. function My_Dispatcher_Regexp(& $request)
  73. {
  74. parent::FLEA_Dispatcher_Simple($request);
  75. $this->loadRouters();
  76. if (! is_array($this->_routers)) return false;
  77. if (!$this->_pathInfo) $this->getPathInfo();
  78. foreach (array_reverse($this->_routers) as $router) {
  79. if (! is_array($router)) continue;
  80. if ($router[0] == '' || !is_string($router[0])) continue;
  81. $regexp = '#^' . $router[0]. '$#i';
  82. if (! isset($router[1])) $router[1] = array();
  83. if (! isset($router[2])) $router[2] = array();
  84. if ($args = $this->match($regexp, $this->_pathInfo, $router[1], $router[2])) {
  85. $this->_curRouter = $router;
  86. $data['controller'] = $args['controller'];
  87. $data['action'] = $args['action'];
  88. $_GET = array_merge($_GET, $args);
  89. break;
  90. }
  91. }
  92. $this->_request = $data;
  93. }
  94. /**
  95. * 载入路由数据信息
  96. *
  97. */
  98. function loadRouters() {
  99. static $routerLoaded;
  100. if ($routerLoaded) return;
  101. $routerLoaded = false;
  102. $routerConfig = FLEA::getAppInf('routerConfig');
  103. FLEA::loadAppInf($routerConfig);
  104. $this->_routers = FLEA::getAppInf('routers');
  105. $routerLoaded = true;
  106. }
  107. /**
  108. * 根据服务器环境不同,取得RequestUri信息
  109. *
  110. * @return unknown
  111. */
  112. function getRequestUri() {
  113. if ($this->_requestUri) return $this->_requestUri;
  114. if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // check this first so IIS will catch
  115. $requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
  116. } elseif (isset($_SERVER['REQUEST_URI'])) {
  117. $requestUri = $_SERVER['REQUEST_URI'];
  118. } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI
  119. $requestUri = $_SERVER['ORIG_PATH_INFO'];
  120. if (!empty($_SERVER['QUERY_STRING'])) {
  121. $requestUri .= '?' . $_SERVER['QUERY_STRING'];
  122. }
  123. } else {
  124. $requestUri = null;
  125. }
  126. $this->_requestUri = $requestUri;
  127. return $requestUri;
  128. }
  129. function getBaseUrl() {
  130. if ($this->_baseUrl) return $this->_baseUrl;
  131. $filename = basename($_SERVER['SCRIPT_FILENAME']);
  132. if (basename($_SERVER['SCRIPT_NAME']) === $filename) {
  133. $baseUrl = $_SERVER['SCRIPT_NAME'];
  134. } elseif (basename($_SERVER['PHP_SELF']) === $filename) {
  135. $baseUrl = $_SERVER['PHP_SELF'];
  136. } elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $filename) {
  137. $baseUrl = $_SERVER['ORIG_SCRIPT_NAME']; // 1and1 shared hosting compatibility
  138. } else {
  139. // Backtrack up the script_filename to find the portion matching
  140. // php_self
  141. $path    = $_SERVER['PHP_SELF'];
  142. $segs    = explode('/', trim($_SERVER['SCRIPT_FILENAME'], '/'));
  143. $segs    = array_reverse($segs);
  144. $index   = 0;
  145. $last    = count($segs);
  146. $baseUrl = '';
  147. do {
  148. $seg     = $segs[$index];
  149. $baseUrl = '/' . $seg . $baseUrl;
  150. ++$index;
  151. } while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos));
  152. }
  153. // Does the baseUrl have anything in common with the request_uri?
  154. $requestUri = $this->getRequestUri();
  155. if (0 === strpos($requestUri, $baseUrl)) {
  156. // full $baseUrl matches
  157. $this->_baseUrl = $baseUrl;
  158. return $this->_baseUrl;
  159. }
  160. if (0 === strpos($requestUri, dirname($baseUrl))) {
  161. // directory portion of $baseUrl matches
  162. $baseUrl = rtrim(dirname($baseUrl), '/');
  163. $this->_baseUrl = $baseUrl;
  164. return $this->_baseUrl;
  165. }
  166. if (!strpos($requestUri, basename($baseUrl))) {
  167. // no match whatsoever; set it blank
  168. $this->_baseUrl = '';
  169. return $this->_baseUrl;
  170. }
  171. // If using mod_rewrite or ISAPI_Rewrite strip the script filename
  172. // out of baseUrl. $pos !== 0 makes sure it is not matching a value
  173. // from PATH_INFO or QUERY_STRING
  174. if ((strlen($requestUri) >= strlen($baseUrl))
  175. && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0)))
  176. {
  177. $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
  178. }
  179. $baseUrl = rtrim($baseUrl, '/');
  180. $this->_baseUrl = $baseUrl;
  181. return $this->_baseUrl;
  182. }
  183. function getPathInfo () {
  184. $baseUrl = $this->getBaseUrl();
  185. if (null === ($requestUri = $this->getRequestUri())) {
  186. return null;
  187. }
  188. // Remove the query string from REQUEST_URI
  189. if ($pos = strpos($requestUri, '?')) {
  190. $requestUri = substr($requestUri, 0, $pos);
  191. }
  192. if ((null !== $baseUrl)
  193. && (false === ($pathInfo = substr($requestUri, strlen($baseUrl)))))
  194. {
  195. // If substr() returns false then PATH_INFO is set to an empty string
  196. $pathInfo = '';
  197. } elseif (null === $baseUrl) {
  198. $pathInfo = $requestUri;
  199. }
  200. $this->_pathInfo = $pathInfo;
  201. return $pathInfo;
  202. }
  203. /**
  204. * Matches a user submitted path with a previously defined route.
  205. * Assigns and returns an array of defaults on a successful match.
  206. *
  207. * @param string Path used to match against this routing map
  208. * @return array|false An array of assigned values or a false on a mismatch
  209. */
  210. function match($regex, $path, $defaults, $map)
  211. {
  212. $path = trim(urldecode($path), '/');
  213. $res = preg_match($regex, $path, $values);
  214. if ($res === 0) return false;
  215. foreach ($values as $i => $value) {
  216. if (!is_int($i) || $i === 0) {
  217. unset($values[$i]);
  218. }
  219. }
  220. $values = $this->_getMappedValues($map, $values);
  221. $defaults = $this->_getMappedValues($map, $defaults, false, true);
  222. $return = $values + $defaults;
  223. return $return;
  224. }
  225. /**
  226. * Maps numerically indexed array values to it's associative mapped counterpart.
  227. * Or vice versa. Uses user provided map array which consists of index => name
  228. * parameter mapping. If map is not found, it returns original array.
  229. *
  230. * Method strips destination type of keys form source array. Ie. if source array is
  231. * indexed numerically then every associative key will be stripped. Vice versa if reversed
  232. * is set to true.
  233. *
  234. * @param array Indexed or associative array of values to map
  235. * @param boolean False means translation of index to association. True means reverse.
  236. * @param boolean Should wrong type of keys be preserved or stripped.
  237. * @return array An array of mapped values
  238. */
  239. function _getMappedValues($map, $values, $reversed = false, $preserve = false)
  240. {
  241. if (count($map) == 0) {
  242. return $values;
  243. }
  244. $return = array();
  245. foreach ($values as $key => $value) {
  246. if (is_int($key) && !$reversed) {
  247. if (array_key_exists($key, $map)) {
  248. $index = $map[$key];
  249. } elseif (false === ($index = array_search($key, $map))) {
  250. $index = $key;
  251. }
  252. $return[$index] = $values[$key];
  253. } elseif ($reversed) {
  254. $index = (!is_int($key)) ? array_search($key, $map, true) : $key;
  255. if (false !== $index) {
  256. $return[$index] = $values[$key];
  257. }
  258. } elseif ($preserve) {
  259. $return[$key] = $value;
  260. }
  261. }
  262. return $return;
  263. }
  264. /**
  265. * Assembles a URL path defined by this route
  266. *
  267. * @param array An array of name (or index) and value pairs used as parameters
  268. * @return string Route path with user submitted parameters
  269. */
  270. function assemble($defaults, $map = array(), $reverse, $data = array())
  271. {
  272. if ($reverse === null) {
  273. return '构建网址失败!路由参数错误!';
  274. }
  275. $data = $this->_getMappedValues($map, $data, true, false);
  276. $data += $this->_getMappedValues($map, $defaults, true, false);
  277. //$data += $this->_values;
  278. ksort($data);
  279. $return = @vsprintf($reverse, $data);
  280. if ($return === false) {
  281. return '构建网址失败!';
  282. }
  283. return $return;
  284. }
  285. /**
  286. * 使用路由构建网址
  287. */
  288. function url($routerName, $urlOptions, $absolute) {
  289. $this->loadRouters();
  290. if (isset($this->_routers[$routerName])) $curRouter = $this->_routers[$routerName];
  291. elseif (isset($this->_curRouter)) $curRouter = $this->_curRouter;
  292. if (is_array($curRouter) && count($curRouter) == 4 && is_string($curRouter[3])) {
  293. $defaults = $curRouter[1];
  294. $map = $curRouter[2];
  295. $reverse = $curRouter[3];
  296. } else {
  297. return '构建网址失败!路由参数错误!';
  298. }
  299. if (is_array($map) && is_string($reverse))
  300. if (!$absolute) return $this->assemble($defaults, $map, $reverse, $urlOptions);
  301. else {
  302. if (!$this->_baseUrl) $this->getBaseUrl();
  303. return $this->_baseUrl . '/' .$this->assemble($defaults, $map, $reverse, $urlOptions);
  304. }
  305. }
  306. }

复制代码

这里要说一个比较好的自定义类的命名规则及文件放置位置。
在FLEA下面建一个My的目录里面放自已的类。比如My_Dispatcher_Regexp放在:
My/Dispatcher/Regexp.php

同时为方便写一个生成网址助手:
My_Helper_Router
My/Helper/Router.php
代码如下:

  1. <?php
  2. /**
  3. * 路由网址助手
  4. */
  5. function rurl($routerName, $urlOptions, $absolute = false) {
  6. $routerHelper =& FLEA::getSingleton('My_Dispatcher_Regexp');
  7. echo $routerHelper->url($routerName, $urlOptions, $absolute);
  8. }

复制代码

使用方法:
/* 修改默认的Dispatcher为自定义的Dispatcher类*/
FLEA::setAppInf('dispatcher','My_Dispatcher_Regexp');

/* 设置路由配置信息的文件位置*/
FLEA::setAppInf('routerConfig', './APP/config/router.php');

其它代码跟任何一个普通的例子一样。

controller里面代码如下:

  1. <?php
  2. class Controller_Default extends FLEA_Controller_Action
  3. {
  4. function actionIndex()
  5. {
  6. FLEA::loadFile('My_Helper_Router');
  7. include('APP/View/PostIndex.php');
  8. }
  9. }

复制代码

我们在view中用下面代码:

  1. <?php
  2. dump($_GET);
  3. rurl('myFirstRouter', array('id' => '33', 'name' => 'thename'));

复制代码

就可以看到$_GET得到正确的参数,
rurl也生成我们期望的网址:
blog/view/33-thename.html

绝对网址生成方法如下:

  1. rurl('myFirstRouter', array('id' => '33', 'name' => 'thename'),true);
  2. //将生成如下的网址:
  3. /other/fleaphp/test/blog/view/33-thename.html
  4. 如果没有使用apache的mod_rewrite功能生成的网址如下:
  5. /fleaphp/test/index.php/blog/view/33-thename.html

php url 调度相关推荐

  1. django 1.8 官方文档翻译: 3-1-1 URL调度器

    URL调度器 简洁.优雅的URL 模式在高质量的Web 应用中是一个非常重要的细节.Django 允许你任意设计你的URL,不受框架束缚. 不要求有.php 或.cgi,更不会要求类似0,2097,1 ...

  2. Django视图层:URL调度器、Django处理一个请求、URLconf在查找什么?URL:①path()路径、②路径转换器Path converter、③正则表达式组re_path()

    一.视图层The view layer Django 具有 "视图" 的概念,负责处理用户的请求并返回响应. 二.URL调度器URL dispatcher urlpattern:U ...

  3. php 5.2 模块路径,5.2 模块和操作

    # 模块和操作 [上一页](# "上一页")[下一页](# "下一页") ThinkPHP采用模块和操作的方式来执行,首先,用户的请求会通过入口文件生成一个应用 ...

  4. filter执行先后问题_Thinkphp5框架变量覆盖导致远程代码执行

    Thinkphp5.0.x框架对输入数据过滤不严,导致Request类成员存在变量覆盖问题,在一定情况下能导致远程代码执行漏洞. 介绍 Thinkphp框架官方提供核心版和完整版两种: 核心版因默认缺 ...

  5. thinkphp5.0生命周期

    2019独角兽企业重金招聘Python工程师标准>>> 1.入口文件 用户发起的请求都会经过应用的入口文件,通常是 public/index.php文件.当然,你也可以更改或者增加新 ...

  6. Thinkphp 源码分析

    Thinkphp 源码分析 ThinkPHP是国内非常火的一个轻量级框架,采用MVC模式,结构写的非常好,今天 大象 带大家走一下ThinkPHP框架系统运行流程,我将跟随ThinkPHP的执行进行代 ...

  7. jenkins rec 分析 cve-2018-1000861 分析

    0x01 Jenkins的动态路由解析 web.xml: 可以看到Jenkins将所有的请求交给org.kohsuke.stapler.Stapler来处理的,跟进看一下这个类中的service方法: ...

  8. ThinkPHP控制器

    ThinkPHP控制器Controller 1.什么是控制器 在MVC框架中,其核心就是C(Controller)控制器.主要用于接收用户请求,处理业务逻辑. 2.控制器的定义 在一个ThinkPHP ...

  9. 手把手教你搭建一个基于Java的分布式爬虫系统

    http://blog.51cto.com/xpleaf/2093952 1 概述 在不用爬虫框架的情况,经过多方学习,尝试实现了一个分布式爬虫系统,并且可以将数据保存到不同地方,类似MySQL.HB ...

最新文章

  1. phpstudy一个域名配置两个网站(一个是thinkphp5,一个是原生php)
  2. 打开eclipse出现an error has occurred.see the loh file
  3. 使用 C# 开发智能手机软件:推箱子(二十三)
  4. gsk meaning
  5. wince -- telnet登陆密码的取消
  6. 初学者适用的最新Java学习路线
  7. Java基础之equals和==的区别深入解析
  8. react leaflet_如何使用Leaflet在React中轻松构建地图应用
  9. SpringBoot 2 快速整合 | Hibernate Validator 数据校验
  10. Struts2教程7:上传任意多个文件
  11. 【优化算法】多目标蝗虫优化算法(MOGOA)【含Matlab源码 937期】
  12. 电脑微信双开 bat文件
  13. 你知道直方图都能干啥?
  14. eechart echarts-wordcloud 生成人物词云图 词云 词少、形状问题、 解决办法
  15. hdu 5887 herb gathering 搜索剪枝
  16. 信息系统项目管理师核心考点(六十四)信息安全基础知识重要概念
  17. 高中数学必修二空间向量及其运算(经典案例)
  18. 日常编程笔记 | 2022.10.1 | 归并排序_一无序列
  19. ARM和NEON指令
  20. Android之重写与重载

热门文章

  1. shell 获取ora报错信息_ORA-04030: 在尝试分配...字节(...)时进程内存不足的原因分析...
  2. maven安装_如何从官网下载Maven与安装Maven
  3. 一般项目中是如何调bug的 ------- 手把手带你体验整个流程
  4. QT键盘响应卡顿的解决方法
  5. 信息系统项目管理师考试资料
  6. 《系统集成项目管理工程师》必背100个知识点-23整体变更控制流程
  7. select设置默认文字,不出现在下拉框中
  8. SpringBoot+MyBatisPlus实现前端传递时间查询条件ajax请求后台并回显数据流程整理
  9. Tkinter的OptionMenu组件
  10. Tkinter的Text组件