热搜:NVER node 开发 php

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

2024-07-24 20:45:01
如何实现一个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 

             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

                             $_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 ;

         }     

     }