clean(); } /** * 清理middleware和路由规则 * * @return void */ public function clean() { $this->prefix = ''; $this->middleware = []; $this->route = [ 'GET' => [], 'POST' => [], 'DELETE' => [], 'PUT' => [], 'HEAD' => [], 'ANY' => [] ]; } /** * 实例化Route * @return mixed|object|string|null */ public static function getInstance() { return \Qii::getInstance("Qii\Base\Route"); } /** * 设置路由规则 * * @param array $route * @return void */ public function setRoute($route){ if (!is_array($route) && !in_array($route, $this->route)) { $this->route[] = $route; } $this->route = array_merge($this->route, $route); } /** * 设置URL前缀 * * @param string $name * @return mixed|object|string|null */ public static function prefix($name) { $route = self::getInstance(); $route->clean(); $route->prefix = $name; return $route; } /** * 设置中间件 * @param array|string $middleware * @return $this */ public function setMiddleware($middleware) { if(!is_array($middleware)) { $this->middleware[] = $middleware; }else{ $this->middleware = array_merge($this->middleware, $middleware); } return $this; } public function gatherMiddleware(){ return array_unique($this->middleware); } public function group($callable) { $route = \Qii::getInstance("Qii\Base\Route"); call_user_func($callable, $route); $this->stored[] = [$route->middleware, $route->route]; return $this; } public function get($uri, $callable){ $uri = $this->appendPrefix($this->prefix, $uri); $this->route['GET'][] = [$uri, $callable]; return $this; } public function post($uri, $callable) { $uri = $this->appendPrefix($this->prefix, $uri); $this->route['POST'][] = [$uri, $callable]; return $this; } /** * 补充前缀 * @param string $prefix 前缀 * @param string $uri uri * @return mixed|string */ protected function appendPrefix($prefix, $uri){ if(!$prefix) { return $uri; } return $prefix . '/'. ltrim($uri, '/');; } public function put($uri, $callable) { $uri = $this->appendPrefix($this->prefix, $uri); $this->route['PUT'][] = [$uri, $callable]; return $this; } public function delete($uri, $callable) { $uri = $this->appendPrefix($this->prefix, $uri); $this->route['DELETE'][] = [$uri, $callable]; return $this; } public function any($uri, $callable) { $uri = $this->appendPrefix($this->prefix, $uri); $this->route['ANY'][] = [$uri, $callable]; return $this; } /** * 匹配路由并执行 * * @param $request * @return bool */ public function match(Http $request, $next) { $route = $this->getStoredRoute(); $method = strtoupper($request->getMethod()); $uri = $request->getRequestUri(); $middleware = []; $callable = ''; foreach ($route as $item) { $middleware = $item[0]; $subRoute = $item[1]; if(!isset($subRoute[$method]) && !isset($subRoute['ANY'])) { continue; } $subRoute['ANY'] = isset($subRoute['ANY']) ? (array) $subRoute['ANY'] : array(); $subRoute[$method] = isset($subRoute[$method]) ? (array) $subRoute[$method] : array(); $routes = array_merge($subRoute[$method], $subRoute['ANY']); $callable = ''; $args = null; foreach ($routes as $routeUri) { //启用正则匹配 if($this->enableExpress) { list($route, $args) = $this->parse($uri, $routeUri); if($route) { if(is_array($args)) { //将$args的值设置到get参数里 foreach ($args as $key => $value) { $request->set($key, $value); } } $callable = $route[1]; break; } } if ($uri == $routeUri[0]) { $callable = $routeUri[1]; break; } } if ($callable) { break; } } if (!$callable || count($middleware) == 0) { return $next($request); } //命中后,执行相应程序后就不往下执行 $middleware = array_reverse(array_unique($middleware)); $result = array_reduce($middleware, function ($carry, $item){ return function () use ($carry, $item){ return _loadClass($item)->handle(\Qii::getInstance()->request, $carry); }; }, function(){ return true; })(); if (!$result) return false; if (!$this->make($callable, $request, $args)){ return $next($request); } return false; } /** * 匹配规则 * /user/get/{uid:num}/{name:string}/{sex:string} * * @param string $uri 请求uri * @param array $route 路由规则 * @return null[] */ public function parse($uri, $route) { if(preg_match("/\{.*?\}/i", $route[0])) { $uriArray = explode("/", $uri); $routeArray = explode("/", $route[0]); //如果uri的长度比route的端,那就直接不匹配 if(count($uriArray) < count($routeArray)) { return [null, null]; } $args = array(); $firstMatch = -1; foreach ($routeArray as $index => $val) { if(preg_match("/\{.*?\}/i", $val)) { if($firstMatch == -1) { $firstMatch = $index; } $key = str_replace(array("{", "}"), "", $val); $args[$key] = $uriArray[$index]; } } //首次变量的位置之前的内容不匹配,页直接返回不匹配 $uriMatch = join("/", array_slice($uriArray, 0, 4)); $routeMatch = join("/", array_slice($routeArray, 0, 4)); if($uriMatch != $routeMatch) { return [null, null]; } return [$route, $args]; } return [null, null]; } /** * 执行 $callable * @param mix $callable 执行方法 * @param HTTP $request request * @param array | null $args 正则匹配后拿到的参数及值 * @return bool */ public function make($callable, $request, $args = null) { if($args === null) { $args = array($request); } if(is_array($args)) { array_unshift($args, $request); } switch ($callable) { case ($callable instanceof \Closure): $res = call_user_func_array($callable, $args); if($res instanceof \Qii\Base\Response) { return $res->response(); } echo $res; break; case is_array($callable): $action = (isset($callable[1]) ? $callable[1] : "index"). Register::get(Consts::APP_DEFAULT_ACTION_SUFFIX); $res = call_user_func_array(array(_loadClass($callable[0]), $action), $args); if($res instanceof \Qii\Base\Response) { return $res->response(); } break; case gettype($callable) == 'string': $res = call_user_func_array( array(_loadClass($callable), Register::get("APP_DEFAULT_ACTION"). Register::get(Consts::APP_DEFAULT_ACTION_SUFFIX)), $args); if($res instanceof \Qii\Base\Response) { return $res->response(); } break; } if ($callable) { return true; } return false; } /** * 获取所有设置的路由 * * @return mixed */ public function getStoredRoute(){ return self::getInstance()->stored; } }