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 * @param array|string $dispatch 调度信息 * @param string $type 调度类型 * @return void */ public static function dispatch($dispatch, $type = 'module') { self::$dispatch = ['type' => $type, $type => $dispatch]; } /** * 执行函数或者闭包方法 支持参数调用 * @access public * @param string|array|\Closure $function 函数或者闭包 * @param array $vars 变量 * @return mixed */ 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); } /** * 调用反射执行类的方法 支持参数绑定 * @access public * @param string|array $method 方法 * @param array $vars 变量 * @return mixed */ public static function invokeMethod($method, $vars = []) { if (is_array($method)) { $class = is_object($method[0]) ? $method[0] : self::invokeClass($method[0]); $reflect = new \ReflectionMethod($class, $method[1]); } else { // 静态方法 $reflect = new \ReflectionMethod($method); } $args = self::bindParams($reflect, $vars); self::$debug && Log::record('[ RUN ] ' . $reflect->class . '->' . $reflect->name . '[ ' . $reflect->getFileName() . ' ]', 'info'); return $reflect->invokeArgs(isset($class) ? $class : null, $args); } /** * 调用反射执行类的实例化 支持依赖注入 * @access public * @param string $class 类名 * @param array $vars 变量 * @return mixed */ public static function invokeClass($class, $vars = []) { $reflect = new \ReflectionClass($class); $constructor = $reflect->getConstructor(); $args = $constructor ? self::bindParams($constructor, $vars) : []; return $reflect->newInstanceArgs($args); } /** * 绑定参数 * @access private * @param \ReflectionMethod|\ReflectionFunction $reflect 反射类 * @param array $vars 变量 * @return array */ private static function bindParams($reflect, $vars = []) { // 自动获取请求变量 if (empty($vars)) { $vars = Config::get('url_param_type') ? Request::instance()->route() : Request::instance()->param(); } $args = []; if ($reflect->getNumberOfParameters() > 0) { // 判断数组类型 数字数组时按顺序绑定参数 reset($vars); $type = key($vars) === 0 ? 1 : 0; foreach ($reflect->getParameters() as $param) { $args[] = self::getParamValue($param, $vars, $type); } } return $args; } /** * 获取参数值 * @access private * @param \ReflectionParameter $param 参数 * @param array $vars 变量 * @param string $type 类别 * @return array */ private static function getParamValue($param, &$vars, $type) { $name = $param->getName(); $class = $param->getClass(); if ($class) { $className = $class->getName(); $bind = Request::instance()->$name; if ($bind instanceof $className) { $result = $bind; } else { if (method_exists($className, 'invoke')) { $method = new \ReflectionMethod($className, 'invoke'); if ($method->isPublic() && $method->isStatic()) { return $className::invoke(Request::instance()); } } $result = method_exists($className, 'instance') ? $className::instance() : new $className; } } elseif (1 == $type && !empty($vars)) { $result = array_shift($vars); } elseif (0 == $type && isset($vars[$name])) { $result = $vars[$name]; } elseif ($param->isDefaultValueAvailable()) { $result = $param->getDefaultValue(); } else { throw new \InvalidArgumentException('method param miss:' . $name); } return $result; } /** * 执行调用分发 * @access protected * @param array $dispatch 调用信息 * @param array $config 配置信息 * @return Response|mixed * @throws \InvalidArgumentException */ protected static function exec($dispatch, $config) { 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': // 执行控制器操作 $vars = array_merge(Request::instance()->param(), $dispatch['var']); $data = Loader::action( $dispatch['controller'], $vars, $config['url_controller_layer'], $config['controller_suffix'] ); break; case 'method': // 回调方法 $vars = array_merge(Request::instance()->param(), $dispatch['var']); $data = self::invokeMethod($dispatch['method'], $vars); break; case 'function': // 闭包 $data = self::invokeFunction($dispatch['function']); break; case 'response': // Response 实例 $data = $dispatch['response']; break; default: throw new \InvalidArgumentException('dispatch type not support'); } return $data; } /** * 执行模块 * @access public * @param array $result 模块/控制器/操作 * @param array $config 配置参数 * @param bool $convert 是否自动转换控制器和操作名 * @return mixed * @throws HttpException */ 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); // 模块请求缓存检查 $request->cache( $config['request_cache'], $config['request_cache_expire'], $config['request_cache_except'] ); } else { throw new HttpException(404, 'module not exists:' . $module); } } else { // 单一模块部署 $module = ''; $request->module($module); } // 设置默认过滤机制 $request->filter($config['default_filter']); // 当前模块路径 App::$modulePath = APP_PATH . ($module ? $module . DS : ''); // 是否自动转换控制器和操作名 $convert = is_bool($convert) ? $convert : $config['url_convert']; // 获取控制器名 $controller = strip_tags($result[1] ?: $config['default_controller']); if (!preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) { throw new HttpException(404, 'controller not exists:' . $controller); } $controller = $convert ? strtolower($controller) : $controller; // 获取操作名 $actionName = strip_tags($result[2] ?: $config['default_action']); if (!empty($config['action_convert'])) { $actionName = Loader::parseName($actionName, 1); } else { $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'] ); } catch (ClassNotFoundException $e) { throw new HttpException(404, 'controller not exists:' . $e->getClass()); } // 获取当前操作名 $action = $actionName . $config['action_suffix']; $vars = []; if (is_callable([$instance, $action])) { // 执行操作方法 $call = [$instance, $action]; // 严格获取当前操作方法名 $reflect = new \ReflectionMethod($instance, $action); $methodName = $reflect->getName(); $suffix = $config['action_suffix']; $actionName = $suffix ? substr($methodName, 0, -strlen($suffix)) : $methodName; $request->action($actionName); } elseif (is_callable([$instance, '_empty'])) { // 空操作 $call = [$instance, '_empty']; $vars = [$actionName]; } else { // 操作不存在 throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()'); } Hook::listen('action_begin', $call); return self::invokeMethod($call, $vars); } /** * URL路由检测(根据PATH_INFO) * @access public * @param \think\Request $request 请求实例 * @param array $config 配置信息 * @return array * @throws \think\Exception */ 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'; 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; 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 RouteNotFoundException(); } } // 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索 if (false === $result) { $result = Route::parseUrl($path, $depr, $config['controller_auto_search']); } return $result; } /** * 设置应用的路由检测机制 * @access public * @param bool $route 是否需要检测路由 * @param bool $must 是否强制检测路由 * @return void */ public static function route($route, $must = false) { self::$routeCheck = $route; self::$routeMust = $must; } } 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 * @param array|string $dispatch 调度信息 * @param string $type 调度类型 * @return void */ public static function dispatch($dispatch, $type = 'module') { self::$dispatch = ['type' => $type, $type => $dispatch]; } /** * 执行函数或者闭包方法 支持参数调用 * @access public * @param string|array|\Closure $function 函数或者闭包 * @param array $vars 变量 * @return mixed */ 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); } /** * 调用反射执行类的方法 支持参数绑定 * @access public * @param string|array $method 方法 * @param array $vars 变量 * @return mixed */ public static function invokeMethod($method, $vars = []) { if (is_array($method)) { $class = is_object($method[0]) ? $method[0] : self::invokeClass($method[0]); $reflect = new \ReflectionMethod($class, $method[1]); } else { // 静态方法 $reflect = new \ReflectionMethod($method); } $args = self::bindParams($reflect, $vars); self::$debug && Log::record('[ RUN ] ' . $reflect->class . '->' . $reflect->name . '[ ' . $reflect->getFileName() . ' ]', 'info'); return $reflect->invokeArgs(isset($class) ? $class : null, $args); } /** * 调用反射执行类的实例化 支持依赖注入 * @access public * @param string $class 类名 * @param array $vars 变量 * @return mixed */ public static function invokeClass($class, $vars = []) { $reflect = new \ReflectionClass($class); $constructor = $reflect->getConstructor(); $args = $constructor ? self::bindParams($constructor, $vars) : []; return $reflect->newInstanceArgs($args); } /** * 绑定参数 * @access private * @param \ReflectionMethod|\ReflectionFunction $reflect 反射类 * @param array $vars 变量 * @return array */ private static function bindParams($reflect, $vars = []) { // 自动获取请求变量 if (empty($vars)) { $vars = Config::get('url_param_type') ? Request::instance()->route() : Request::instance()->param(); } $args = []; if ($reflect->getNumberOfParameters() > 0) { // 判断数组类型 数字数组时按顺序绑定参数 reset($vars); $type = key($vars) === 0 ? 1 : 0; foreach ($reflect->getParameters() as $param) { $args[] = self::getParamValue($param, $vars, $type); } } return $args; } /** * 获取参数值 * @access private * @param \ReflectionParameter $param 参数 * @param array $vars 变量 * @param string $type 类别 * @return array */ private static function getParamValue($param, &$vars, $type) { $name = $param->getName(); $class = $param->getClass(); if ($class) { $className = $class->getName(); $bind = Request::instance()->$name; if ($bind instanceof $className) { $result = $bind; } else { if (method_exists($className, 'invoke')) { $method = new \ReflectionMethod($className, 'invoke'); if ($method->isPublic() && $method->isStatic()) { return $className::invoke(Request::instance()); } } $result = method_exists($className, 'instance') ? $className::instance() : new $className; } } elseif (1 == $type && !empty($vars)) { $result = array_shift($vars); } elseif (0 == $type && isset($vars[$name])) { $result = $vars[$name]; } elseif ($param->isDefaultValueAvailable()) { $result = $param->getDefaultValue(); } else { throw new \InvalidArgumentException('method param miss:' . $name); } return $result; } /** * 执行调用分发 * @access protected * @param array $dispatch 调用信息 * @param array $config 配置信息 * @return Response|mixed * @throws \InvalidArgumentException */ protected static function exec($dispatch, $config) { 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': // 执行控制器操作 $vars = array_merge(Request::instance()->param(), $dispatch['var']); $data = Loader::action( $dispatch['controller'], $vars, $config['url_controller_layer'], $config['controller_suffix'] ); break; case 'method': // 回调方法 $vars = array_merge(Request::instance()->param(), $dispatch['var']); $data = self::invokeMethod($dispatch['method'], $vars); break; case 'function': // 闭包 $data = self::invokeFunction($dispatch['function']); break; case 'response': // Response 实例 $data = $dispatch['response']; break; default: throw new \InvalidArgumentException('dispatch type not support'); } return $data; } /** * 执行模块 * @access public * @param array $result 模块/控制器/操作 * @param array $config 配置参数 * @param bool $convert 是否自动转换控制器和操作名 * @return mixed * @throws HttpException */ 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); // 模块请求缓存检查 $request->cache( $config['request_cache'], $config['request_cache_expire'], $config['request_cache_except'] ); } else { throw new HttpException(404, 'module not exists:' . $module); } } else { // 单一模块部署 $module = ''; $request->module($module); } // 设置默认过滤机制 $request->filter($config['default_filter']); // 当前模块路径 App::$modulePath = APP_PATH . ($module ? $module . DS : ''); // 是否自动转换控制器和操作名 $convert = is_bool($convert) ? $convert : $config['url_convert']; // 获取控制器名 $controller = strip_tags($result[1] ?: $config['default_controller']); if (!preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) { throw new HttpException(404, 'controller not exists:' . $controller); } $controller = $convert ? strtolower($controller) : $controller; // 获取操作名 $actionName = strip_tags($result[2] ?: $config['default_action']); if (!empty($config['action_convert'])) { $actionName = Loader::parseName($actionName, 1); } else { $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'] ); } catch (ClassNotFoundException $e) { throw new HttpException(404, 'controller not exists:' . $e->getClass()); } // 获取当前操作名 $action = $actionName . $config['action_suffix']; $vars = []; if (is_callable([$instance, $action])) { // 执行操作方法 $call = [$instance, $action]; // 严格获取当前操作方法名 $reflect = new \ReflectionMethod($instance, $action); $methodName = $reflect->getName(); $suffix = $config['action_suffix']; $actionName = $suffix ? substr($methodName, 0, -strlen($suffix)) : $methodName; $request->action($actionName); } elseif (is_callable([$instance, '_empty'])) { // 空操作 $call = [$instance, '_empty']; $vars = [$actionName]; } else { // 操作不存在 throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()'); } Hook::listen('action_begin', $call); return self::invokeMethod($call, $vars); } /** * URL路由检测(根据PATH_INFO) * @access public * @param \think\Request $request 请求实例 * @param array $config 配置信息 * @return array * @throws \think\Exception */ 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'; 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; 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 RouteNotFoundException(); } } // 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索 if (false === $result) { $result = Route::parseUrl($path, $depr, $config['controller_auto_search']); } return $result; } /** * 设置应用的路由检测机制 * @access public * @param bool $route 是否需要检测路由 * @param bool $must 是否强制检测路由 * @return void */ public static function route($route, $must = false) { self::$routeCheck = $route; self::$routeMust = $must; } }
Fatal error: Uncaught Error: Class 'think\App' not found in /www/wwwroot/agmc.voin.ink/thinkphp/library/think/exception/Handle.php:44 Stack trace: #0 /www/wwwroot/agmc.voin.ink/thinkphp/library/think/Error.php(47): think\exception\Handle->report(Object(think\exception\ThrowableError)) #1 [internal function]: think\Error::appException(Object(think\exception\ThrowableError)) #2 {main} thrown in /www/wwwroot/agmc.voin.ink/thinkphp/library/think/exception/Handle.php on line 44
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 * @param array|string $dispatch 调度信息 * @param string $type 调度类型 * @return void */ public static function dispatch($dispatch, $type = 'module') { self::$dispatch = ['type' => $type, $type => $dispatch]; } /** * 执行函数或者闭包方法 支持参数调用 * @access public * @param string|array|\Closure $function 函数或者闭包 * @param array $vars 变量 * @return mixed */ 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); } /** * 调用反射执行类的方法 支持参数绑定 * @access public * @param string|array $method 方法 * @param array $vars 变量 * @return mixed */ public static function invokeMethod($method, $vars = []) { if (is_array($method)) { $class = is_object($method[0]) ? $method[0] : self::invokeClass($method[0]); $reflect = new \ReflectionMethod($class, $method[1]); } else { // 静态方法 $reflect = new \ReflectionMethod($method); } $args = self::bindParams($reflect, $vars); self::$debug && Log::record('[ RUN ] ' . $reflect->class . '->' . $reflect->name . '[ ' . $reflect->getFileName() . ' ]', 'info'); return $reflect->invokeArgs(isset($class) ? $class : null, $args); } /** * 调用反射执行类的实例化 支持依赖注入 * @access public * @param string $class 类名 * @param array $vars 变量 * @return mixed */ public static function invokeClass($class, $vars = []) { $reflect = new \ReflectionClass($class); $constructor = $reflect->getConstructor(); $args = $constructor ? self::bindParams($constructor, $vars) : []; return $reflect->newInstanceArgs($args); } /** * 绑定参数 * @access private * @param \ReflectionMethod|\ReflectionFunction $reflect 反射类 * @param array $vars 变量 * @return array */ private static function bindParams($reflect, $vars = []) { // 自动获取请求变量 if (empty($vars)) { $vars = Config::get('url_param_type') ? Request::instance()->route() : Request::instance()->param(); } $args = []; if ($reflect->getNumberOfParameters() > 0) { // 判断数组类型 数字数组时按顺序绑定参数 reset($vars); $type = key($vars) === 0 ? 1 : 0; foreach ($reflect->getParameters() as $param) { $args[] = self::getParamValue($param, $vars, $type); } } return $args; } /** * 获取参数值 * @access private * @param \ReflectionParameter $param 参数 * @param array $vars 变量 * @param string $type 类别 * @return array */ private static function getParamValue($param, &$vars, $type) { $name = $param->getName(); $class = $param->getClass(); if ($class) { $className = $class->getName(); $bind = Request::instance()->$name; if ($bind instanceof $className) { $result = $bind; } else { if (method_exists($className, 'invoke')) { $method = new \ReflectionMethod($className, 'invoke'); if ($method->isPublic() && $method->isStatic()) { return $className::invoke(Request::instance()); } } $result = method_exists($className, 'instance') ? $className::instance() : new $className; } } elseif (1 == $type && !empty($vars)) { $result = array_shift($vars); } elseif (0 == $type && isset($vars[$name])) { $result = $vars[$name]; } elseif ($param->isDefaultValueAvailable()) { $result = $param->getDefaultValue(); } else { throw new \InvalidArgumentException('method param miss:' . $name); } return $result; } /** * 执行调用分发 * @access protected * @param array $dispatch 调用信息 * @param array $config 配置信息 * @return Response|mixed * @throws \InvalidArgumentException */ protected static function exec($dispatch, $config) { 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': // 执行控制器操作 $vars = array_merge(Request::instance()->param(), $dispatch['var']); $data = Loader::action( $dispatch['controller'], $vars, $config['url_controller_layer'], $config['controller_suffix'] ); break; case 'method': // 回调方法 $vars = array_merge(Request::instance()->param(), $dispatch['var']); $data = self::invokeMethod($dispatch['method'], $vars); break; case 'function': // 闭包 $data = self::invokeFunction($dispatch['function']); break; case 'response': // Response 实例 $data = $dispatch['response']; break; default: throw new \InvalidArgumentException('dispatch type not support'); } return $data; } /** * 执行模块 * @access public * @param array $result 模块/控制器/操作 * @param array $config 配置参数 * @param bool $convert 是否自动转换控制器和操作名 * @return mixed * @throws HttpException */ 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); // 模块请求缓存检查 $request->cache( $config['request_cache'], $config['request_cache_expire'], $config['request_cache_except'] ); } else { throw new HttpException(404, 'module not exists:' . $module); } } else { // 单一模块部署 $module = ''; $request->module($module); } // 设置默认过滤机制 $request->filter($config['default_filter']); // 当前模块路径 App::$modulePath = APP_PATH . ($module ? $module . DS : ''); // 是否自动转换控制器和操作名 $convert = is_bool($convert) ? $convert : $config['url_convert']; // 获取控制器名 $controller = strip_tags($result[1] ?: $config['default_controller']); if (!preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) { throw new HttpException(404, 'controller not exists:' . $controller); } $controller = $convert ? strtolower($controller) : $controller; // 获取操作名 $actionName = strip_tags($result[2] ?: $config['default_action']); if (!empty($config['action_convert'])) { $actionName = Loader::parseName($actionName, 1); } else { $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'] ); } catch (ClassNotFoundException $e) { throw new HttpException(404, 'controller not exists:' . $e->getClass()); } // 获取当前操作名 $action = $actionName . $config['action_suffix']; $vars = []; if (is_callable([$instance, $action])) { // 执行操作方法 $call = [$instance, $action]; // 严格获取当前操作方法名 $reflect = new \ReflectionMethod($instance, $action); $methodName = $reflect->getName(); $suffix = $config['action_suffix']; $actionName = $suffix ? substr($methodName, 0, -strlen($suffix)) : $methodName; $request->action($actionName); } elseif (is_callable([$instance, '_empty'])) { // 空操作 $call = [$instance, '_empty']; $vars = [$actionName]; } else { // 操作不存在 throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()'); } Hook::listen('action_begin', $call); return self::invokeMethod($call, $vars); } /** * URL路由检测(根据PATH_INFO) * @access public * @param \think\Request $request 请求实例 * @param array $config 配置信息 * @return array * @throws \think\Exception */ 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'; 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; 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 RouteNotFoundException(); } } // 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索 if (false === $result) { $result = Route::parseUrl($path, $depr, $config['controller_auto_search']); } return $result; } /** * 设置应用的路由检测机制 * @access public * @param bool $route 是否需要检测路由 * @param bool $must 是否强制检测路由 * @return void */ public static function route($route, $must = false) { self::$routeCheck = $route; self::$routeMust = $must; } }
Fatal error: Uncaught Error: Class 'think\App' not found in /www/wwwroot/agmc.voin.ink/thinkphp/library/think/exception/Handle.php:44 Stack trace: #0 /www/wwwroot/agmc.voin.ink/thinkphp/library/think/Error.php(47): think\exception\Handle->report(Object(think\exception\ErrorException)) #1 /www/wwwroot/agmc.voin.ink/thinkphp/library/think/Error.php(88): think\Error::appException(Object(think\exception\ErrorException)) #2 [internal function]: think\Error::appShutdown() #3 {main} thrown in /www/wwwroot/agmc.voin.ink/thinkphp/library/think/exception/Handle.php on line 44