<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace
think;
use think\exception\
ClassNotFoundException;
use think\exception\
HttpException;
use think\exception\
HttpResponseException;
use think\exception\
RouteNotFoundException;
/**
* App 应用管理
*
@author
liu21st <liu21st@gmail.com>
*/
class
App
{
/**
*
@var
bool
是否初始化过
*/
protected
static
$init =
false;
/**
*
@var
string
当前模块路径
*/
public
static
$modulePath;
/**
*
@var
bool
应用调试模式
*/
public
static
$debug =
true;
/**
*
@var
string
应用类库命名空间
*/
public
static
$namespace =
'app';
/**
*
@var
bool
应用类库后缀
*/
public
static
$suffix =
false;
/**
*
@var
bool
应用路由检测
*/
protected
static
$routeCheck;
/**
*
@var
bool
严格路由检测
*/
protected
static
$routeMust;
/**
*
@var
array
请求调度分发
*/
protected
static
$dispatch;
/**
*
@var
array
额外加载文件
*/
protected
static
$file = [];
/**
* 执行应用程序
*
@access
public
*
@param
Request
$request 请求对象
*
@return
Response
*
@throws
Exception
*/
//thinkphp5框架入口,执行run方法
public
static
function
run(
Request
$request =
null)
{
//返回实例think\Request方法,该方法在thinkphp\library\think\Request.php中
$request =
is_null(
$request) ?
Request::
instance() :
$request;
//捕获异常
try {
// 执行当前类的initCommon方法,返回 \thinkphp\convention.php里的全部配置信息
$config =
self::
initCommon();
// 模块/控制器绑定
if (
defined(
'BIND_MODULE')) {
BIND_MODULE &&
Route::
bind(BIND_MODULE);
// \thinkphp\convention.php配置里auto_bind_module参数设为true时执行,默认不执行
}
elseif (
$config[
'auto_bind_module']) {
// 入口自动绑定
$name =
pathinfo(
$request->
baseFile(), PATHINFO_FILENAME);
if (
$name &&
'index' !=
$name &&
is_dir(APP_PATH .
$name)) {
Route::
bind(
$name);
}
}
//thinkphp\convention.php配置里default_filter参数设为true时执行,默认不执行
$request->
filter(
$config[
'default_filter']);
// 默认语言
Lang::
range(
$config[
'default_lang']);
// 开启多语言机制 检测当前语言
$config[
'lang_switch_on'] &&
Lang::
detect();
$request->
langset(
Lang::
range());
// 加载系统语言包
Lang::
load([
THINK_PATH .
'lang' . DS .
$request->
langset() . EXT,
APP_PATH .
'lang' . DS .
$request->
langset() . EXT,
]);
// 监听 app_dispatch
Hook::
listen(
'app_dispatch',
self::
$dispatch);
// 获取应用调度信息
$dispatch =
self::
$dispatch;
// 未设置调度信息则进行 URL 路由检测
if (
empty(
$dispatch)) {
/*执行当前类的routeCheck方法,获取调度信息,如访问index模块下index控制器里的index方法,则
$dispatch = array(2) { ["type"]=> string(6) "module"
["module"]=> array(3) {
[0]=> string(5) "index" [1]=> string(5) "index" [2]=> string(5) "index" } }
*/
$dispatch =
self::
routeCheck(
$request,
$config);
}
// 记录当前调度信息 将获取的调度信息,即模块,控制器,方法名存入Request类的dispatch属性中
$request->
dispatch(
$dispatch);
// 记录路由和请求信息 ,调式模式,在\application\config.php 参数app_debug可配置
if (
self::
$debug) {
//将调度信息写入日志 ,执行\thinkphp\library\think\Log.php 中 Log类的record方法
Log::
record(
'[ ROUTE ] ' .
var_export(
$dispatch,
true),
'info');
/*将\thinkphp\library\think\Request.php Request类中header方法
获取的头部信息写入日志 */
Log::
record(
'[ HEADER ] ' .
var_export(
$request->
header(),
true),
'info');
//记录当前请求的参数
Log::
record(
'[ PARAM ] ' .
var_export(
$request->
param(),
true),
'info');
}
// 监听 app_begin
Hook::
listen(
'app_begin',
$dispatch);
// 请求缓存检查
$request->
cache(
$config[
'request_cache'],
$config[
'request_cache_expire'],
$config[
'request_cache_except']
);
//执行当前类的exec方法
$data =
self::
exec(
$dispatch,
$config);
}
catch (
HttpResponseException
$exception) {
$data =
$exception->
getResponse();
}
// 清空类的实例化
Loader::
clearInstance();
// 输出数据到客户端 判断$data是否为Response类的实例
if (
$data instanceof Response) {
$response =
$data;
}
elseif (!
is_null(
$data)) {
// 默认自动识别响应输出类型
$type =
$request->
isAjax() ?
Config::
get(
'default_ajax_return') :
Config::
get(
'default_return_type');