直接通过url参数访问业务模块($app)中控制器($ctl)里的函数($act)

我们支持3种路由模式

普通模式

_a=$app,     _u=$ctl.$act

最简单的方式,专注实现业务$act函数,不需要再写额外代码

为什么参数名前面要加下划线就不解释了

easy模式

_easy=$app.$tpl.$ctl.$act

_easy=$app.$ctl.$act

在web开发中,通常我们在$act中输出一个前端页面,

easy模式下,如果未实现$act处理函数,会自动寻找并显示对应的前端模板文件。

对于简单的展示页面适合使用这种路由模式

   url重写模式(需要nginx或apache配置) 

apache: ^rewrite[\.\/](.*)$ /index.php?_rewrite=$1  [R,QSA]

nginx:  rewrite ^/rewrite[\.\/](.*)$ /index.php?_rewrite=$1 last;

rewrite.{$app}.{$ctl}.{$act}.{$params}.html

或更加优雅的目录式访问方式

rewrite/{$app}/{$ctl}/{$act}/{$params}.html

其中$params为选填参数部分.格式为urlencode后的参数列表

如果想传递sp_uid=1&d=1.2&p=sb, 那么$params = sp_uid%3D1%26d%3D1.2%26p%3Ds%2Fb

或sp_uid/1/d/1.2/p/sb

在某些要求url中不能带?&特殊字符的场景下可以使用这种模式

1. 为了能通过qq oauth2登陆验证,需要配置重写规则

rewrite.thirdlogin.index.qqcallback.sp_uid%3D1.php

2. 资源静态化

rewrite.upload.index.out.uidm%3D310ef4b.png

3. 支付回调

rewrite.pay.weixin.native2_notify.php

4. 微信开放平台授权回调

rewrite/web/component/message/_app_id/xxxxxxx.php

部分实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
    $a = (!empty($_REQUEST['_a']) && is_string($_REQUEST['_a'])) ? $_REQUEST['_a'] : 'web';
    if (!preg_match('/^[\w\.]+$/'$a)) {
        exit('invalid _app name! ' . htmlspecialchars($a));
    }   
    $GLOBALS['_UCT']['APP'] = !empty($a) ? strtolower($a) : 'web';
        
    $u = (!empty($_REQUEST['_u']) && is_string($_REQUEST['_u'])) ? $_REQUEST['_u'] : 'index.index';
    if (!preg_match('/^[\w\.]+$/'$u)) {
        exit('invalid _url name! ' . htmlspecialchars($u));
    }   
    $u                      explode('.'$u, 2); 
    $GLOBALS['_UCT']['CTL'] = !empty($u['0']) ? strtolower($u['0']) : 'index';
    $GLOBALS['_UCT']['ACT'] = !empty($u['1']) ? strtolower($u['1']) : 'index';

easy模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    //easy 模式直接访问模板tpl
    if (!empty($_REQUEST['_easy']) && is_string($_REQUEST['_easy'])) {
        $easy explode('.'$_REQUEST['_easy']);
        switch (count($easy)) {
            case 4:
                $_GET['_u'] = $_REQUEST['_u'] = $easy[2] . '.' $easy[3];
                if (preg_match('/^[\w\.]+$/'$easy[1])) {
                    $GLOBALS['_UCT']['TPL'] = $easy[1];
                }
                $_GET['_a'] = $_REQUEST['_a'] = $easy[0];
                break;
            case 3:
                $_GET['_u'] = $_REQUEST['_u'] = $easy[1] . '.' $easy[2];
                $_GET['_a'] = $_REQUEST['_a'] = $easy[0];
                break;
            case 2:
                $_GET['_u'] = $_REQUEST['_u'] = $easy[1];
                $_GET['_a'] = $_REQUEST['_a'] = $easy[0];
                break;
            case 1:
                $_GET['_a'] = $_REQUEST['_a'] = $easy[0];
                break;
            default:
                exit('invalid _easy param! ' . htmlspecialchars($_REQUEST['_easy']));
        }
    }

rewrite模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    //url重写模式
    if (!empty($_REQUEST['_rewrite']) && is_string($_REQUEST['_rewrite'])) {
        //1.支持apache 重写模式下?后的参数缺失的情况 
        if(stripos($_SERVER['SERVER_SOFTWARE'], 'nginx') === false) {
            $_REQUEST['_rewrite'] = urldecode(substr($_SERVER['QUERY_STRING'], strlen('_rewrite=')));
        }
        //2. 丢弃_rewrite中的后缀名
        $rewrite substr($_REQUEST['_rewrite'], 0, strrpos($_REQUEST['_rewrite'], '.'));
 
        //3. 支持/作为分隔符
        $sp '.';
        for($i = 0; $i strlen($rewrite); $i++) {
            if(in_array($rewrite[$i], array('.''/'))) {
                $sp $rewrite[$i];
                break;
            }
        }
        $rewrite explode($sp$rewrite, 4);
        //最后1段是必填后缀名
        switch(count($rewrite)) {
            case 3:
            case 4: {
                $_GET['_a'] = $_REQUEST['_a'] = $rewrite[0];
                $_GET['_u'] = $_REQUEST['_u'] = $rewrite[1].'.'.$rewrite[2];
                if(!empty($rewrite[3])) {
                    if(strpos($rewrite[3], '/')) {
                        $params explode('/'$rewrite[3]);
                        for($i=0; $i+1<count($params); $i+=2) {
                            $_REQUEST[urldecode($params[$i])] = urldecode($params[$i+1]);
                        }   
                    }   
                    else {
                        foreach(explode('&'$rewrite[3]) as $p) {
                            list($k$v) = explode('='$p, 2);  
                            $_REQUEST[urldecode($k)] = urldecode($v);
                        }   
                    }   
                }   
                break;
            }   
            case 2:
                $_GET['_a'] = $_REQUEST['_a'] = $rewrite[0];
                $_GET['_u'] = $_REQUEST['_u'] = $rewrite[1];
                break;
            case 1: 
                $_GET['_a'] = $_REQUEST['_a'] = $rewrite[0];
                break;
            default:
                break;
        }     
    }

如何实现一个php框架系列文章【4】url路由管理的更多相关文章

  1. 如何实现一个php框架系列文章【开篇】

    1.本系列文章的目的 实现一个小而美的产品级别php框架 自己动手实现一个新框架仅用于学习交流,不打算替代市面上现有的其他主流框架. 2. 我要一个怎样的PHP框架 简单实用,安全优雅,博采众长 安装 ...

  2. 如何实现一个php框架系列文章【5】安全处理输入

    所有的外部输入参数都应该检查合法性. 未正确处理输入数据将可能导致sql注入等漏洞. 框架提供系列函数来取$_REQUEST中的值 requestInt requestString requestFl ...

  3. 如何实现一个php框架系列文章【1】如何组织文件

    1. 组织文件布局应该考虑什么问题 前后端分离 各业务模块分离但方便互相调用 上传文件安全性 方便接入第三方类库 如图所示 框架入口文件 uct/index.php 框架目录         uct/ ...

  4. 如何实现一个php框架系列文章【6】mysql数据库

    实现一个mysql数据库封装需要考虑的问题 使用方便性 采用直接sql语句操作方式.只要会写sql语句,那么将没有其他学习成本. uctphp框架提供的dba辅助封装类,用会之后将爱不释手. 使用前需 ...

  5. 如何实现一个php框架系列文章【2】实现类的自动加载

    根据前一篇文章的设计原则,我们暂时把php文件分为3类,类名和文件名都遵守如下约定.   类名 文件名 路径 模型类m {$app}Mod  {$app}.mod.php {$app}/model   ...

  6. 如何实现一个php框架系列文章【3】支持psr4的自动加载类

    psr4自动加载规范https://github.com/PizzaLiu/PHP-FIG/blob/master/PSR-4-autoloader-cn.md 我们把第三方使用psr规范的类库放在v ...

  7. 2019 年起如何开始学习 ABP 框架系列文章-开篇有益

    2019 年起如何开始学习 ABP 框架系列文章-开篇有益 [[TOC]] 本系列文章推荐阅读地址为:52ABP 开发文档 https://www.52abp.com/Wiki/52abp/lates ...

  8. Artech的MVC4框架学习——第二章URL路由

    总结:HttpModule 和HttpHandler是Asp.net管道的两个重要组件.请求最终处理通过HttpHandler完成.MVC就是通过名为MvcHandler自定义HttpHandler现 ...

  9. 【开源】EFW框架系列文章索引

    开源轻量级.Net框架EnterpriseFrameWork详解 ——自己动手写框架 ——适合中小企业的开发框架 ——Ajax+JqueryEasyUI+NotNetBar+MVC+WebServic ...

随机推荐

  1. TFS 测试用例步骤数据统计

    TFS系统集成了一套BI系统,基于SQL Server的Analysis Service进行实现的.通过这几年的深入使用,能够感触到这个数据数据仓库模型是多么的优秀,和微软官方提供的数据仓库示例Adv ...

  2. Lind.DDD.LindMQ的一些想法

    回到目录 很久就想写一套属于自己的消息队列组件,前段时候看了汤雪华同学的EQueue,感觉还是不错的,他也是看了rabbitMQ之后写的Equeue,在设计上与前者有类似的地方,而大叔这次准备写一个L ...

  3. oracle常用函数及示例

    学习oracle也有一段时间了,发现oracle中的函数好多,对于做后台的程序猿来说,大把大把的时间还要学习很多其他的新东西,再把这些函数也都记住是不太现实的,所以总结了一下oracle中的一些常用函 ...

  4. closure

    什么是闭包?百度的答案: 闭包是指可以包含自由(未绑定到特定对象)变量的代码块:这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)."闭包&quo ...

  5. 【C#】获取网页内容及HTML解析器HtmlAgilityPack的使用

    最近经常需要下载一些东西,而这个下载地址又会经过层层跳转,每个页面上都有很多广告,烦不胜烦,所以做了一个一键获得最终下载地址的小工具.使用C#,来获取网页内容,然后通过HtmlAgilityPack获 ...

  6. Aop动态生成代理类时支持带参数构造函数

    一.背景 在某些情况下,我们需要植入AOP代码的类并没有默认构造函数.那么此时动态生成的代理类也需要相同签名的构造函数,并且内部调用原始类的构造函数.自己折腾了1晚上没搞定,现在搞定了发出来供大家一起 ...

  7. mysql 外键约束备注

    梳理mysql外键约束的知识点. 1.mysql外键约束只对InnoDb引擎有效: 2.创建外键约束如下: DROP TABLE IF EXISTS t_demo_product; CREATE TA ...

  8. 通过easyui tab添加的子页面JS脚本必须放在body才生效

    通过easyui tab添加的子页面JS脚本必须放在body才生效 可通过Chrome查看元素时,head标签是否含有你自己写的JS代码

  9. 解析大型.NET ERP系统 通用附件管理功能

    大型系统具备一个通用的附件管理功能,对于单据中无法清晰表达的字段,用一个附件图片或附件文档表示是最好的方法了.比如物料清单附加一张CAD图纸,销售订单评审功能中附加客户的各种表格,通用附件功能对系统起 ...

  10. 设计C/S架构应用程序的并发功能

    C/S架构的ERP.CRM程序有的是以并发点(Concurrency)来销售,并发点是指同时在线人数.并发数量大时,理论上程序的运行速度会慢,软件供应商(vendor)也以控制并发的上限以解决客户对系 ...