[TOC]
* * * * *
#1 應用入口(App.php->run())
>>在[應用啟動](http://www.hmoore.net/zmwtp/tp/210985)過程中,
>創建[請求對象](http://www.hmoore.net/zmwtp/tp/210989)后,根據注冊的[路由規則](http://www.hmoore.net/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.hmoore.net/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.hmoore.net/zmwtp/tp/210989)的[Url路由](http://www.hmoore.net/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)