一个简单的PHP Route
一个简单的PHP Route · November 6, 2013 views: 118
写了一个简单的PHP Route玩玩。
只有寥寥数行,实现最简单的功能
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函数了,再配合匿名函数,比以前用着更爽了。
下面是使用示例:
//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'));
最后的输出结果:
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
)