格式化 start、base、traits 和 App、Config、Error、Loader 代码的样式。其他代码的样式待处理。

This commit is contained in:
Lin07ux
2017-11-05 15:21:42 +08:00
committed by ThinkPHP
parent 0fb51680e8
commit 35e763c8ff
9 changed files with 682 additions and 513 deletions

View File

@@ -40,8 +40,10 @@ require CORE_PATH . 'Loader.php';
// 加载环境变量配置文件 // 加载环境变量配置文件
if (is_file(ROOT_PATH . '.env')) { if (is_file(ROOT_PATH . '.env')) {
$env = parse_ini_file(ROOT_PATH . '.env', true); $env = parse_ini_file(ROOT_PATH . '.env', true);
foreach ($env as $key => $val) { foreach ($env as $key => $val) {
$name = ENV_PREFIX . strtoupper($key); $name = ENV_PREFIX . strtoupper($key);
if (is_array($val)) { if (is_array($val)) {
foreach ($val as $k => $v) { foreach ($val as $k => $v) {
$item = $name . '_' . strtoupper($k); $item = $name . '_' . strtoupper($k);

View File

@@ -18,7 +18,7 @@ use think\exception\RouteNotFoundException;
/** /**
* App 应用管理 * App 应用管理
* @author liu21st <liu21st@gmail.com> * @author liu21st <liu21st@gmail.com>
*/ */
class App class App
{ {
@@ -57,24 +57,32 @@ class App
*/ */
protected static $routeMust; protected static $routeMust;
/**
* @var array 请求调度分发
*/
protected static $dispatch; protected static $dispatch;
/**
* @var array 额外加载文件
*/
protected static $file = []; protected static $file = [];
/** /**
* 执行应用程序 * 执行应用程序
* @access public * @access public
* @param Request $request Request对象 * @param Request $request 请求对象
* @return Response * @return Response
* @throws Exception * @throws Exception
*/ */
public static function run(Request $request = null) public static function run(Request $request = null)
{ {
is_null($request) && $request = Request::instance(); $request = is_null($request) ? Request::instance() : $request;
try { try {
$config = self::initCommon(); $config = self::initCommon();
// 模块/控制器绑定
if (defined('BIND_MODULE')) { if (defined('BIND_MODULE')) {
// 模块/控制器绑定
BIND_MODULE && Route::bind(BIND_MODULE); BIND_MODULE && Route::bind(BIND_MODULE);
} elseif ($config['auto_bind_module']) { } elseif ($config['auto_bind_module']) {
// 入口自动绑定 // 入口自动绑定
@@ -88,10 +96,8 @@ class App
// 默认语言 // 默认语言
Lang::range($config['default_lang']); Lang::range($config['default_lang']);
if ($config['lang_switch_on']) { // 开启多语言机制 检测当前语言
// 开启多语言机制 检测当前语言 $config['lang_switch_on'] && Lang::detect();
Lang::detect();
}
$request->langset(Lang::range()); $request->langset(Lang::range());
// 加载系统语言包 // 加载系统语言包
@@ -102,10 +108,11 @@ class App
// 获取应用调度信息 // 获取应用调度信息
$dispatch = self::$dispatch; $dispatch = self::$dispatch;
// 未设置调度信息则进行 URL 路由检测
if (empty($dispatch)) { if (empty($dispatch)) {
// 进行URL路由检测
$dispatch = self::routeCheck($request, $config); $dispatch = self::routeCheck($request, $config);
} }
// 记录当前调度信息 // 记录当前调度信息
$request->dispatch($dispatch); $request->dispatch($dispatch);
@@ -116,10 +123,15 @@ class App
Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info'); Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info');
} }
// 监听app_begin // 监听 app_begin
Hook::listen('app_begin', $dispatch); Hook::listen('app_begin', $dispatch);
// 请求缓存检查 // 请求缓存检查
$request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']); $request->cache(
$config['request_cache'],
$config['request_cache_expire'],
$config['request_cache_except']
);
$data = self::exec($dispatch, $config); $data = self::exec($dispatch, $config);
} catch (HttpResponseException $exception) { } catch (HttpResponseException $exception) {
@@ -134,24 +146,144 @@ class App
$response = $data; $response = $data;
} elseif (!is_null($data)) { } elseif (!is_null($data)) {
// 默认自动识别响应输出类型 // 默认自动识别响应输出类型
$isAjax = $request->isAjax(); $type = $request->isAjax() ?
$type = $isAjax ? Config::get('default_ajax_return') : Config::get('default_return_type'); Config::get('default_ajax_return') :
Config::get('default_return_type');
$response = Response::create($data, $type); $response = Response::create($data, $type);
} else { } else {
$response = Response::create(); $response = Response::create();
} }
// 监听app_end // 监听 app_end
Hook::listen('app_end', $response); Hook::listen('app_end', $response);
return $response; return $response;
} }
/**
* 初始化应用,并返回配置信息
* @access public
* @return mixed
*/
public static function initCommon()
{
if (empty(self::$init)) {
if (defined('APP_NAMESPACE')) self::$namespace = APP_NAMESPACE;
Loader::addNamespace(self::$namespace, APP_PATH);
// 初始化应用
$config = self::init();
self::$suffix = $config['class_suffix'];
// 应用调试模式
self::$debug = Env::get('app_debug', Config::get('app_debug'));
if (!self::$debug) {
ini_set('display_errors', 'Off');
} elseif (!IS_CLI) {
// 重新申请一块比较大的 buffer
if (ob_get_level() > 0) $output = ob_get_clean();
ob_start();
if (!empty($output)) echo $output;
}
if (!empty($config['root_namespace'])) {
Loader::addNamespace($config['root_namespace']);
}
// 加载额外文件
if (!empty($config['extra_file_list'])) {
foreach ($config['extra_file_list'] as $file) {
$file = strpos($file, '.') ? $file : APP_PATH . $file . EXT;
if (is_file($file) && !isset(self::$file[$file])) {
include $file;
self::$file[$file] = true;
}
}
}
// 设置系统时区
date_default_timezone_set($config['default_timezone']);
// 监听 app_init
Hook::listen('app_init');
self::$init = true;
}
return Config::get();
}
/**
* 初始化应用或模块
* @access public
* @param string $module 模块名
* @return array
*/
private static function init($module = '')
{
// 定位模块目录
$module = $module ? $module . DS : '';
// 加载初始化文件
if (is_file(APP_PATH . $module . 'init' . EXT)) {
include APP_PATH . $module . 'init' . EXT;
} elseif (is_file(RUNTIME_PATH . $module . 'init' . EXT)) {
include RUNTIME_PATH . $module . 'init' . EXT;
} else {
// 加载模块配置
$config = Config::load(CONF_PATH . $module . 'config' . CONF_EXT);
// 读取数据库配置文件
$filename = CONF_PATH . $module . 'database' . CONF_EXT;
Config::load($filename, 'database');
// 读取扩展配置文件
if (is_dir(CONF_PATH . $module . 'extra')) {
$dir = CONF_PATH . $module . 'extra';
$files = scandir($dir);
foreach ($files as $file) {
if ('.' . pathinfo($file, PATHINFO_EXTENSION) === CONF_EXT) {
$filename = $dir . DS . $file;
Config::load($filename, pathinfo($file, PATHINFO_FILENAME));
}
}
}
// 加载应用状态配置
if ($config['app_status']) {
Config::load(CONF_PATH . $module . $config['app_status'] . CONF_EXT);
}
// 加载行为扩展文件
if (is_file(CONF_PATH . $module . 'tags' . EXT)) {
Hook::import(include CONF_PATH . $module . 'tags' . EXT);
}
// 加载公共文件
$path = APP_PATH . $module;
if (is_file($path . 'common' . EXT)) {
include $path . 'common' . EXT;
}
// 加载当前模块语言包
if ($module) {
Lang::load($path . 'lang' . DS . Request::instance()->langset() . EXT);
}
}
return Config::get();
}
/** /**
* 设置当前请求的调度信息 * 设置当前请求的调度信息
* @access public * @access public
* @param array|string $dispatch 调度信息 * @param array|string $dispatch 调度信息
* @param string $type 调度类型 * @param string $type 调度类型
* @return void * @return void
*/ */
public static function dispatch($dispatch, $type = 'module') public static function dispatch($dispatch, $type = 'module')
@@ -170,8 +302,10 @@ class App
{ {
$reflect = new \ReflectionFunction($function); $reflect = new \ReflectionFunction($function);
$args = self::bindParams($reflect, $vars); $args = self::bindParams($reflect, $vars);
// 记录执行信息 // 记录执行信息
self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info'); self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info');
return $reflect->invokeArgs($args); return $reflect->invokeArgs($args);
} }
@@ -191,28 +325,27 @@ class App
// 静态方法 // 静态方法
$reflect = new \ReflectionMethod($method); $reflect = new \ReflectionMethod($method);
} }
$args = self::bindParams($reflect, $vars); $args = self::bindParams($reflect, $vars);
self::$debug && Log::record('[ RUN ] ' . $reflect->class . '->' . $reflect->name . '[ ' . $reflect->getFileName() . ' ]', 'info'); self::$debug && Log::record('[ RUN ] ' . $reflect->class . '->' . $reflect->name . '[ ' . $reflect->getFileName() . ' ]', 'info');
return $reflect->invokeArgs(isset($class) ? $class : null, $args); return $reflect->invokeArgs(isset($class) ? $class : null, $args);
} }
/** /**
* 调用反射执行类的实例化 支持依赖注入 * 调用反射执行类的实例化 支持依赖注入
* @access public * @access public
* @param string $class 类名 * @param string $class 类名
* @param array $vars 变量 * @param array $vars 变量
* @return mixed * @return mixed
*/ */
public static function invokeClass($class, $vars = []) public static function invokeClass($class, $vars = [])
{ {
$reflect = new \ReflectionClass($class); $reflect = new \ReflectionClass($class);
$constructor = $reflect->getConstructor(); $constructor = $reflect->getConstructor();
if ($constructor) { $args = $constructor ? self::bindParams($constructor, $vars) : [];
$args = self::bindParams($constructor, $vars);
} else {
$args = [];
}
return $reflect->newInstanceArgs($args); return $reflect->newInstanceArgs($args);
} }
@@ -225,52 +358,58 @@ class App
*/ */
private static function bindParams($reflect, $vars = []) private static function bindParams($reflect, $vars = [])
{ {
// 自动获取请求变量
if (empty($vars)) { if (empty($vars)) {
// 自动获取请求变量 $vars = Config::get('url_param_type') ?
if (Config::get('url_param_type')) { Request::instance()->route() :
$vars = Request::instance()->route(); Request::instance()->param();
} else {
$vars = Request::instance()->param();
}
} }
$args = []; $args = [];
if ($reflect->getNumberOfParameters() > 0) { if ($reflect->getNumberOfParameters() > 0) {
// 判断数组类型 数字数组时按顺序绑定参数 // 判断数组类型 数字数组时按顺序绑定参数
reset($vars); reset($vars);
$type = key($vars) === 0 ? 1 : 0; $type = key($vars) === 0 ? 1 : 0;
$params = $reflect->getParameters();
foreach ($params as $param) { foreach ($reflect->getParameters() as $param) {
$args[] = self::getParamValue($param, $vars, $type); $args[] = self::getParamValue($param, $vars, $type);
} }
} }
return $args; return $args;
} }
/** /**
* 获取参数值 * 获取参数值
* @access private * @access private
* @param \ReflectionParameter $param * @param \ReflectionParameter $param 参数
* @param array $vars 变量 * @param array $vars 变量
* @param string $type * @param string $type 类别
* @return array * @return array
*/ */
private static function getParamValue($param, &$vars, $type) private static function getParamValue($param, &$vars, $type)
{ {
$name = $param->getName(); $name = $param->getName();
$class = $param->getClass(); $class = $param->getClass();
if ($class) { if ($class) {
$className = $class->getName(); $className = $class->getName();
$bind = Request::instance()->$name; $bind = Request::instance()->$name;
if ($bind instanceof $className) { if ($bind instanceof $className) {
$result = $bind; $result = $bind;
} else { } else {
if (method_exists($className, 'invoke')) { if (method_exists($className, 'invoke')) {
$method = new \ReflectionMethod($className, 'invoke'); $method = new \ReflectionMethod($className, 'invoke');
if ($method->isPublic() && $method->isStatic()) { if ($method->isPublic() && $method->isStatic()) {
return $className::invoke(Request::instance()); return $className::invoke(Request::instance());
} }
} }
$result = method_exists($className, 'instance') ? $className::instance() : new $className;
$result = method_exists($className, 'instance') ?
$className::instance() :
new $className;
} }
} elseif (1 == $type && !empty($vars)) { } elseif (1 == $type && !empty($vars)) {
$result = array_shift($vars); $result = array_shift($vars);
@@ -281,65 +420,83 @@ class App
} else { } else {
throw new \InvalidArgumentException('method param miss:' . $name); throw new \InvalidArgumentException('method param miss:' . $name);
} }
return $result; return $result;
} }
/**
* 执行调用分发
* @access protected
* @param array $dispatch 调用信息
* @param array $config 配置信息
* @return Response|mixed
* @throws \InvalidArgumentException
*/
protected static function exec($dispatch, $config) protected static function exec($dispatch, $config)
{ {
switch ($dispatch['type']) { switch ($dispatch['type']) {
case 'redirect': case 'redirect': // 重定向跳转
// 执行重定向跳转 $data = Response::create($dispatch['url'], 'redirect')
$data = Response::create($dispatch['url'], 'redirect')->code($dispatch['status']); ->code($dispatch['status']);
break; break;
case 'module': case 'module': // 模块/控制器/操作
// 模块/控制器/操作 $data = self::module(
$data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null); $dispatch['module'],
$config,
isset($dispatch['convert']) ? $dispatch['convert'] : null
);
break; break;
case 'controller': case 'controller': // 执行控制器操作
// 执行控制器操作
$vars = array_merge(Request::instance()->param(), $dispatch['var']); $vars = array_merge(Request::instance()->param(), $dispatch['var']);
$data = Loader::action($dispatch['controller'], $vars, $config['url_controller_layer'], $config['controller_suffix']); $data = Loader::action(
$dispatch['controller'],
$vars,
$config['url_controller_layer'],
$config['controller_suffix']
);
break; break;
case 'method': case 'method': // 回调方法
// 执行回调方法
$vars = array_merge(Request::instance()->param(), $dispatch['var']); $vars = array_merge(Request::instance()->param(), $dispatch['var']);
$data = self::invokeMethod($dispatch['method'], $vars); $data = self::invokeMethod($dispatch['method'], $vars);
break; break;
case 'function': case 'function': // 闭包
// 执行闭包
$data = self::invokeFunction($dispatch['function']); $data = self::invokeFunction($dispatch['function']);
break; break;
case 'response': case 'response': // Response 实例
$data = $dispatch['response']; $data = $dispatch['response'];
break; break;
default: default:
throw new \InvalidArgumentException('dispatch type not support'); throw new \InvalidArgumentException('dispatch type not support');
} }
return $data; return $data;
} }
/** /**
* 执行模块 * 执行模块
* @access public * @access public
* @param array $result 模块/控制器/操作 * @param array $result 模块/控制器/操作
* @param array $config 配置参数 * @param array $config 配置参数
* @param bool $convert 是否自动转换控制器和操作名 * @param bool $convert 是否自动转换控制器和操作名
* @return mixed * @return mixed
* @throws HttpException
*/ */
public static function module($result, $config, $convert = null) public static function module($result, $config, $convert = null)
{ {
if (is_string($result)) { if (is_string($result)) $result = explode('/', $result);
$result = explode('/', $result);
}
$request = Request::instance(); $request = Request::instance();
if ($config['app_multi_module']) { if ($config['app_multi_module']) {
// 多模块部署 // 多模块部署
$module = strip_tags(strtolower($result[0] ?: $config['default_module'])); $module = strip_tags(strtolower($result[0] ?: $config['default_module']));
$bind = Route::getBind('module'); $bind = Route::getBind('module');
$available = false; $available = false;
if ($bind) { if ($bind) {
// 绑定模块 // 绑定模块
list($bindModule) = explode('/', $bind); list($bindModule) = explode('/', $bind);
if (empty($result[0])) { if (empty($result[0])) {
$module = $bindModule; $module = $bindModule;
$available = true; $available = true;
@@ -355,8 +512,13 @@ class App
// 初始化模块 // 初始化模块
$request->module($module); $request->module($module);
$config = self::init($module); $config = self::init($module);
// 模块请求缓存检查 // 模块请求缓存检查
$request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']); $request->cache(
$config['request_cache'],
$config['request_cache_expire'],
$config['request_cache_except']
);
} else { } else {
throw new HttpException(404, 'module not exists:' . $module); throw new HttpException(404, 'module not exists:' . $module);
} }
@@ -365,11 +527,13 @@ class App
$module = ''; $module = '';
$request->module($module); $request->module($module);
} }
// 当前模块路径 // 当前模块路径
App::$modulePath = APP_PATH . ($module ? $module . DS : ''); App::$modulePath = APP_PATH . ($module ? $module . DS : '');
// 是否自动转换控制器和操作名 // 是否自动转换控制器和操作名
$convert = is_bool($convert) ? $convert : $config['url_convert']; $convert = is_bool($convert) ? $convert : $config['url_convert'];
// 获取控制器名 // 获取控制器名
$controller = strip_tags($result[1] ?: $config['default_controller']); $controller = strip_tags($result[1] ?: $config['default_controller']);
$controller = $convert ? strtolower($controller) : $controller; $controller = $convert ? strtolower($controller) : $controller;
@@ -385,7 +549,12 @@ class App
Hook::listen('module_init', $request); Hook::listen('module_init', $request);
try { try {
$instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']); $instance = Loader::controller(
$controller,
$config['url_controller_layer'],
$config['controller_suffix'],
$config['empty_controller']
);
} catch (ClassNotFoundException $e) { } catch (ClassNotFoundException $e) {
throw new HttpException(404, 'controller not exists:' . $e->getClass()); throw new HttpException(404, 'controller not exists:' . $e->getClass());
} }
@@ -411,125 +580,11 @@ class App
return self::invokeMethod($call, $vars); return self::invokeMethod($call, $vars);
} }
/**
* 初始化应用
*/
public static function initCommon()
{
if (empty(self::$init)) {
if (defined('APP_NAMESPACE')) {
self::$namespace = APP_NAMESPACE;
}
Loader::addNamespace(self::$namespace, APP_PATH);
// 初始化应用
$config = self::init();
self::$suffix = $config['class_suffix'];
// 应用调试模式
self::$debug = Env::get('app_debug', Config::get('app_debug'));
if (!self::$debug) {
ini_set('display_errors', 'Off');
} elseif (!IS_CLI) {
//重新申请一块比较大的buffer
if (ob_get_level() > 0) {
$output = ob_get_clean();
}
ob_start();
if (!empty($output)) {
echo $output;
}
}
if (!empty($config['root_namespace'])) {
Loader::addNamespace($config['root_namespace']);
}
// 加载额外文件
if (!empty($config['extra_file_list'])) {
foreach ($config['extra_file_list'] as $file) {
$file = strpos($file, '.') ? $file : APP_PATH . $file . EXT;
if (is_file($file) && !isset(self::$file[$file])) {
include $file;
self::$file[$file] = true;
}
}
}
// 设置系统时区
date_default_timezone_set($config['default_timezone']);
// 监听app_init
Hook::listen('app_init');
self::$init = true;
}
return Config::get();
}
/**
* 初始化应用或模块
* @access public
* @param string $module 模块名
* @return array
*/
private static function init($module = '')
{
// 定位模块目录
$module = $module ? $module . DS : '';
// 加载初始化文件
if (is_file(APP_PATH . $module . 'init' . EXT)) {
include APP_PATH . $module . 'init' . EXT;
} elseif (is_file(RUNTIME_PATH . $module . 'init' . EXT)) {
include RUNTIME_PATH . $module . 'init' . EXT;
} else {
$path = APP_PATH . $module;
// 加载模块配置
$config = Config::load(CONF_PATH . $module . 'config' . CONF_EXT);
// 读取数据库配置文件
$filename = CONF_PATH . $module . 'database' . CONF_EXT;
Config::load($filename, 'database');
// 读取扩展配置文件
if (is_dir(CONF_PATH . $module . 'extra')) {
$dir = CONF_PATH . $module . 'extra';
$files = scandir($dir);
foreach ($files as $file) {
if ('.' . pathinfo($file, PATHINFO_EXTENSION) === CONF_EXT) {
$filename = $dir . DS . $file;
Config::load($filename, pathinfo($file, PATHINFO_FILENAME));
}
}
}
// 加载应用状态配置
if ($config['app_status']) {
$config = Config::load(CONF_PATH . $module . $config['app_status'] . CONF_EXT);
}
// 加载行为扩展文件
if (is_file(CONF_PATH . $module . 'tags' . EXT)) {
Hook::import(include CONF_PATH . $module . 'tags' . EXT);
}
// 加载公共文件
if (is_file($path . 'common' . EXT)) {
include $path . 'common' . EXT;
}
// 加载当前模块语言包
if ($module) {
Lang::load($path . 'lang' . DS . Request::instance()->langset() . EXT);
}
}
return Config::get();
}
/** /**
* URL路由检测根据PATH_INFO) * URL路由检测根据PATH_INFO)
* @access public * @access public
* @param \think\Request $request * @param \think\Request $request 请求实例
* @param array $config * @param array $config 配置信息
* @return array * @return array
* @throws \think\Exception * @throws \think\Exception
*/ */
@@ -538,6 +593,7 @@ class App
$path = $request->path(); $path = $request->path();
$depr = $config['pathinfo_depr']; $depr = $config['pathinfo_depr'];
$result = false; $result = false;
// 路由检测 // 路由检测
$check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on']; $check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on'];
if ($check) { if ($check) {
@@ -545,34 +601,33 @@ class App
if (is_file(RUNTIME_PATH . 'route.php')) { if (is_file(RUNTIME_PATH . 'route.php')) {
// 读取路由缓存 // 读取路由缓存
$rules = include RUNTIME_PATH . 'route.php'; $rules = include RUNTIME_PATH . 'route.php';
if (is_array($rules)) { is_array($rules) && Route::rules($rules);
Route::rules($rules);
}
} else { } else {
$files = $config['route_config_file']; $files = $config['route_config_file'];
foreach ($files as $file) { foreach ($files as $file) {
if (is_file(CONF_PATH . $file . CONF_EXT)) { if (is_file(CONF_PATH . $file . CONF_EXT)) {
// 导入路由配置 // 导入路由配置
$rules = include CONF_PATH . $file . CONF_EXT; $rules = include CONF_PATH . $file . CONF_EXT;
if (is_array($rules)) { is_array($rules) && Route::import($rules);
Route::import($rules);
}
} }
} }
} }
// 路由检测根据路由定义返回不同的URL调度 // 路由检测根据路由定义返回不同的URL调度
$result = Route::check($request, $path, $depr, $config['url_domain_deploy']); $result = Route::check($request, $path, $depr, $config['url_domain_deploy']);
$must = !is_null(self::$routeMust) ? self::$routeMust : $config['url_route_must']; $must = !is_null(self::$routeMust) ? self::$routeMust : $config['url_route_must'];
if ($must && false === $result) { if ($must && false === $result) {
// 路由无效 // 路由无效
throw new RouteNotFoundException(); throw new RouteNotFoundException();
} }
} }
// 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索
if (false === $result) { if (false === $result) {
// 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索
$result = Route::parseUrl($path, $depr, $config['controller_auto_search']); $result = Route::parseUrl($path, $depr, $config['controller_auto_search']);
} }
return $result; return $result;
} }

View File

@@ -13,70 +13,84 @@ namespace think;
class Config class Config
{ {
// 配置参数 /**
* @var array 配置参数
*/
private static $config = []; private static $config = [];
// 参数作用域
/**
* @var string 参数作用域
*/
private static $range = '_sys_'; private static $range = '_sys_';
// 设定配置参数的作用域 /**
* 设定配置参数的作用域
* @param string $range 作用域
* @return void
*/
public static function range($range) public static function range($range)
{ {
self::$range = $range; self::$range = $range;
if (!isset(self::$config[$range])) {
self::$config[$range] = []; if (!isset(self::$config[$range])) self::$config[$range] = [];
}
} }
/** /**
* 解析配置文件或内容 * 解析配置文件或内容
* @param string $config 配置文件路径或内容 * @param string $config 配置文件路径或内容
* @param string $type 配置解析类型 * @param string $type 配置解析类型
* @param string $name 配置名(如设置即表示二级配置) * @param string $name 配置名(如设置即表示二级配置)
* @param string $range 作用域 * @param string $range 作用域
* @return mixed * @return mixed
*/ */
public static function parse($config, $type = '', $name = '', $range = '') public static function parse($config, $type = '', $name = '', $range = '')
{ {
$range = $range ?: self::$range; $range = $range ?: self::$range;
if (empty($type)) {
$type = pathinfo($config, PATHINFO_EXTENSION); if (empty($type)) $type = pathinfo($config, PATHINFO_EXTENSION);
}
$class = false !== strpos($type, '\\') ? $type : '\\think\\config\\driver\\' . ucwords($type); $class = false !== strpos($type, '\\') ?
$type :
'\\think\\config\\driver\\' . ucwords($type);
return self::set((new $class())->parse($config), $name, $range); return self::set((new $class())->parse($config), $name, $range);
} }
/** /**
* 加载配置文件PHP格式 * 加载配置文件PHP格式
* @param string $file 配置文件名 * @param string $file 配置文件名
* @param string $name 配置名(如设置即表示二级配置) * @param string $name 配置名(如设置即表示二级配置)
* @param string $range 作用域 * @param string $range 作用域
* @return mixed * @return mixed
*/ */
public static function load($file, $name = '', $range = '') public static function load($file, $name = '', $range = '')
{ {
$range = $range ?: self::$range; $range = $range ?: self::$range;
if (!isset(self::$config[$range])) {
self::$config[$range] = []; if (!isset(self::$config[$range])) self::$config[$range] = [];
}
if (is_file($file)) { if (is_file($file)) {
$name = strtolower($name); $name = strtolower($name);
$type = pathinfo($file, PATHINFO_EXTENSION); $type = pathinfo($file, PATHINFO_EXTENSION);
if ('php' == $type) { if ('php' == $type) {
return self::set(include $file, $name, $range); return self::set(include $file, $name, $range);
} elseif ('yaml' == $type && function_exists('yaml_parse_file')) {
return self::set(yaml_parse_file($file), $name, $range);
} else {
return self::parse($file, $type, $name, $range);
} }
} else {
return self::$config[$range]; if ('yaml' == $type && function_exists('yaml_parse_file')) {
return self::set(yaml_parse_file($file), $name, $range);
}
return self::parse($file, $type, $name, $range);
} }
return self::$config[$range];
} }
/** /**
* 检测配置是否存在 * 检测配置是否存在
* @param string $name 配置参数名(支持二级配置 .号分割) * @param string $name 配置参数名(支持二级配置 . 号分割)
* @param string $range 作用域 * @param string $range 作用域
* @return bool * @return bool
*/ */
public static function has($name, $range = '') public static function has($name, $range = '')
@@ -85,90 +99,105 @@ class Config
if (!strpos($name, '.')) { if (!strpos($name, '.')) {
return isset(self::$config[$range][strtolower($name)]); return isset(self::$config[$range][strtolower($name)]);
} else {
// 二维数组设置和获取支持
$name = explode('.', $name, 2);
return isset(self::$config[$range][strtolower($name[0])][$name[1]]);
} }
// 二维数组设置和获取支持
$name = explode('.', $name, 2);
return isset(self::$config[$range][strtolower($name[0])][$name[1]]);
} }
/** /**
* 获取配置参数 为空则获取所有配置 * 获取配置参数 为空则获取所有配置
* @param string $name 配置参数名(支持二级配置 .号分割) * @param string $name 配置参数名(支持二级配置 . 号分割)
* @param string $range 作用域 * @param string $range 作用域
* @return mixed * @return mixed
*/ */
public static function get($name = null, $range = '') public static function get($name = null, $range = '')
{ {
$range = $range ?: self::$range; $range = $range ?: self::$range;
// 无参数时获取所有 // 无参数时获取所有
if (empty($name) && isset(self::$config[$range])) { if (empty($name) && isset(self::$config[$range])) {
return self::$config[$range]; return self::$config[$range];
} }
// 非二级配置时直接返回
if (!strpos($name, '.')) { if (!strpos($name, '.')) {
$name = strtolower($name); $name = strtolower($name);
return isset(self::$config[$range][$name]) ? self::$config[$range][$name] : null; return isset(self::$config[$range][$name]) ? self::$config[$range][$name] : null;
} else {
// 二维数组设置和获取支持
$name = explode('.', $name, 2);
$name[0] = strtolower($name[0]);
if (!isset(self::$config[$range][$name[0]])) {
// 动态载入额外配置
$module = Request::instance()->module();
$file = CONF_PATH . ($module ? $module . DS : '') . 'extra' . DS . $name[0] . CONF_EXT;
is_file($file) && self::load($file, $name[0]);
}
return isset(self::$config[$range][$name[0]][$name[1]]) ? self::$config[$range][$name[0]][$name[1]] : null;
} }
// 二维数组设置和获取支持
$name = explode('.', $name, 2);
$name[0] = strtolower($name[0]);
if (!isset(self::$config[$range][$name[0]])) {
// 动态载入额外配置
$module = Request::instance()->module();
$file = CONF_PATH . ($module ? $module . DS : '') . 'extra' . DS . $name[0] . CONF_EXT;
is_file($file) && self::load($file, $name[0]);
}
return isset(self::$config[$range][$name[0]][$name[1]]) ?
self::$config[$range][$name[0]][$name[1]] :
null;
} }
/** /**
* 设置配置参数 name为数组则为批量设置 * 设置配置参数 name 为数组则为批量设置
* @param string|array $name 配置参数名(支持二级配置 .号分割) * @param string|array $name 配置参数名(支持二级配置 . 号分割)
* @param mixed $value 配置值 * @param mixed $value 配置值
* @param string $range 作用域 * @param string $range 作用域
* @return mixed * @return mixed
*/ */
public static function set($name, $value = null, $range = '') public static function set($name, $value = null, $range = '')
{ {
$range = $range ?: self::$range; $range = $range ?: self::$range;
if (!isset(self::$config[$range])) {
self::$config[$range] = []; if (!isset(self::$config[$range])) self::$config[$range] = [];
}
// 字符串则表示单个配置设置
if (is_string($name)) { if (is_string($name)) {
if (!strpos($name, '.')) { if (!strpos($name, '.')) {
self::$config[$range][strtolower($name)] = $value; self::$config[$range][strtolower($name)] = $value;
} else { } else {
// 二维数组设置和获取支持 // 二维数组
$name = explode('.', $name, 2); $name = explode('.', $name, 2);
self::$config[$range][strtolower($name[0])][$name[1]] = $value; self::$config[$range][strtolower($name[0])][$name[1]] = $value;
} }
return;
} elseif (is_array($name)) { return $value;
// 批量设置 }
// 数组则表示批量设置
if (is_array($name)) {
if (!empty($value)) { if (!empty($value)) {
self::$config[$range][$value] = isset(self::$config[$range][$value]) ? self::$config[$range][$value] = isset(self::$config[$range][$value]) ?
array_merge(self::$config[$range][$value], $name) : $name; array_merge(self::$config[$range][$value], $name) :
$name;
return self::$config[$range][$value]; return self::$config[$range][$value];
} else {
return self::$config[$range] = array_merge(self::$config[$range], array_change_key_case($name));
} }
} else {
// 为空直接返回 已有配置 return self::$config[$range] = array_merge(
return self::$config[$range]; self::$config[$range], array_change_key_case($name)
);
} }
// 为空直接返回已有配置
return self::$config[$range];
} }
/** /**
* 重置配置参数 * 重置配置参数
* @param string $range 作用域
* @return void
*/ */
public static function reset($range = '') public static function reset($range = '')
{ {
$range = $range ?: self::$range; $range = $range ?: self::$range;
if (true === $range) { if (true === $range) {
self::$config = []; self::$config = [];
} else { } else {

View File

@@ -31,53 +31,55 @@ class Error
} }
/** /**
* Exception Handler * 异常处理
* @param \Exception|\Throwable $e * @param \Exception|\Throwable $e 异常
* @return void
*/ */
public static function appException($e) public static function appException($e)
{ {
if (!$e instanceof \Exception) { if (!$e instanceof \Exception) $e = new ThrowableError($e);
$e = new ThrowableError($e);
} $handler = self::getExceptionHandler();
$handler->report($e);
self::getExceptionHandler()->report($e);
if (IS_CLI) { if (IS_CLI) {
self::getExceptionHandler()->renderForConsole(new ConsoleOutput, $e); $handler->renderForConsole(new ConsoleOutput, $e);
} else { } else {
self::getExceptionHandler()->render($e)->send(); $handler->render($e)->send();
} }
} }
/** /**
* Error Handler * 错误处理
* @param integer $errno 错误编号 * @param integer $errno 错误编号
* @param integer $errstr 详细错误信息 * @param integer $errstr 详细错误信息
* @param string $errfile 出错的文件 * @param string $errfile 出错的文件
* @param integer $errline 出错行号 * @param integer $errline 出错行号
* @param array $errcontext * @param array $errcontext 出错上下文
* @return void
* @throws ErrorException * @throws ErrorException
*/ */
public static function appError($errno, $errstr, $errfile = '', $errline = 0, $errcontext = []) public static function appError($errno, $errstr, $errfile = '', $errline = 0, $errcontext = [])
{ {
$exception = new ErrorException($errno, $errstr, $errfile, $errline, $errcontext); $exception = new ErrorException($errno, $errstr, $errfile, $errline, $errcontext);
if (error_reporting() & $errno) {
// 将错误信息托管至 think\exception\ErrorException // 符合异常处理的则将错误信息托管至 think\exception\ErrorException
throw $exception; if (error_reporting() & $errno) throw $exception;
} else {
self::getExceptionHandler()->report($exception); self::getExceptionHandler()->report($exception);
}
} }
/** /**
* Shutdown Handler * 异常中止处理
* @return void
*/ */
public static function appShutdown() public static function appShutdown()
{ {
// 将错误信息托管至 think\ErrorException
if (!is_null($error = error_get_last()) && self::isFatal($error['type'])) { if (!is_null($error = error_get_last()) && self::isFatal($error['type'])) {
// 将错误信息托管至think\ErrorException self::appException(new ErrorException(
$exception = new ErrorException($error['type'], $error['message'], $error['file'], $error['line']); $error['type'], $error['message'], $error['file'], $error['line']
));
self::appException($exception);
} }
// 写入日志 // 写入日志
@@ -86,8 +88,7 @@ class Error
/** /**
* 确定错误类型是否致命 * 确定错误类型是否致命
* * @param int $type
* @param int $type
* @return bool * @return bool
*/ */
protected static function isFatal($type) protected static function isFatal($type)
@@ -96,25 +97,28 @@ class Error
} }
/** /**
* Get an instance of the exception handler. * 获取异常处理的实例
*
* @return Handle * @return Handle
*/ */
public static function getExceptionHandler() public static function getExceptionHandler()
{ {
static $handle; static $handle;
if (!$handle) { if (!$handle) {
// 异常处理handle // 异常处理 handle
$class = Config::get('exception_handle'); $class = Config::get('exception_handle');
if ($class && is_string($class) && class_exists($class) && is_subclass_of($class, "\\think\\exception\\Handle")) {
if ($class && is_string($class) && class_exists($class) &&
is_subclass_of($class, "\\think\\exception\\Handle")
) {
$handle = new $class; $handle = new $class;
} else { } else {
$handle = new Handle; $handle = new Handle;
if ($class instanceof \Closure) {
$handle->setRender($class); if ($class instanceof \Closure) $handle->setRender($class);
}
} }
} }
return $handle; return $handle;
} }
} }

View File

@@ -15,7 +15,9 @@ use think\exception\ClassNotFoundException;
class Loader class Loader
{ {
// 实例
protected static $instance = []; protected static $instance = [];
// 类名映射 // 类名映射
protected static $map = []; protected static $map = [];
@@ -34,7 +36,12 @@ class Loader
// 自动加载的文件 // 自动加载的文件
private static $autoloadFiles = []; private static $autoloadFiles = [];
// 自动加载 /**
* 自动加载
* @access public
* @param string $class 类名
* @return bool
*/
public static function autoload($class) public static function autoload($class)
{ {
// 检测命名空间别名 // 检测命名空间别名
@@ -48,34 +55,34 @@ class Loader
} }
} }
if ($file = self::findFile($class)) { $file = self::findFile($class);
$path = pathinfo($file, PATHINFO_FILENAME);
// Win环境严格区分大小写 $realPath = pathinfo(realpath($file), PATHINFO_FILENAME);
if (IS_WIN && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) {
return false;
}
// 非 Win 环境不严格区分大小写
if ($file && (!IS_WIN || $path == $realPath)) {
__include_file($file); __include_file($file);
return true; return true;
} }
return false;
} }
/** /**
* 查找文件 * 查找文件
* @param $class * @access private
* @param string $class 类名
* @return bool * @return bool
*/ */
private static function findFile($class) private static function findFile($class)
{ {
if (!empty(self::$map[$class])) { // 类库映射
// 类库映射 if (!empty(self::$map[$class])) return self::$map[$class];
return self::$map[$class];
}
// 查找 PSR-4 // 查找 PSR-4
$logicalPathPsr4 = strtr($class, '\\', DS) . EXT; $logicalPathPsr4 = strtr($class, '\\', DS) . EXT;
$first = $class[0]; $first = $class[0];
if (isset(self::$prefixLengthsPsr4[$first])) { if (isset(self::$prefixLengthsPsr4[$first])) {
foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) { foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) {
if (0 === strpos($class, $prefix)) { if (0 === strpos($class, $prefix)) {
@@ -97,9 +104,9 @@ class Loader
// 查找 PSR-0 // 查找 PSR-0
if (false !== $pos = strrpos($class, '\\')) { if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name // namespace class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DS); . strtr(substr($logicalPathPsr4, $pos + 1), '_', DS);
} else { } else {
// PEAR-like class name // PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DS) . EXT; $logicalPathPsr0 = strtr($class, '_', DS) . EXT;
@@ -127,7 +134,13 @@ class Loader
return self::$map[$class] = false; return self::$map[$class] = false;
} }
// 注册classmap /**
* 注册 classmap
* @access public
* @param string|array $class 类名
* @param string $map 映射
* @return void
*/
public static function addClassMap($class, $map = '') public static function addClassMap($class, $map = '')
{ {
if (is_array($class)) { if (is_array($class)) {
@@ -137,7 +150,13 @@ class Loader
} }
} }
// 注册命名空间 /**
* 注册命名空间
* @access public
* @param string|array $namespace 命名空间
* @param string $path 路径
* @return void
*/
public static function addNamespace($namespace, $path = '') public static function addNamespace($namespace, $path = '')
{ {
if (is_array($namespace)) { if (is_array($namespace)) {
@@ -149,84 +168,77 @@ class Loader
} }
} }
// 添加Ps0空间 /**
* 添加 Ps0 空间
* @access private
* @param array|null $prefix 空间前缀
* @param array $paths 路径
* @param bool $prepend 预先设置的优先级更高
* @return void
*/
private static function addPsr0($prefix, $paths, $prepend = false) private static function addPsr0($prefix, $paths, $prepend = false)
{ {
if (!$prefix) { if (!$prefix) {
if ($prepend) { self::$fallbackDirsPsr0 = $prepend ?
self::$fallbackDirsPsr0 = array_merge( array_merge((array) $paths, self::$fallbackDirsPsr0) :
(array) $paths, array_merge(self::$fallbackDirsPsr0, (array) $paths);
self::$fallbackDirsPsr0
);
} else {
self::$fallbackDirsPsr0 = array_merge(
self::$fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset(self::$prefixesPsr0[$first][$prefix])) {
self::$prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
self::$prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
self::$prefixesPsr0[$first][$prefix]
);
} else { } else {
self::$prefixesPsr0[$first][$prefix] = array_merge( $first = $prefix[0];
self::$prefixesPsr0[$first][$prefix],
(array) $paths if (!isset(self::$prefixesPsr0[$first][$prefix])) {
); self::$prefixesPsr0[$first][$prefix] = (array) $paths;
} else {
self::$prefixesPsr0[$first][$prefix] = $prepend ?
array_merge((array) $paths, self::$prefixesPsr0[$first][$prefix]) :
array_merge(self::$prefixesPsr0[$first][$prefix], (array) $paths);
}
} }
} }
// 添加Psr4空间 /**
* 添加 Ps4 空间
* @access private
* @param array|string $prefix 空间前缀
* @param string $paths 路径
* @param bool $prepend 预先设置的优先级更高
* @return void
*/
private static function addPsr4($prefix, $paths, $prepend = false) private static function addPsr4($prefix, $paths, $prepend = false)
{ {
if (!$prefix) { if (!$prefix) {
// Register directories for the root namespace. // Register directories for the root namespace.
if ($prepend) { self::$fallbackDirsPsr4 = $prepend ?
self::$fallbackDirsPsr4 = array_merge( array_merge((array) $paths, self::$fallbackDirsPsr4) :
(array) $paths, array_merge(self::$fallbackDirsPsr4, (array) $paths);
self::$fallbackDirsPsr4
);
} else {
self::$fallbackDirsPsr4 = array_merge(
self::$fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset(self::$prefixDirsPsr4[$prefix])) { } elseif (!isset(self::$prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace. // Register directories for a new namespace.
$length = strlen($prefix); $length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) { if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); throw new \InvalidArgumentException(
"A non-empty PSR-4 prefix must end with a namespace separator."
);
} }
self::$prefixLengthsPsr4[$prefix[0]][$prefix] = $length; self::$prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
self::$prefixDirsPsr4[$prefix] = (array) $paths; self::$prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
self::$prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
self::$prefixDirsPsr4[$prefix]
);
} else { } else {
// Append directories for an already registered namespace. self::$prefixDirsPsr4[$prefix] = $prepend ?
self::$prefixDirsPsr4[$prefix] = array_merge( // Prepend directories for an already registered namespace.
self::$prefixDirsPsr4[$prefix], array_merge((array) $paths, self::$prefixDirsPsr4[$prefix]) :
(array) $paths // Append directories for an already registered namespace.
); array_merge(self::$prefixDirsPsr4[$prefix], (array) $paths);
} }
} }
// 注册命名空间别名 /**
* 注册命名空间别名
* @access public
* @param array|string $namespace 命名空间
* @param string $original 源文件
* @return void
*/
public static function addNamespaceAlias($namespace, $original = '') public static function addNamespaceAlias($namespace, $original = '')
{ {
if (is_array($namespace)) { if (is_array($namespace)) {
@@ -236,32 +248,41 @@ class Loader
} }
} }
// 注册自动加载机制 /**
public static function register($autoload = '') * 注册自动加载机制
* @access public
* @param callable $autoload 自动加载处理方法
* @return void
*/
public static function register($autoload = null)
{ {
// 注册系统自动加载 // 注册系统自动加载
spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true); spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);
// 加载类库映射文件
if (is_file(RUNTIME_PATH . 'classmap' . EXT)) {
self::addClassMap(__include_file(RUNTIME_PATH . 'classmap' . EXT));
}
// Composer 自动加载支持
if (is_dir(VENDOR_PATH . 'composer')) self::registerComposerLoader();
// 注册命名空间定义 // 注册命名空间定义
self::addNamespace([ self::addNamespace([
'think' => LIB_PATH . 'think' . DS, 'think' => LIB_PATH . 'think' . DS,
'behavior' => LIB_PATH . 'behavior' . DS, 'behavior' => LIB_PATH . 'behavior' . DS,
'traits' => LIB_PATH . 'traits' . DS, 'traits' => LIB_PATH . 'traits' . DS,
]); ]);
// 加载类库映射文件
if (is_file(RUNTIME_PATH . 'classmap' . EXT)) {
self::addClassMap(__include_file(RUNTIME_PATH . 'classmap' . EXT));
}
// Composer自动加载支持 // 自动加载 extend 目录
if (is_dir(VENDOR_PATH . 'composer')) {
self::registerComposerLoader();
}
// 自动加载extend目录
self::$fallbackDirsPsr4[] = rtrim(EXTEND_PATH, DS); self::$fallbackDirsPsr4[] = rtrim(EXTEND_PATH, DS);
} }
// 注册composer自动加载 /**
* 注册 composer 自动加载
* @access private
* @return void
*/
private static function registerComposerLoader() private static function registerComposerLoader()
{ {
if (is_file(VENDOR_PATH . 'composer/autoload_namespaces.php')) { if (is_file(VENDOR_PATH . 'composer/autoload_namespaces.php')) {
@@ -280,9 +301,7 @@ class Loader
if (is_file(VENDOR_PATH . 'composer/autoload_classmap.php')) { if (is_file(VENDOR_PATH . 'composer/autoload_classmap.php')) {
$classMap = require VENDOR_PATH . 'composer/autoload_classmap.php'; $classMap = require VENDOR_PATH . 'composer/autoload_classmap.php';
if ($classMap) { if ($classMap) self::addClassMap($classMap);
self::addClassMap($classMap);
}
} }
if (is_file(VENDOR_PATH . 'composer/autoload_files.php')) { if (is_file(VENDOR_PATH . 'composer/autoload_files.php')) {
@@ -297,20 +316,20 @@ class Loader
} }
/** /**
* 导入所需的类库 同javaImport 本函数有缓存功能 * 导入所需的类库 同 JavaImport 本函数有缓存功能
* @access public
* @param string $class 类库命名空间字符串 * @param string $class 类库命名空间字符串
* @param string $baseUrl 起始路径 * @param string $baseUrl 起始路径
* @param string $ext 导入的文件扩展名 * @param string $ext 导入的文件扩展名
* @return boolean * @return bool
*/ */
public static function import($class, $baseUrl = '', $ext = EXT) public static function import($class, $baseUrl = '', $ext = EXT)
{ {
static $_file = []; static $_file = [];
$key = $class . $baseUrl; $key = $class . $baseUrl;
$class = str_replace(['.', '#'], [DS, '.'], $class); $class = str_replace(['.', '#'], [DS, '.'], $class);
if (isset($_file[$key])) {
return true; if (isset($_file[$key])) return true;
}
if (empty($baseUrl)) { if (empty($baseUrl)) {
list($name, $class) = explode(DS, $class, 2); list($name, $class) = explode(DS, $class, 2);
@@ -319,7 +338,7 @@ class Loader
// 注册的命名空间 // 注册的命名空间
$baseUrl = self::$prefixDirsPsr4[$name . '\\']; $baseUrl = self::$prefixDirsPsr4[$name . '\\'];
} elseif ('@' == $name) { } elseif ('@' == $name) {
//加载当前模块应用类库 // 加载当前模块应用类库
$baseUrl = App::$modulePath; $baseUrl = App::$modulePath;
} elseif (is_dir(EXTEND_PATH . $name)) { } elseif (is_dir(EXTEND_PATH . $name)) {
$baseUrl = EXTEND_PATH . $name . DS; $baseUrl = EXTEND_PATH . $name . DS;
@@ -330,32 +349,34 @@ class Loader
} elseif (substr($baseUrl, -1) != DS) { } elseif (substr($baseUrl, -1) != DS) {
$baseUrl .= DS; $baseUrl .= DS;
} }
// 如果类存在 则导入类库文件
// 如果类存在则导入类库文件
if (is_array($baseUrl)) { if (is_array($baseUrl)) {
foreach ($baseUrl as $path) { foreach ($baseUrl as $path) {
$filename = $path . DS . $class . $ext; $filename = $path . DS . $class . $ext;
if (is_file($filename)) {
break; if (is_file($filename)) break;
}
} }
} else { } else {
$filename = $baseUrl . $class . $ext; $filename = $baseUrl . $class . $ext;
} }
if (!empty($filename) && is_file($filename)) { if (!empty($filename) &&
// 开启调试模式Win环境严格区分大小写 is_file($filename) &&
if (IS_WIN && pathinfo($filename, PATHINFO_FILENAME) != pathinfo(realpath($filename), PATHINFO_FILENAME)) { (!IS_WIN || pathinfo($filename, PATHINFO_FILENAME) == pathinfo(realpath($filename), PATHINFO_FILENAME))
return false; ) {
}
__include_file($filename); __include_file($filename);
$_file[$key] = true; $_file[$key] = true;
return true; return true;
} }
return false; return false;
} }
/** /**
* 实例化(分层)模型 * 实例化(分层)模型
* @access public
* @param string $name Model名称 * @param string $name Model名称
* @param string $layer 业务层名称 * @param string $layer 业务层名称
* @param bool $appendSuffix 是否添加类名后缀 * @param bool $appendSuffix 是否添加类名后缀
@@ -365,27 +386,30 @@ class Loader
*/ */
public static function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common') public static function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common')
{ {
$guid = $name . $layer; $uid = $name . $layer;
if (isset(self::$instance[$guid])) {
return self::$instance[$guid]; if (isset(self::$instance[$uid])) return self::$instance[$uid];
}
list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix); list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix);
if (class_exists($class)) { if (class_exists($class)) {
$model = new $class(); $model = new $class();
} else { } else {
$class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class); $class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class);
if (class_exists($class)) { if (class_exists($class)) {
$model = new $class(); $model = new $class();
} else { } else {
throw new ClassNotFoundException('class not exists:' . $class, $class); throw new ClassNotFoundException('class not exists:' . $class, $class);
} }
} }
self::$instance[$guid] = $model;
return $model; return self::$instance[$uid] = $model;
} }
/** /**
* 实例化(分层)控制器 格式:[模块名/]控制器名 * 实例化(分层)控制器 格式:[模块名/]控制器名
* @access public
* @param string $name 资源地址 * @param string $name 资源地址
* @param string $layer 控制层名称 * @param string $layer 控制层名称
* @param bool $appendSuffix 是否添加类名后缀 * @param bool $appendSuffix 是否添加类名后缀
@@ -396,17 +420,23 @@ class Loader
public static function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '') public static function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '')
{ {
list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix); list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix);
if (class_exists($class)) {
return App::invokeClass($class); if (class_exists($class)) return App::invokeClass($class);
} elseif ($empty && class_exists($emptyClass = self::parseClass($module, $layer, $empty, $appendSuffix))) {
return new $emptyClass(Request::instance()); if ($empty) {
} else { $emptyClass = self::parseClass($module, $layer, $empty, $appendSuffix);
throw new ClassNotFoundException('class not exists:' . $class, $class);
if (class_exists($emptyClass)) {
return new $emptyClass(Request::instance());
}
} }
throw new ClassNotFoundException('class not exists:' . $class, $class);
} }
/** /**
* 实例化验证类 格式:[模块名/]验证器名 * 实例化验证类 格式:[模块名/]验证器名
* @access public
* @param string $name 资源地址 * @param string $name 资源地址
* @param string $layer 验证层名称 * @param string $layer 验证层名称
* @param bool $appendSuffix 是否添加类名后缀 * @param bool $appendSuffix 是否添加类名后缀
@@ -417,30 +447,31 @@ class Loader
public static function validate($name = '', $layer = 'validate', $appendSuffix = false, $common = 'common') public static function validate($name = '', $layer = 'validate', $appendSuffix = false, $common = 'common')
{ {
$name = $name ?: Config::get('default_validate'); $name = $name ?: Config::get('default_validate');
if (empty($name)) { if (empty($name)) return new Validate;
return new Validate;
} $uid = $name . $layer;
$guid = $name . $layer; if (isset(self::$instance[$uid])) return self::$instance[$uid];
if (isset(self::$instance[$guid])) {
return self::$instance[$guid];
}
list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix); list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix);
if (class_exists($class)) { if (class_exists($class)) {
$validate = new $class; $validate = new $class;
} else { } else {
$class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class); $class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class);
if (class_exists($class)) { if (class_exists($class)) {
$validate = new $class; $validate = new $class;
} else { } else {
throw new ClassNotFoundException('class not exists:' . $class, $class); throw new ClassNotFoundException('class not exists:' . $class, $class);
} }
} }
self::$instance[$guid] = $validate;
return $validate; return self::$instance[$uid] = $validate;
} }
/** /**
* 解析模块和类名 * 解析模块和类名
* @access protected
* @param string $name 资源地址 * @param string $name 资源地址
* @param string $layer 验证层名称 * @param string $layer 验证层名称
* @param bool $appendSuffix 是否添加类名后缀 * @param bool $appendSuffix 是否添加类名后缀
@@ -457,15 +488,18 @@ class Loader
} else { } else {
$module = Request::instance()->module(); $module = Request::instance()->module();
} }
$class = self::parseClass($module, $layer, $name, $appendSuffix); $class = self::parseClass($module, $layer, $name, $appendSuffix);
} }
return [$module, $class]; return [$module, $class];
} }
/** /**
* 数据库初始化 并取得数据库类实例 * 数据库初始化 并取得数据库类实例
* @param mixed $config 数据库配置 * @access public
* @param bool|string $name 连接标识 true 强制重新连接 * @param mixed $config 数据库配置
* @param bool|string $name 连接标识 true 强制重新连接
* @return \think\db\Connection * @return \think\db\Connection
*/ */
public static function db($config = [], $name = false) public static function db($config = [], $name = false)
@@ -475,6 +509,7 @@ class Loader
/** /**
* 远程调用模块的操作方法 参数格式 [模块/控制器/]操作 * 远程调用模块的操作方法 参数格式 [模块/控制器/]操作
* @access public
* @param string $url 调用地址 * @param string $url 调用地址
* @param string|array $vars 调用参数 支持字符串和数组 * @param string|array $vars 调用参数 支持字符串和数组
* @param string $layer 要调用的控制层名称 * @param string $layer 要调用的控制层名称
@@ -487,6 +522,7 @@ class Loader
$action = $info['basename']; $action = $info['basename'];
$module = '.' != $info['dirname'] ? $info['dirname'] : Request::instance()->controller(); $module = '.' != $info['dirname'] ? $info['dirname'] : Request::instance()->controller();
$class = self::controller($module, $layer, $appendSuffix); $class = self::controller($module, $layer, $appendSuffix);
if ($class) { if ($class) {
if (is_scalar($vars)) { if (is_scalar($vars)) {
if (strpos($vars, '=')) { if (strpos($vars, '=')) {
@@ -495,15 +531,19 @@ class Loader
$vars = [$vars]; $vars = [$vars];
} }
} }
return App::invokeMethod([$class, $action . Config::get('action_suffix')], $vars); return App::invokeMethod([$class, $action . Config::get('action_suffix')], $vars);
} }
return false;
} }
/** /**
* 字符串命名风格转换 * 字符串命名风格转换
* type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格 * type 0 将 Java 风格转换为 C 的风格 1 将 C 风格转换为 Java 的风格
* @param string $name 字符串 * @access public
* @param integer $type 转换类型 * @param string $name 字符串
* @param integer $type 转换类型
* @param bool $ucfirst 首字母是否大写(驼峰规则) * @param bool $ucfirst 首字母是否大写(驼峰规则)
* @return string * @return string
*/ */
@@ -513,31 +553,38 @@ class Loader
$name = preg_replace_callback('/_([a-zA-Z])/', function ($match) { $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
return strtoupper($match[1]); return strtoupper($match[1]);
}, $name); }, $name);
return $ucfirst ? ucfirst($name) : lcfirst($name); return $ucfirst ? ucfirst($name) : lcfirst($name);
} else {
return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
} }
return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
} }
/** /**
* 解析应用类的类名 * 解析应用类的类名
* @param string $module 模块名 * @access public
* @param string $layer 层名 controller model ... * @param string $module 模块名
* @param string $name 类名 * @param string $layer 层名 controller model ...
* @param bool $appendSuffix * @param string $name 类名
* @param bool $appendSuffix 是否添加类名后缀
* @return string * @return string
*/ */
public static function parseClass($module, $layer, $name, $appendSuffix = false) public static function parseClass($module, $layer, $name, $appendSuffix = false)
{ {
$name = str_replace(['/', '.'], '\\', $name);
$array = explode('\\', $name); $array = explode('\\', str_replace(['/', '.'], '\\', $name));
$class = self::parseName(array_pop($array), 1) . (App::$suffix || $appendSuffix ? ucfirst($layer) : ''); $class = self::parseName(array_pop($array), 1);
$class = $class . (App::$suffix || $appendSuffix ? ucfirst($layer) : '');
$path = $array ? implode('\\', $array) . '\\' : ''; $path = $array ? implode('\\', $array) . '\\' : '';
return App::$namespace . '\\' . ($module ? $module . '\\' : '') . $layer . '\\' . $path . $class;
return App::$namespace . '\\' .
($module ? $module . '\\' : '') .
$layer . '\\' . $path . $class;
} }
/** /**
* 初始化类的实例 * 初始化类的实例
* @access public
* @return void * @return void
*/ */
public static function clearInstance() public static function clearInstance()
@@ -546,10 +593,11 @@ class Loader
} }
} }
// 作用范围隔离
/** /**
* 作用范围隔离 * include
* * @param string $file 文件路径
* @param $file
* @return mixed * @return mixed
*/ */
function __include_file($file) function __include_file($file)
@@ -557,6 +605,11 @@ function __include_file($file)
return include $file; return include $file;
} }
/**
* require
* @param string $file 文件路径
* @return mixed
*/
function __require_file($file) function __require_file($file)
{ {
return require $file; return require $file;

View File

@@ -1,5 +1,4 @@
<?php <?php
/** /**
* 用法: * 用法:
* load_trait('controller/Jump'); * load_trait('controller/Jump');
@@ -27,20 +26,23 @@ trait Jump
/** /**
* 操作成功跳转的快捷方法 * 操作成功跳转的快捷方法
* @access protected * @access protected
* @param mixed $msg 提示信息 * @param mixed $msg 提示信息
* @param string $url 跳转的URL地址 * @param string $url 跳转的 URL 地址
* @param mixed $data 返回的数据 * @param mixed $data 返回的数据
* @param integer $wait 跳转等待时间 * @param int $wait 跳转等待时间
* @param array $header 发送的Header信息 * @param array $header 发送的 Header 信息
* @return void * @return void
* @throws HttpResponseException
*/ */
protected function success($msg = '', $url = null, $data = '', $wait = 3, array $header = []) protected function success($msg = '', $url = null, $data = '', $wait = 3, array $header = [])
{ {
if (is_null($url) && !is_null(Request::instance()->server('HTTP_REFERER'))) { if (is_null($url) && !is_null(Request::instance()->server('HTTP_REFERER'))) {
$url = Request::instance()->server('HTTP_REFERER'); $url = Request::instance()->server('HTTP_REFERER');
} elseif ('' !== $url) { } elseif ('' !== $url && !strpos($url, '://') && 0 !== strpos($url, '/')) {
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : Url::build($url); $url = Url::build($url);
} }
$type = $this->getResponseType();
$result = [ $result = [
'code' => 1, 'code' => 1,
'msg' => $msg, 'msg' => $msg,
@@ -49,32 +51,39 @@ trait Jump
'wait' => $wait, 'wait' => $wait,
]; ];
$type = $this->getResponseType();
if ('html' == strtolower($type)) { if ('html' == strtolower($type)) {
$result = ViewTemplate::instance(Config::get('template'), Config::get('view_replace_str')) $template = Config::get('template');
$view = Config::get('view_replace_str');
$result = ViewTemplate::instance($template, $view)
->fetch(Config::get('dispatch_success_tmpl'), $result); ->fetch(Config::get('dispatch_success_tmpl'), $result);
} }
$response = Response::create($result, $type)->header($header); $response = Response::create($result, $type)->header($header);
throw new HttpResponseException($response); throw new HttpResponseException($response);
} }
/** /**
* 操作错误跳转的快捷方法 * 操作错误跳转的快捷方法
* @access protected * @access protected
* @param mixed $msg 提示信息 * @param mixed $msg 提示信息
* @param string $url 跳转的URL地址 * @param string $url 跳转的 URL 地址
* @param mixed $data 返回的数据 * @param mixed $data 返回的数据
* @param integer $wait 跳转等待时间 * @param int $wait 跳转等待时间
* @param array $header 发送的Header信息 * @param array $header 发送的 Header 信息
* @return void * @return void
* @throws HttpResponseException
*/ */
protected function error($msg = '', $url = null, $data = '', $wait = 3, array $header = []) protected function error($msg = '', $url = null, $data = '', $wait = 3, array $header = [])
{ {
if (is_null($url)) { if (is_null($url)) {
$url = Request::instance()->isAjax() ? '' : 'javascript:history.back(-1);'; $url = Request::instance()->isAjax() ? '' : 'javascript:history.back(-1);';
} elseif ('' !== $url) { } elseif ('' !== $url && !strpos($url, '://') && 0 !== strpos($url, '/')) {
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : Url::build($url); $url = Url::build($url);
} }
$type = $this->getResponseType();
$result = [ $result = [
'code' => 0, 'code' => 0,
'msg' => $msg, 'msg' => $msg,
@@ -83,24 +92,29 @@ trait Jump
'wait' => $wait, 'wait' => $wait,
]; ];
$type = $this->getResponseType();
if ('html' == strtolower($type)) { if ('html' == strtolower($type)) {
$result = ViewTemplate::instance(Config::get('template'), Config::get('view_replace_str')) $template = Config::get('template');
$view = Config::get('view_replace_str');
$result = ViewTemplate::instance($template, $view)
->fetch(Config::get('dispatch_error_tmpl'), $result); ->fetch(Config::get('dispatch_error_tmpl'), $result);
} }
$response = Response::create($result, $type)->header($header); $response = Response::create($result, $type)->header($header);
throw new HttpResponseException($response); throw new HttpResponseException($response);
} }
/** /**
* 返回封装后的API数据到客户端 * 返回封装后的 API 数据到客户端
* @access protected * @access protected
* @param mixed $data 要返回的数据 * @param mixed $data 要返回的数据
* @param integer $code 返回的code * @param int $code 返回的 code
* @param mixed $msg 提示信息 * @param mixed $msg 提示信息
* @param string $type 返回数据格式 * @param string $type 返回数据格式
* @param array $header 发送的Header信息 * @param array $header 发送的 Header 信息
* @return void * @return void
* @throws HttpResponseException
*/ */
protected function result($data, $code = 0, $msg = '', $type = '', array $header = []) protected function result($data, $code = 0, $msg = '', $type = '', array $header = [])
{ {
@@ -112,37 +126,42 @@ trait Jump
]; ];
$type = $type ?: $this->getResponseType(); $type = $type ?: $this->getResponseType();
$response = Response::create($result, $type)->header($header); $response = Response::create($result, $type)->header($header);
throw new HttpResponseException($response); throw new HttpResponseException($response);
} }
/** /**
* URL重定向 * URL 重定向
* @access protected * @access protected
* @param string $url 跳转的URL表达式 * @param string $url 跳转的 URL 表达式
* @param array|integer $params 其它URL参数 * @param array|int $params 其它 URL 参数
* @param integer $code http code * @param int $code http code
* @param array $with 隐式传参 * @param array $with 隐式传参
* @return void * @return void
* @throws HttpResponseException
*/ */
protected function redirect($url, $params = [], $code = 302, $with = []) protected function redirect($url, $params = [], $code = 302, $with = [])
{ {
$response = new Redirect($url);
if (is_integer($params)) { if (is_integer($params)) {
$code = $params; $code = $params;
$params = []; $params = [];
} }
$response = new Redirect($url);
$response->code($code)->params($params)->with($with); $response->code($code)->params($params)->with($with);
throw new HttpResponseException($response); throw new HttpResponseException($response);
} }
/** /**
* 获取当前的response 输出类型 * 获取当前的 response 输出类型
* @access protected * @access protected
* @return string * @return string
*/ */
protected function getResponseType() protected function getResponseType()
{ {
$isAjax = Request::instance()->isAjax(); return Request::instance()->isAjax()
return $isAjax ? Config::get('default_ajax_return') : Config::get('default_return_type'); ? Config::get('default_ajax_return')
: Config::get('default_return_type');
} }
} }

View File

@@ -10,7 +10,6 @@ use think\Model;
*/ */
trait SoftDelete trait SoftDelete
{ {
/** /**
* 判断当前实例是否被软删除 * 判断当前实例是否被软删除
* @access public * @access public
@@ -19,22 +18,18 @@ trait SoftDelete
public function trashed() public function trashed()
{ {
$field = $this->getDeleteTimeField(); $field = $this->getDeleteTimeField();
if (!empty($this->data[$field])) {
return true; return !empty($this->data[$field]);
}
return false;
} }
/** /**
* 查询软删除数据 * 查询包含软删除数据
* @access public * @access public
* @return Query * @return Query
*/ */
public static function withTrashed() public static function withTrashed()
{ {
$model = new static(); return (new static)->getQuery();
$field = $model->getDeleteTimeField(true);
return $model->getQuery();
} }
/** /**
@@ -46,31 +41,28 @@ trait SoftDelete
{ {
$model = new static(); $model = new static();
$field = $model->getDeleteTimeField(true); $field = $model->getDeleteTimeField(true);
return $model->getQuery()
->useSoftDelete($field, ['not null', '']); return $model->getQuery()->useSoftDelete($field, ['not null', '']);
} }
/** /**
* 删除当前的记录 * 删除当前的记录
* @access public * @access public
* @param bool $force 是否强制删除 * @param bool $force 是否强制删除
* @return integer * @return integer
*/ */
public function delete($force = false) public function delete($force = false)
{ {
if (false === $this->trigger('before_delete', $this)) { if (false === $this->trigger('before_delete', $this)) return false;
return false;
}
$name = $this->getDeleteTimeField(); $name = $this->getDeleteTimeField();
if (!$force) { if (!$force) {
// 软删除 // 软删除
$this->data[$name] = $this->autoWriteTimestamp($name); $this->data[$name] = $this->autoWriteTimestamp($name);
$result = $this->isUpdate()->save(); $result = $this->isUpdate()->save();
} else { } else {
// 删除条件 // 强制删除当前模型数据
$where = $this->getWhere(); $result = $this->getQuery()->where($this->getWhere())->delete();
// 删除当前模型数据
$result = $this->getQuery()->where($where)->delete();
} }
// 关联删除 // 关联删除
@@ -78,47 +70,48 @@ trait SoftDelete
foreach ($this->relationWrite as $key => $name) { foreach ($this->relationWrite as $key => $name) {
$name = is_numeric($key) ? $name : $key; $name = is_numeric($key) ? $name : $key;
$model = $this->getAttr($name); $model = $this->getAttr($name);
if ($model instanceof Model) {
$model->delete($force); if ($model instanceof Model) $model->delete();
}
} }
} }
$this->trigger('after_delete', $this); $this->trigger('after_delete', $this);
// 清空原始数据 // 清空原始数据
$this->origin = []; $this->origin = [];
return $result; return $result;
} }
/** /**
* 删除记录 * 删除记录
* @access public * @access public
* @param mixed $data 主键列表 支持闭包查询条件 * @param mixed $data 主键列表(支持闭包查询条件)
* @param bool $force 是否强制删除 * @param bool $force 是否强制删除
* @return integer 成功删除的记录数 * @return integer 成功删除的记录数
*/ */
public static function destroy($data, $force = false) public static function destroy($data, $force = false)
{ {
if (is_null($data)) return 0;
// 包含软删除数据 // 包含软删除数据
$query = self::withTrashed(); $query = self::withTrashed();
if (is_array($data) && key($data) !== 0) { if (is_array($data) && key($data) !== 0) {
$query->where($data); $query->where($data);
$data = null; $data = null;
} elseif ($data instanceof \Closure) { } elseif ($data instanceof \Closure) {
call_user_func_array($data, [ & $query]); call_user_func_array($data, [&$query]);
$data = null; $data = null;
} elseif (is_null($data)) {
return 0;
} }
$resultSet = $query->select($data); $count = 0;
$count = 0; if ($resultSet = $query->select($data)) {
if ($resultSet) {
foreach ($resultSet as $data) { foreach ($resultSet as $data) {
$result = $data->delete($force); $result = $data->delete($force);
$count += $result; $count += $result;
} }
} }
return $count; return $count;
} }
@@ -130,11 +123,13 @@ trait SoftDelete
*/ */
public function restore($where = []) public function restore($where = [])
{ {
$name = $this->getDeleteTimeField();
if (empty($where)) { if (empty($where)) {
$pk = $this->getPk(); $pk = $this->getPk();
$where[$pk] = $this->getData($pk); $where[$pk] = $this->getData($pk);
} }
$name = $this->getDeleteTimeField();
// 恢复删除 // 恢复删除
return $this->getQuery() return $this->getQuery()
->useSoftDelete($name, ['not null', '']) ->useSoftDelete($name, ['not null', ''])
@@ -146,30 +141,32 @@ trait SoftDelete
* 查询默认不包含软删除数据 * 查询默认不包含软删除数据
* @access protected * @access protected
* @param Query $query 查询对象 * @param Query $query 查询对象
* @return void * @return Query
*/ */
protected function base($query) protected function base($query)
{ {
$field = $this->getDeleteTimeField(true); return $query->useSoftDelete($this->getDeleteTimeField(true));
$query->useSoftDelete($field);
} }
/** /**
* 获取软删除字段 * 获取软删除字段
* @access public * @access public
* @param bool $read 是否查询操作 写操作的时候会自动去掉表别名 * @param bool $read 是否查询操作(写操作的时候会自动去掉表别名)
* @return string * @return string
*/ */
protected function getDeleteTimeField($read = false) protected function getDeleteTimeField($read = false)
{ {
$field = property_exists($this, 'deleteTime') && isset($this->deleteTime) ? $this->deleteTime : 'delete_time'; $field = property_exists($this, 'deleteTime') && isset($this->deleteTime) ?
if (!strpos($field, '.')) { $this->deleteTime :
$field = '__TABLE__.' . $field; 'delete_time';
}
if (!strpos($field, '.')) $field = '__TABLE__.' . $field;
if (!$read && strpos($field, '.')) { if (!$read && strpos($field, '.')) {
$array = explode('.', $field); $array = explode('.', $field);
$field = array_pop($array); $field = array_pop($array);
} }
return $field; return $field;
} }
} }

View File

@@ -15,31 +15,40 @@ use think\Exception;
trait Instance trait Instance
{ {
/**
* @var null|static 实例对象
*/
protected static $instance = null; protected static $instance = null;
/** /**
* @param array $options * 获取示例
* @param array $options 实例配置
* @return static * @return static
*/ */
public static function instance($options = []) public static function instance($options = [])
{ {
if (is_null(self::$instance)) { if (is_null(self::$instance)) self::$instance = new self($options);
self::$instance = new self($options);
}
return self::$instance; return self::$instance;
} }
// 静态调用 /**
public static function __callStatic($method, $params) * 静态调用
* @param string $method 调用方法
* @param array $params 调用参数
* @return mixed
* @throws Exception
*/
public static function __callStatic($method, array $params)
{ {
if (is_null(self::$instance)) { if (is_null(self::$instance)) self::$instance = new self();
self::$instance = new self();
}
$call = substr($method, 1); $call = substr($method, 1);
if (0 === strpos($method, '_') && is_callable([self::$instance, $call])) {
return call_user_func_array([self::$instance, $call], $params); if (0 !== strpos($method, '_') || !is_callable([self::$instance, $call])) {
} else {
throw new Exception("method not exists:" . $method); throw new Exception("method not exists:" . $method);
} }
return call_user_func_array([self::$instance, $call], $params);
} }
} }

View File

@@ -12,7 +12,8 @@
namespace think; namespace think;
// ThinkPHP 引导文件 // ThinkPHP 引导文件
// 加载基础文件 // 1. 加载基础文件
require __DIR__ . '/base.php'; require __DIR__ . '/base.php';
// 执行应用
// 2. 执行应用
App::run()->send(); App::run()->send();