一个简单的PHP Route

一个简单的PHP Route · Nov 6, 2013 311 clicks

写了一个简单的PHP Route玩玩。

只有寥寥数行,实现最简单的功能

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
class Route{
    public static $rules = [];
    public static function addRule($uri,$rule,$defaults=[])
    {
        self::$rules[] = ['regex'=> self::compileRule($uri,$rule) , 'defaults'=>$defaults ];
    }
    public static function compileRule($uri,$rule)
    {
        $uri = str_replace(')', ')?', $uri);
        return  preg_replace_callback(
            "#<([^<>/\?]+)>#i",
            function ($matches) use ($rule){
                $name = $matches[1];
                return "(?P<{$name}>" . ( !empty($rule[$name]) ? $rule[$name] : '[^<>/]+') . ')';
            },
            $uri
        );
         
    }
    public static function parseUri($uri){
        foreach (self::$rules as $rule_setting) {
            if ( preg_match("#{$rule_setting['regex']}#i", $uri, $matches) ){
                $ret = $rule_setting['defaults'];
                foreach ($matches as $name => $value) {
                    $ret[$name] = $value;
                }
                return $ret;
            }
        }
        return NULL;
    }
}

一开始,第10行用的preg_match函数,而在后面的正则了用了/e修饰符, 在这种情况下,preg_match的第二个参数可以是一行php代码。

然而在PHP 5中,已经去掉了/e修饰符,所以只能用preg_match_callback函数了,再配合匿名函数,比以前用着更爽了。

 

下面是使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//example
Route::addRule(
    '<controller>/<action>(/<param>)',
    ['controller'=>'[a-z]+','action'=>'[a-z]+'],
    ['controller'=>'home','action'=>'index']
);
Route::addRule(
    'a_<param>.html',
    ['param'=>'[0-9]+'],
    ['controller'=>'article','action'=>'detail']
);
print_r(Route::parseUri('a_1234.html'));
print_r(Route::parseUri('find/me'));
print_r(Route::parseUri('find/somebody/tom'));

 

最后的输出结果:

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
Array
(
    [controller] => article
    [action] => detail
    [0] => a_1234.html
    [param] => 1234
    [1] => 1234
)
Array
(
    [controller] => find
    [action] => me
    [0] => find/me
    [1] => find
    [2] => me
)
Array
(
    [controller] => find
    [action] => somebody
    [0] => find/somebody/tom
    [1] => find
    [2] => somebody
    [3] => /tom
    [param] => tom
    [4] => tom
)
PHP