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

直接通过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路由管理)