Website:Fast request router for PHPphp
`git
<?php class PregRoute { const NOT_FOUND = 404; const FOUND = 200; /** ~^/user/([^/]+)/(\d+)$~ * ~^/user/(\d+)$~ * ~^/user/([^/]+)$~ * @var string 單個正則 */ protected $single_regex = '~^/user/([^/]+)/(\d+)$~'; /** 基於位置匹配 * @var string 多個路由匹配規則 */ protected $combined_position_regex = " ~^(?: /user/([^/]+)/(\d+) | /user/(\d+) | /user/([^/]+) )$~x"; /** 位置匹配數據 * @var array */ protected $route_data_position = [ 1 => ['handler0', ['name', 'id']], # /user/tom/1 regex=> /user/([^/]+)/(\d+) 3 => ['handler1', ['id']], # /user/1 regex=> /user/(\d+) 4 => ['handler2', ['name']], # /user/tom regex=> /user/([^/]+) ]; /** 基於計數匹配 * @var string 多個路由匹配規則 */ protected $combined_count_regex = " ~^(?| /user/([^/]+)/(\d+) | /user/(\d+)()() | /user/([^/]+)()()() )$~x"; /** 基於計數匹配,只修改 ?: * @result 將 ?: 換成 ?| 能夠組號重置,但 * | /user/(\d+) * | /user/([^/]+) 的count都相同,採用()進行個數填充,也可使用其它方式,如 * <result1>/user/(\d+) * <result2>/user/([^/]+) * @var string */ protected $combined_count_regex2 = " ~^(?| /user/([^/]+)/(\d+) | /user/(\d+) | /user/([^/]+) )$~x"; /** 計數匹配數據 * @var array */ protected $route_data_count = [ 3 => ['handler0', ['name', 'id']], # /user/tom/1 regex=> /user/([^/]+)/(\d+) 4 => ['handler1', ['id']], # /user/1 regex=> /user/(\d+) 5 => ['handler2', ['name']], # /user/tom regex=> /user/([^/]+) ]; /** 塊正則表達式 * @var array */ protected $combined_count_regexes = []; /** 塊正則表達式數據 * @var array */ protected $route_data_counts = []; /** 基於位置調度路由 * @param $url * @way 基於組位置的非分塊 * @result 單個佔位符的狀況下提供了至關好的性能 * 佔位符過多,在最壞的狀況下(最後一條路線匹配),性能降低到比普通方法慢兩倍以上的程度 * @return array */ public function dispatchPosition($url) { if(!preg_match($this->combined_position_regex,$url,$matches)) { return [self::NOT_FOUND]; } //$i找到第一個非空偏移量並查找了相關數據後 //能夠經過繼續遍歷$matches數組並將值與變量名配對來填充佔位符變量。 for($i = 1; '' === $matches[$i]; ++$i); list($handler, $varNames) = $this->route_data_position[$i]; $vars = []; foreach ($varNames as $varName) { $vars[$varName] = $matches[$i++]; } return [self::FOUND, $handler, $vars]; } //++++++++++++++++++++++++++++++++++++++++ // 組號重置: // PCRE regex 語法: // (?| ... )是非捕獲組類型。 // (?:和之間的區別在於 ,(?|後者將重置其包含的每一個分支中的組號 //++++++++++++++++++++++++++++++++++++++++ /** 基於計數調度路由 * @param $url * @return array */ public function dispatchCount($url) { if(!preg_match($this->combined_count_regex,$url,$matches)) { return [self::NOT_FOUND]; } list($handler, $varNames) = $this->route_data_count[count($matches)]; $vars = []; $i = 0; foreach ($varNames as $varName) { $vars[$varName] = $matches[++$i]; } return [self::FOUND, $handler, $vars]; } /** 基於計數調度路由,非()佔位 * @param $url * @return array */ public function dispatchCount2($url) { if(!preg_match($this->combined_count_regex2,$url,$matches)) { return [self::NOT_FOUND]; } var_dump($matches); } /** 塊正則表達式調度 * @param $url * @return array */ public function dispatchBlock($url) { foreach ($this->combined_count_regexes as $i => $regex) { if (!preg_match($regex, $url, $matches)) { continue; } list($handler, $varNames) = $this->route_data_counts[$i][count($matches)]; $vars = []; $i = 0; foreach ($varNames as $varName) { $vars[$varName] = $matches[++$i]; } return [self::FOUND, $handler, $vars]; } } //+++++++++++++++++++++++++++++++++++++++++ //組合的正則表達式方法對於少許的正則表達式很是有效, //可是若是涉及許多正則表達式則不是最佳選擇,而若是每一個規則有多個捕獲組則則是災難性的。 //經過僅組合大約十個表達式的塊能夠提升性能。 //這不只能夠整體上提升性能,並且能夠解決多組狀況下性能特別差的問題。 //一旦開始使用分塊,基於組計數的替代方法就不會有太大的區別。 //捕獲組較少時,狀況稍差一些,而許多組則稍好一些。特別是對於路由,一般每條路由涉及多個佔位符,基於組計數的方法彷佛更可取。 //另外一方面,對於詞法分析,每一個標記一般僅使用一個捕獲組,所以基於位置的方法將獲勝。 //+++++++++++++++++++++++++++++++++++++++++ } $testClass = new PregRoute(); $url = '/user/tom'; #/user/1 | /user/tom/1 $dispatchPosition = $testClass->dispatchPosition($url); $dispatchCount = $testClass->dispatchCount($url); var_dump($dispatchPosition); var_dump($dispatchCount);
`github