[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;
}
~~~
- 框架简介
- 简介
- 框架目录
- 根目录
- 应用目录
- 核心目录
- 扩展目录
- 其他目录
- 框架流程
- 启动流程
- 请求流程
- 响应流程
- 框架结构
- 应用组织
- 网络请求
- 路由组织
- 数据验证
- 数据模型(M)
- 数据库连接(Connection)
- 数据库(Db)
- 查询构造(Builder)
- 数据库查询(Query)
- 模型(Model)
- 模板视图(V)
- 视图(View)
- 模板引擎(Think)
- 模板标签库(TagLib)
- 控制器(C)
- 网络响应
- 配置与缓存
- 配置操作
- 缓存操作
- cookie与session
- Cookie操作
- Session操作
- 自动加载
- 钩子注册
- 文件上传
- 分页控制
- 控制台
- 自动构建
- 日志异常调试
- 异常处理
- 代码调试
- 日志记录
- 框架使用
- 1 环境搭建(Server)
- 2 网络请求(Request)
- 3 请求路由(Route)
- 4 响应输出(Response)
- 5 业务处理(Controller)
- 6 数据存取(Model)
- 7 Web界面(View)