一个简单的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 ) |