private static function parseRule($rule, $route, $pathinfo, $option = [], $matches = [])
{
$request = Request::instance();
// 解析路由规则
if ($rule) {
$rule = explode('/', $rule);
// 获取URL地址中的参数
$paths = explode('|', $pathinfo);
foreach ($rule as $item) {
$fun = '';
if (0 === strpos($item, '[:')) {
$item = substr($item, 1, -1);
}
if (0 === strpos($item, ':')) {
$var = substr($item, 1);
$matches[$var] = array_shift($paths);
} else {
// 过滤URL中的静态变量
array_shift($paths);
}
}
} else {
$paths = explode('|', $pathinfo);
}
// 获取路由地址规则
if (is_string($route) && isset($option['prefix'])) {
// 路由地址前缀
$route = $option['prefix'] . $route;
}
// 替换路由地址中的变量
if (is_string($route) && !empty($matches)) {
foreach ($matches as $key => $val) {
if (false !== strpos($route, ':' . $key)) {
$route = str_replace(':' . $key, $val, $route);
unset($matches[$key]);
}
}
}
// 绑定模型数据
if (isset($option['bind_model'])) {
$bind = [];
foreach ($option['bind_model'] as $key => $val) {
if ($val instanceof \Closure) {
$result = call_user_func_array($val, [$matches]);
} else {
if (is_array($val)) {
$fields = explode('&', $val[1]);
$model = $val[0];
$exception = isset($val[2]) ? $val[2] : true;
} else {
$fields = ['id'];
$model = $val;
$exception = true;
}
$where = [];
$match = true;
foreach ($fields as $field) {
if (!isset($matches[$field])) {
$match = false;
break;
} else {
$where[$field] = $matches[$field];
}
}
if ($match) {
$query = strpos($model, '\\') ? $model::where($where) : Loader::model($model)->where($where);
$result = $query->failException($exception)->find();
}
}
if (!empty($result)) {
$bind[$key] = $result;
}
}
$request->bind($bind);
}
// 解析额外参数
self::parseUrlParams(empty($paths) ? '' : implode('|', $paths), $matches);
// 记录匹配的路由信息
$request->routeInfo(['rule' => $rule, 'route' => $route, 'option' => $option, 'var' => $matches]);
// 检测路由after行为
if (!empty($option['after_behavior'])) {
if ($option['after_behavior'] instanceof \Closure) {
$result = call_user_func_array($option['after_behavior'], []);
} else {
foreach ((array) $option['after_behavior'] as $behavior) {
$result = Hook::exec($behavior, '');
if (!is_null($result)) {
break;
}
}
}
// 路由规则重定向
if ($result instanceof Response) {
return ['type' => 'response', 'response' => $result];
} elseif (is_array($result)) {
return $result;
}
}
if ($route instanceof \Closure) {
// 执行闭包
$result = ['type' => 'function', 'function' => $route];
} elseif (0 === strpos($route, '/') || strpos($route, '://')) {
// 路由到重定向地址
$result = ['type' => 'redirect', 'url' => $route, 'status' => isset($option['status']) ? $option['status'] : 301];
} elseif (false !== strpos($route, '\\')) {
// 路由到方法
$route = str_replace('/', '@', $route);
$method = strpos($route, '@') ? explode('@', $route) : $route;
$result = ['type' => 'method', 'method' => $method];
} elseif (0 === strpos($route, '@')) {
// 路由到控制器
$result = ['type' => 'controller', 'controller' => substr($route, 1)];
} else {
// 路由到模块/控制器/操作
$result = self::parseModule($route);
}
// 开启请求缓存
if ($request->isGet() && !empty($option['cache'])) {
$cache = $option['cache'];
if (is_array($cache)) {
list($key, $expire) = $cache;
} else {
$key = $pathinfo;
$expire = $cache;
}
$request->cache($key, $expire);
}
return $result;
}