🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] * * * * * #1 应用入口(App.php->run()) >>在[应用启动](http://www.kancloud.cn/zmwtp/tp/210985)过程中, >创建[请求对象](http://www.kancloud.cn/zmwtp/tp/210989)后,根据注册的[路由规则](http://www.kancloud.cn/zmwtp/tp/210990),解析请求对象为相应的应用类型 >根据不同的应用类型执行不同的应用 >其中包括六种类型 >redirect,module,controller,method,function,response. ~~~ App.php->run(); switch ($dispatch['type']) { case 'redirect': // 执行重定向跳转 $data = Response::create($dispatch['url'], 'redirect')->code($dispatch['status']); break; case 'module': // 模块/控制器/操作 $data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null); break; case 'controller': // 执行控制器操作 $data = Loader::action($dispatch['controller']); break; case 'method': // 执行回调方法 $data = self::invokeMethod($dispatch['method']); break; case 'function': // 执行闭包 $data = self::invokeFunction($dispatch['function']); break; case 'response': $data = $dispatch['response']; break; default: throw new \InvalidArgumentException('dispatch type not support'); } ~~~ #2 应用类型 ## 2-1 redirect类型 ### redirect应用调度 ~~~ case 'redirect': // 执行重定向跳转 $data = Response::create($dispatch['url'], 'redirect')->code($dispatch['status']); ~~~ >>redircet类型 使用Response创建重定向跳转,跳转到指定Url运行应用。 ### redirect应用处理 >>redirect应用,创建redirect类响应对象,跳转到指定url。redirect类响应对象 见 [网络响应](http://www.kancloud.cn/zmwtp/tp/210995) 章节 ## 2-2 module类型 ### module应用调度 ~~~ case 'module': // 模块/控制器/操作 $data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null); ~~~ >>module类型 调用App::moudle()执行特定模块的应用 ### module应用处理 ~~~ public static function module($result, $config, $convert = null) { if (is_string($result)) { $result = explode('/', $result); } $request = Request::instance(); if ($config['app_multi_module']) { // 多模块部署 $module = strip_tags(strtolower($result[0] ?: $config['default_module'])); $bind = Route::getBind('module'); $available = false; if ($bind) { // 绑定模块 list($bindModule) = explode('/', $bind); if (empty($result[0])) { $module = $bindModule; $available = true; } elseif ($module == $bindModule) { $available = true; } } elseif (!in_array($module, $config['deny_module_list']) && is_dir(APP_PATH . $module)) { $available = true; } // 模块初始化 if ($module && $available) { // 初始化模块 $request->module($module); $config = self::init($module); } else { throw new HttpException(404, 'module not exists:' . $module); } } else { // 单一模块部署 $module = ''; $request->module($module); } // 当前模块路径 App::$modulePath = APP_PATH . ($module ? $module . DS : ''); // 是否自动转换控制器和操作名 $convert = is_bool($convert) ? $convert : $config['url_convert']; // 获取控制器名 $controller = strip_tags($result[1] ?: $config['default_controller']); $controller = $convert ? strtolower($controller) : $controller; // 获取操作名 $actionName = strip_tags($result[2] ?: $config['default_action']); $actionName = $convert ? strtolower($actionName) : $actionName; // 设置当前请求的控制器、操作 $request->controller(Loader::parseName($controller, 1))->action($actionName); // 监听module_init Hook::listen('module_init', $request); try { $instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']); if (is_null($instance)) { throw new HttpException(404, 'controller not exists:' . Loader::parseName($controller, 1)); } // 获取当前操作名 $action = $actionName . $config['action_suffix']; if (!preg_match('/^[A-Za-z](\w)*$/', $action)) { // 非法操作 throw new \ReflectionException('illegal action name:' . $actionName); } // 执行操作方法 $call = [$instance, $action]; Hook::listen('action_begin', $call); $data = self::invokeMethod($call); } catch (\ReflectionException $e) { // 操作不存在 if (method_exists($instance, '_empty')) { $reflect = new \ReflectionMethod($instance, '_empty'); $data = $reflect->invokeArgs($instance, [$action]); self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info'); } else { throw new HttpException(404, 'method not exists:' . (new \ReflectionClass($instance))->getName() . '->' . $action); } } return $data; } ~~~ >>初始化请求的模块,然后查找控制器名,操作名 >使用App::invokeMethod()调用其请求的控制器的操作 ## 2-3 controller类型 ### controller应用调度 ~~~ case 'controller': // 执行控制器操作 $data = Loader::action($dispatch['controller']); ~~~ >>controller类型 调用Loader执行特定应用控制器 ### controller应用处理 >>调用Loader的操作实例化,远程调用控制器的操作 ## 2-4 method类型 ### method应用调度 ~~~ case 'method': // 执行回调方法 $data = self::invokeMethod($dispatch['method']); ~~~ >>method类型 调用App::invokeMethod()执行特定应用的方法 ### method应用处理 ~~~ public static function invokeMethod($method, $vars = []) { if (is_array($method)) { $class = is_object($method[0]) ? $method[0] : new $method[0](Request::instance()); $reflect = new \ReflectionMethod($class, $method[1]); } else { // 静态方法 $reflect = new \ReflectionMethod($method); } $args = self::bindParams($reflect, $vars); // 记录执行信息 self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info'); return $reflect->invokeArgs(isset($class) ? $class : null, $args); } ~~~ >>使用反射执行请求的控制器的操作 ## 2-5 function类型 ### function应用调度 ~~~ case 'function': // 执行闭包 $data = self::invokeFunction($dispatch['function']); ~~~ >>function类型 调用App::invokeFunction()执行特定应用闭包 ### function应用处理 ~~~ public static function invokeFunction($function, $vars = []) { $reflect = new \ReflectionFunction($function); $args = self::bindParams($reflect, $vars); // 记录执行信息 self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info'); return $reflect->invokeArgs($args); } ~~~ >>使用反射执行函数或闭包。 ## 2-6 response类型 ~~~ case 'response': $data = $dispatch['response']; ~~~ >>response类型 直接保存调度的response信息到输出数据 #3 应用类型总结 ## 3-1 类型的特征 >>根据不同类型的复杂度从低到高依次为 >1 response类型 >2 function类型 >3 method类型 >4 controller类型 >5 module类型 >6 redirect类型 >>根据类型的使用频率从高到低依次为 >1 redirect类型 >2 module类型 >3 controller类型 >4 method类型 >5 function类型 >6 response类型 >也就是说大多数应用类型为redirect和module类型。 >>不同类型的应用可以表示为不同形式的应用地址 >应用地址在Url路由的路由注册中使用。 ## 3-2 类型的检测 >>类型的获取使用App::routeCheck()获取请求的应用类型 >应用类型的获取在[网络请求](http://www.kancloud.cn/zmwtp/tp/210989)的[Url路由](http://www.kancloud.cn/zmwtp/tp/210990)的路由检测中获取 ~~~ App.php; public static function routeCheck($request, array $config) { $path = $request->path(); $depr = $config['pathinfo_depr']; $result = false; // 路由检测 $check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on']; if ($check) { // 开启路由 if (is_file(RUNTIME_PATH . 'route.php')) { // 读取路由缓存 $rules = include RUNTIME_PATH . 'route.php'; if (is_array($rules)) { Route::rules($rules); } } else { $files = $config['route_config_file']; foreach ($files as $file) { if (is_file(CONF_PATH . $file . CONF_EXT)) { // 导入路由配置 $rules = include CONF_PATH . $file . CONF_EXT; if (is_array($rules)) { Route::import($rules); } } } } // 路由检测(根据路由定义返回不同的URL调度) $result = Route::check($request, $path, $depr, $config['url_domain_deploy']); $must = !is_null(self::$routeMust) ? self::$routeMust : $config['url_route_must']; if ($must && false === $result) { // 路由无效 throw new HttpException(404, 'Route Not Found'); } } if (false === $result) { // 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索 $result = Route::parseUrl($path, $depr, $config['controller_auto_search']); } return $result; } ~~~