一个简单的PHP Route
一个简单的PHP Route · Nov 6, 2013 clicks
写了一个简单的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 )