|
@@ -1,6 +1,8 @@
|
|
|
<?php
|
|
|
namespace Qii\Base;
|
|
|
|
|
|
+use Qii\Config\Consts;
|
|
|
+use Qii\Config\Register;
|
|
|
use Qii\Request\Http;
|
|
|
|
|
|
/**
|
|
@@ -29,6 +31,12 @@ class Route
|
|
|
* @var array $stored
|
|
|
*/
|
|
|
private $stored = [];
|
|
|
+ /**
|
|
|
+ * 是否启用正则匹配
|
|
|
+ *
|
|
|
+ * @var bool $enableExpress 默认为启用
|
|
|
+ */
|
|
|
+ private $enableExpress = true;
|
|
|
|
|
|
public function __construct() {
|
|
|
$this->clean();
|
|
@@ -52,10 +60,20 @@ class Route
|
|
|
];
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 实例化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;
|
|
@@ -63,6 +81,12 @@ class 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();
|
|
@@ -159,8 +183,22 @@ class Route
|
|
|
$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;
|
|
@@ -183,28 +221,86 @@ class Route
|
|
|
return true;
|
|
|
})();
|
|
|
if (!$result) return false;
|
|
|
- if (!$this->make($callable)){
|
|
|
+ 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) {
|
|
|
+ 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):
|
|
|
- echo call_user_func($callable);
|
|
|
+ $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"). 'Action';
|
|
|
- _loadClass($callable[0])->$action();
|
|
|
+ echo Register::get("APP_DEFAULT_ACTION");
|
|
|
+ $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':
|
|
|
- _loadClass($callable)->indexAction();
|
|
|
+ $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) {
|