/** * 自动表单验证 * @access protected * @param array $data 创建数据 * @param string $type 创建类型 * @return boolean */ public function valid($data, $rule = []) { $validate = $rule ? $rule : $this->validate; // 属性验证 if ($validate) { // 如果设置了数据自动验证则进行数据验证 if ($this->patchValidate) { // 重置验证错误信息 $this->error = []; } foreach ($validate as $key => $val) { // 验证因子定义格式 // array(field,rule,message,condition,type,params) // 判断是否需要执行验证 if (0 == strpos($val[2], '{%') && strpos($val[2], '}')) { $val[2] = Lang::get(substr($val[2], 2, -1)); } $val[3] = isset($val[3]) ? $val[3] : 0; $val[4] = isset($val[4]) ? $val[4] : 'regex'; // 判断验证条件 if (1 == $val[3] || 2 == $val[3] && '' != trim($data[$val[0]]) || 0 == $val[3] && isset($data[$val[0]])) { if (false === $this->_validationField($data, $val)) { return false; } } } // 批量验证的时候最后返回错误 if (!empty($this->error)) { return false; } } return true; }
/** * 构造方法,可用于打开一张图像 * * @param string $imgname 图像路径 */ public function __construct($imgname = null) { if (!extension_loaded('Imagick')) { throw new \Exception(Lang::get('_NOT_SUPPERT_') . ':Imagick'); } $imgname && $this->open($imgname); }
public function testRange() { $this->assertEquals('zh-cn', Lang::range()); Lang::set('hello', '欢迎', 'test'); Lang::range('test'); $this->assertEquals('test', Lang::range()); $this->assertEquals('欢迎', Lang::get('hello')); }
/** * 操作失败返回 JSON * * @param string|Exception $error * @return void */ public function errorJson($error) { $this->assign('success', 0); if (is_object($error)) { $this->assign('error', $error->getMessage()); $this->assign('error_msg', Lang::get($error->getMessage())); } else { if (is_string($error)) { $this->assign('error', $error); $this->assign('error_msg', Lang::get($error)); } } $this->json(); }
/** * 利用__call方法实现一些特殊的Model方法 * @access public * * @param string $method 方法名称 * @param array $args 调用参数 * * @return mixed * @throws \think\Exception */ public function __call($method, $args) { if (strtolower(substr($method, 0, 5)) == 'getby') { // 根据某个字段获取记录 $field = Loader::parseName(substr($method, 5)); $where[$field] = $args[0]; return $this->where($where)->find(); } elseif (strtolower(substr($method, 0, 10)) == 'getfieldby') { // 根据某个字段获取记录的某个值 $name = Loader::parseName(substr($method, 10)); $where[$name] = $args[0]; return $this->where($where)->getField($args[1]); } else { throw new \think\Exception(__CLASS__ . ':' . $method . Lang::get('_METHOD_NOT_EXIST_')); } }
/** * REST 调用 * @access public * * @param string $method 方法名 * @param array $args 参数 * * @return mixed * @throws \think\Exception */ public function _empty($method, $args) { if (method_exists($this, $method . '_' . $this->_method . '_' . $this->_type)) { // RESTFul方法支持 $fun = $method . '_' . $this->_method . '_' . $this->_type; } elseif ($this->_method == $this->restDefaultMethod && method_exists($this, $method . '_' . $this->_type)) { $fun = $method . '_' . $this->_type; } elseif ($this->_type == $this->restDefaultType && method_exists($this, $method . '_' . $this->_method)) { $fun = $method . '_' . $this->_method; } if (isset($fun)) { $this->{$fun}(); } else { // 抛出异常 throw new \think\Exception(\think\Lang::get('_ERROR_ACTION_:') . ACTION_NAME); } }
/** * 利用__call方法实现一些特殊的Model方法 * @access public * @param string $method 方法名称 * @param array $args 调用参数 * @return mixed */ public function __call($method, $args) { if (in_array(strtolower($method), ['count', 'sum', 'min', 'max', 'avg'], true)) { // 统计查询的实现 $field = isset($args[0]) ? $args[0] : '*'; return $this->getField(strtoupper($method) . '(' . $field . ') AS tp_' . $method); } elseif (strtolower(substr($method, 0, 5)) == 'getby') { // 根据某个字段获取记录 $field = Loader::parseName(substr($method, 5)); $where[$field] = $args[0]; return $this->where($where)->find(); } elseif (strtolower(substr($method, 0, 10)) == 'getfieldby') { // 根据某个字段获取记录的某个值 $name = Loader::parseName(substr($method, 10)); $where[$name] = $args[0]; return $this->where($where)->getField($args[1]); } elseif (isset($this->scope[$method])) { // 命名范围的单独调用支持 return $this->scope($method, $args[0]); } else { throw new \think\Exception(__CLASS__ . ':' . $method . Lang::get('_METHOD_NOT_EXIST_')); return; } }
/** * 验证表单字段 支持批量验证 * 如果批量验证返回错误的数组信息 * @access protected * @param array $data 创建数据 * @param array $val 验证因子 * @param string $type 创建类型 * @return boolean */ protected function _validationField(&$data, &$val, $type) { // 如果是批量验证,并且当前字段已经有规则验证没有通过则跳过 if ($this->patchValidate && isset($this->error[$val[0]])) { return true; } // 验证因子定义格式 // [field,rule,message,condition,type,when,params] if (empty($val[5])) { $flags = 1 << self::MODEL_BOTH - 1; } elseif (is_array($val[5])) { $flags = 0; foreach ($val[5] as $v) { $flags |= 1 << $v - 1; } } else { $flags = 3 == $val[5] ? 3 : 1 << $val[5] - 1; } // 判断是否需要执行验证 if ($flags & $type) { if (0 == strpos($val[2], '{%') && strpos($val[2], '}')) { // 支持提示信息的多语言 使用 {%语言定义} 方式 $val[2] = Lang::get(substr($val[2], 2, -1)); } $val[3] = isset($val[3]) ? $val[3] : self::EXISTS_VALIDATE; $val[4] = isset($val[4]) ? $val[4] : 'regex'; $status = true; // 判断验证条件 switch ($val[3]) { case self::MUST_VALIDATE: // 必须验证 不管表单是否有设置该字段 $status = $this->_validationFieldItem($data, $val); break; case self::VALUE_VALIDATE: // 值不为空的时候才验证 if ('' != trim($data[$val[0]])) { $status = $this->_validationFieldItem($data, $val); } break; default: // 默认表单存在该字段就验证 if (isset($data[$val[0]])) { $status = $this->_validationFieldItem($data, $val); } } if (false === $status) { if ($this->patchValidate) { $this->error[$val[0]] = $val[2]; } else { $this->error = $val[2]; return false; } } } return true; }
/** * 初始化应用或模块 * @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; } else { $path = APP_PATH . $module; // 加载模块配置 $config = Config::load(CONF_PATH . $module . 'config' . CONF_EXT); // 加载应用状态配置 if ($config['app_status']) { $config = Config::load(CONF_PATH . $module . $config['app_status'] . CONF_EXT); } // 读取扩展配置文件 if ($config['extra_config_list']) { foreach ($config['extra_config_list'] as $name => $file) { $filename = CONF_PATH . $module . $file . CONF_EXT; Config::load($filename, is_string($name) ? $name : pathinfo($filename, PATHINFO_FILENAME)); } } // 加载别名文件 if (is_file(CONF_PATH . $module . 'alias' . EXT)) { Loader::addClassMap(include CONF_PATH . $module . 'alias' . 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 ($config['lang_switch_on'] && $module) { Lang::load($path . 'lang' . DS . Request::instance()->langset() . EXT); } } return Config::get(); }
/** * 自动表单验证 * @access protected * @param array $data 创建数据 * @param string $type 创建类型 * @return boolean */ protected function autoValidation($data, $type) { if (!empty($this->options['validate'])) { $_validate = $this->options['validate']; unset($this->options['validate']); } elseif (!empty($this->validate)) { $_validate = $this->validate; } // 属性验证 if (isset($_validate)) { // 如果设置了数据自动验证则进行数据验证 if ($this->patchValidate) { // 重置验证错误信息 $this->error = []; } foreach ($_validate as $key => $val) { // 验证因子定义格式 // [field,rule,message,condition,type,when,params] // 判断是否需要执行验证 if (empty($val[5]) || self::MODEL_BOTH == $val[5] || $val[5] == $type) { if (0 == strpos($val[2], '{%') && strpos($val[2], '}')) { // 支持提示信息的多语言 使用 {%语言定义} 方式 $val[2] = Lang::get(substr($val[2], 2, -1)); } $val[3] = isset($val[3]) ? $val[3] : self::EXISTS_VALIDATE; $val[4] = isset($val[4]) ? $val[4] : 'regex'; // 判断验证条件 switch ($val[3]) { case self::MUST_VALIDATE: // 必须验证 不管表单是否有设置该字段 if (false === $this->_validationField($data, $val)) { return false; } break; case self::VALUE_VALIDATE: // 值不为空的时候才验证 if ('' != trim($data[$val[0]])) { if (false === $this->_validationField($data, $val)) { return false; } } break; default: // 默认表单存在该字段就验证 if (isset($data[$val[0]]) && false === $this->_validationField($data, $val)) { return false; } } } } // 批量验证的时候最后返回错误 if (!empty($this->error)) { return false; } } return true; }
protected function parseWhereItem($key, $val) { $whereStr = ''; if (is_array($val)) { if (is_string($val[0])) { $exp = strtolower($val[0]); if (preg_match('/^(eq|neq|gt|egt|lt|elt)$/', $exp)) { // 比较运算 $whereStr .= $key . ' ' . $this->exp[$exp] . ' ' . $this->parseValue($val[1]); } elseif (preg_match('/^(notlike|like)$/', $exp)) { // 模糊查找 if (is_array($val[1])) { $likeLogic = isset($val[2]) ? strtoupper($val[2]) : 'OR'; if (in_array($likeLogic, ['AND', 'OR', 'XOR'])) { $like = []; foreach ($val[1] as $item) { $like[] = $key . ' ' . $this->exp[$exp] . ' ' . $this->parseValue($item); } $whereStr .= '(' . implode(' ' . $likeLogic . ' ', $like) . ')'; } } else { $whereStr .= $key . ' ' . $this->exp[$exp] . ' ' . $this->parseValue($val[1]); } } elseif ('bind' == $exp) { // 使用表达式 $whereStr .= $key . ' = :' . $val[1]; } elseif ('exp' == $exp) { // 使用表达式 $whereStr .= $key . ' ' . $val[1]; } elseif (preg_match('/^(notin|not in|in)$/', $exp)) { // IN 运算 if (isset($val[2]) && 'exp' == $val[2]) { $whereStr .= $key . ' ' . $this->exp[$exp] . ' ' . $val[1]; } else { if (is_string($val[1])) { $val[1] = explode(',', $val[1]); } $zone = implode(',', $this->parseValue($val[1])); $whereStr .= $key . ' ' . $this->exp[$exp] . ' (' . $zone . ')'; } } elseif (preg_match('/^(notbetween|not between|between)$/', $exp)) { // BETWEEN运算 $data = is_string($val[1]) ? explode(',', $val[1]) : $val[1]; $whereStr .= $key . ' ' . $this->exp[$exp] . ' ' . $this->parseValue($data[0]) . ' AND ' . $this->parseValue($data[1]); } else { throw new Exception(Lang::get('_EXPRESS_ERROR_') . ':' . $val[0]); } } else { $count = count($val); $rule = isset($val[$count - 1]) ? is_array($val[$count - 1]) ? strtoupper($val[$count - 1][0]) : strtoupper($val[$count - 1]) : ''; if (in_array($rule, ['AND', 'OR', 'XOR'])) { $count = $count - 1; } else { $rule = 'AND'; } for ($i = 0; $i < $count; $i++) { $data = is_array($val[$i]) ? $val[$i][1] : $val[$i]; if ('exp' == strtolower($val[$i][0])) { $whereStr .= $key . ' ' . $data . ' ' . $rule . ' '; } else { $whereStr .= $this->parseWhereItem($key, $val[$i]) . ' ' . $rule . ' '; } } $whereStr = '( ' . substr($whereStr, 0, -4) . ' )'; } } else { //对字符串类型字段采用模糊匹配 $likeFields = $this->config['db_like_fields']; if ($likeFields && preg_match('/^(' . $likeFields . ')$/i', $key)) { $whereStr .= $key . ' LIKE ' . $this->parseValue('%' . $val . '%'); } else { $whereStr .= $key . ' = ' . $this->parseValue($val); } } return $whereStr; }
/** * where分析 * @access protected * @param mixed $where * @return array */ public function parseWhere($where) { $query = []; foreach ((array) $where as $key => $val) { if ('_id' != $key && 0 === strpos($key, '_')) { // 解析特殊条件表达式 $query = $this->parseThinkWhere($key, $val); } else { // 查询字段的安全过滤 if (!preg_match('/^[A-Z_\\|\\&\\-.a-z0-9]+$/', trim($key))) { throw new Exception(Lang::get('_ERROR_QUERY_') . ':' . $key); } $key = trim($key); if (strpos($key, '|')) { $array = explode('|', $key); $str = []; foreach ($array as $k) { $str[] = $this->parseWhereItem($k, $val); } $query['$or'] = $str; } elseif (strpos($key, '&')) { $array = explode('&', $key); $str = []; foreach ($array as $k) { $str[] = $this->parseWhereItem($k, $val); } $query = array_merge($query, $str); } else { $str = $this->parseWhereItem($key, $val); $query = array_merge($query, $str); } } } return $query; }
private static function initModule($module, $config) { // 定位模块目录 $module = COMMON_MODULE == $module || !APP_MULTI_MODULE ? '' : $module . DS; // 加载初始化文件 if (is_file(APP_PATH . $module . 'init' . EXT)) { include APP_PATH . $module . 'init' . EXT; } else { $path = APP_PATH . $module; // 加载模块配置 $config = Config::load(APP_PATH . $module . 'config' . CONF_EXT); // 加载应用状态配置 if ($config['app_status']) { $config = Config::load(APP_PATH . $module . $config['app_status'] . CONF_EXT); } // 读取扩展配置文件 if ($config['extra_config_list']) { foreach ($config['extra_config_list'] as $name => $file) { $filename = $path . $file . CONF_EXT; Config::load($filename, is_string($name) ? $name : pathinfo($filename, PATHINFO_FILENAME)); } } // 加载别名文件 if (is_file($path . 'alias' . EXT)) { Loader::addMap(include $path . 'alias' . EXT); } // 加载行为扩展文件 if (APP_HOOK && is_file($path . 'tags' . EXT)) { Hook::import(include $path . 'tags' . EXT); } // 加载公共文件 if (is_file($path . 'common' . EXT)) { include $path . 'common' . EXT; } // 加载当前模块语言包 if ($config['lang_switch_on'] && $module) { Lang::load($path . 'lang' . DS . LANG_SET . EXT); } } }
/** * 批量更新操作 * @access public * @param mixed $data 创建数据,如果传入true则更新所有缓存 * @param string $type 状态 * @return mixed */ public function bulkSave($data = '', $options = []) { // 如果没有数据传入 if (empty($data)) { $this->error = Lang::get('_DATA_TYPE_INVALID_'); } $options = $this->_parseOptions(); $pk = $this->getPk(); if ($data !== true) { //批量跟新必须是带有主键的数组 if (!isset($data[$pk])) { throw new Exception('no have pk field'); } //由于批量更新存在在原值累加的情况,所以会有 array('id'=>1,'val+'=>10);所以不能先做字段检查 foreach ($data as $field => $val) { //主键不需要处理 if ($field == $pk) { continue; } //对字段缓存初始化.每个字段的更新都会以独立的SQL进行. if (!isset($this->bulkSaveCache[$field])) { $this->bulkSaveCache[$field] = []; $this->bulkSaveSize[$field] = 0; } //如果同一个记录的同一字段被多次更新 if (!isset($this->bulkSaveCache[$field][$data[$pk]])) { //计算新增修改增加的SQL长度 $this->bulkSaveCache[$field][$data[$pk]] = $val; $this->bulkSaveSize[$field] += strlen($val) + strlen($data[$pk]) * 2 + 14; continue; } //如果是自增自减操作 $operator = '='; if (in_array(substr($field, -1, 1), ['+', '-'])) { $operator = substr($field, -1, 1); } if ($operator == '=') { //如果是直接赋值,不能重复写入,因为不确定那个值是正确的 throw new Exception('cannot repeat write in'); } else { //在原有修改基础上再进行自增或自减操作 $this->bulkSaveCache[$field][$data[$pk]] += $operator == '+' ? $val : -$val; } } } $bulkSize = isset($options['bulkSize']) ? $options['bulkSize'] : 10000; //扫描字段长度.看是否有需要先执行的 foreach ($this->bulkSaveSize as $field => $size) { if ($size < $bulkSize && ($size == 0 || $data !== true)) { continue; } //复制出插入数组 $dataSet = $this->bulkSaveCache[$field]; unset($this->bulkSaveCache[$field]); unset($this->bulkSaveSize[$field]); //默认运算符 $operator = '='; //自增或者自减 if (in_array(substr($field, -1, 1), ['+', '-'])) { $operator = substr($field, -1, 1); $field = substr($field, 0, -1); } //批量字段更新 $this->db->updateFieldAll($field, $pk, $dataSet, $operator, $options); } }
/** * 获取错误信息 * ErrorException则使用错误级别作为错误编码 * @param \Exception $exception * @return string 错误信息 */ protected function getMessage(Exception $exception) { $message = $exception->getMessage(); if (IS_CLI) { return $message; } // 导入语言包 if (!Config::get('lang_switch_on')) { Lang::load(THINK_PATH . 'lang' . DS . Lang::detect() . EXT); } if (strpos($message, ':')) { $name = strstr($message, ':', true); return Lang::has($name) ? Lang::get($name) . ' ' . strstr($message, ':') : $message; } else { return Lang::has($message) ? Lang::get($message) : $message; } }
/** * 获取验证规则的错误提示信息 * @access protected * @param string $attribute 字段英文名 * @param string $title 字段描述名 * @param string $type 验证规则名称 * @param mixed $rule 验证规则数据 * @return string */ protected function getRuleMsg($attribute, $title, $type, $rule) { if (isset($this->message[$attribute . '.' . $type])) { $msg = $this->message[$attribute . '.' . $type]; } elseif (isset($this->message[$attribute])) { $msg = $this->message[$attribute]; } elseif (isset(self::$typeMsg[$type])) { $msg = self::$typeMsg[$type]; } else { $msg = $title . '规则错误'; } if (is_string($msg) && strpos($msg, '{%')) { $msg = Lang::get(substr($msg, 2, -1)); } if (is_string($msg) && false !== strpos($msg, ':')) { // 变量替换 if (strpos($rule, ',')) { $array = array_pad(explode(',', $rule), 3, ''); } else { $array = array_pad([], 3, ''); } $msg = str_replace([':attribute', ':rule', ':1', ':2', ':3'], [$title, (string) $rule, $array[0], $array[1], $array[2]], $msg); } return $msg; }
/** * 初始化应用或模块 * @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 (strpos($file, 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(); }
/** * 默认跳转操作 支持错误导向和正确跳转 * 调用模板显示 默认为public目录下面的success页面 * 提示页面为可配置 支持模板标签 * @access private * @param string $message 提示信息 * @param Boolean $status 状态 * @param string $jumpUrl 页面跳转地址 * @param mixed $ajax 是否为Ajax方式 当数字时指定跳转时间 * @return void */ private function dispatchJump($message, $status = 1, $jumpUrl = '', $ajax = false) { if (true === $ajax || IS_AJAX) { // AJAX提交 $data = is_array($ajax) ? $ajax : []; $data['info'] = $message; $data['status'] = $status; $data['url'] = $jumpUrl; $this->ajaxReturn($data); } // 模板变量 $data = []; if (is_int($ajax)) { $data['waitSecond'] = $ajax; } if (!empty($jumpUrl)) { $data['jumpUrl'] = $jumpUrl; } // 提示标题 $data['msgTitle'] = Lang::get($status ? '_OPERATION_SUCCESS_' : '_OPERATION_FAIL_'); $data['status'] = $status; // 状态 //保证输出不受静态缓存影响 Config::set('html_cache_on', false); if ($status) { //发送成功信息 $data['message'] = $message; // 提示信息 // 成功操作后默认停留1秒 $data['waitSecond'] = '1'; // 默认操作成功自动返回操作前页面 if (!$jumpUrl) { $data["jumpUrl"] = $_SERVER["HTTP_REFERER"]; } return $this->display(Config::get('success_tmpl'), $data); } else { $data['error'] = $message; // 提示信息 //发生错误时候默认停留3秒 $data['waitSecond'] = '3'; // 默认发生错误的话自动返回上页 if (!$jumpUrl) { $data['jumpUrl'] = 'javascript:history.back(-1);'; } return $this->display(Config::get('error_tmpl'), $data); } }
/** * 加载语言包 * * @return void */ private static function load_lang() { Lang::set(include FRAME_PATH . 'Lang/' . strtolower(Config::get('DEFAULT_LANG')) . '.php'); // 项目行为 if (is_file(APP_PATH . 'Lang/' . strtolower(Config::get('DEFAULT_LANG')) . '.php')) { Lang::set(include APP_PATH . 'Lang/' . strtolower(Config::get('DEFAULT_LANG')) . '.php'); } // 分组行为 if (is_file(GROUP_PATH . 'Lang/' . strtolower(Config::get('DEFAULT_LANG')) . '.php')) { Lang::set(include GROUP_PATH . 'Lang/' . strtolower(Config::get('DEFAULT_LANG')) . '.php'); } }
<?php \think\Lang::load(APP_PATH . 'common\\lang\\url.php');
/** * 获取语言变量值 * @param string $name 语言变量名 * @param array $vars 动态变量值 * @param string $lang 语言 * @return mixed */ function lang($name, $vars = [], $lang = '') { return Lang::get($name, $vars, $lang); }
/** * 返回403 * 可以根据实际情况在项目内覆盖 * * @return void */ public function redirectTo403() { if (IS_AJAX) { exit(Response::send_http_status(403)); } else { exit(Lang::get('_ERROR_403')); } }
function L($name, $vars = [], $lang = '') { return \think\Lang::get($name, $vars, $lang); }
/** * 执行应用程序 * @access public * @return void */ public static function run($config) { // 日志初始化 Log::init($config['log']); // 缓存初始化 Cache::connect($config['cache']); // 加载框架底层语言包 if (is_file(THINK_PATH . 'Lang/' . strtolower($config['default_lang']) . EXT)) { Lang::set(include THINK_PATH . 'Lang/' . strtolower($config['default_lang']) . EXT); } if (is_file(APP_PATH . 'build.php')) { // 自动化创建脚本 Create::build(include APP_PATH . 'build.php'); } // 监听app_init Hook::listen('app_init'); // 初始化公共模块 define('COMMON_PATH', APP_PATH . $config['common_module'] . '/'); self::initModule(COMMON_PATH, $config); // 启动session if (!IS_CLI) { Session::init($config['session']); } // 应用URL调度 self::dispatch($config); // 监听app_run Hook::listen('app_run'); // 执行操作 if (!preg_match('/^[A-Za-z](\\/|\\w)*$/', CONTROLLER_NAME)) { // 安全检测 $instance = false; } elseif ($config['action_bind_class']) { // 操作绑定到类:模块\controller\控制器\操作 if (is_dir(MODULE_PATH . CONTROLLER_LAYER . '/' . CONTROLLER_NAME)) { $namespace = MODULE_NAME . '\\' . CONTROLLER_LAYER . '\\' . CONTROLLER_NAME . '\\'; } else { // 空控制器 $namespace = MODULE_NAME . '\\' . CONTROLLER_LAYER . '\\empty\\'; } $actionName = strtolower(ACTION_NAME); if (class_exists($namespace . $actionName)) { $class = $namespace . $actionName; } elseif (class_exists($namespace . '_empty')) { // 空操作 $class = $namespace . '_empty'; } else { throw new Exception('_ERROR_ACTION_:' . ACTION_NAME); } $instance = new $class(); // 操作绑定到类后 固定执行run入口 $action = 'run'; } else { $instance = Loader::controller(CONTROLLER_NAME); // 获取当前操作名 $action = ACTION_NAME . $config['action_suffix']; } if (!$instance) { throw new Exception('[ ' . MODULE_NAME . '\\' . CONTROLLER_LAYER . '\\' . Loader::parseName(CONTROLLER_NAME, 1) . ' ] not exists'); } try { // 操作方法开始监听 $call = [$instance, $action]; Hook::listen('action_begin', $call); if (!preg_match('/^[A-Za-z](\\w)*$/', $action)) { // 非法操作 throw new \ReflectionException(); } //执行当前操作 $method = new \ReflectionMethod($instance, $action); if ($method->isPublic()) { // URL参数绑定检测 if ($config['url_params_bind'] && $method->getNumberOfParameters() > 0) { switch ($_SERVER['REQUEST_METHOD']) { case 'POST': $vars = array_merge($_GET, $_POST); break; case 'PUT': parse_str(file_get_contents('php://input'), $vars); break; default: $vars = $_GET; } $params = $method->getParameters(); $paramsBindType = $config['url_parmas_bind_type']; foreach ($params as $param) { $name = $param->getName(); if (1 == $paramsBindType && !empty($vars)) { $args[] = array_shift($vars); } if (0 == $paramsBindType && isset($vars[$name])) { $args[] = $vars[$name]; } elseif ($param->isDefaultValueAvailable()) { $args[] = $param->getDefaultValue(); } else { throw new Exception('_PARAM_ERROR_:' . $name); } } array_walk_recursive($args, 'Input::filterExp'); $data = $method->invokeArgs($instance, $args); } else { $data = $method->invoke($instance); } // 操作方法执行完成监听 Hook::listen('action_end', $call); if (IS_API) { // API接口返回数据 self::returnData($data, $config['default_ajax_return']); } } else { // 操作方法不是Public 抛出异常 throw new \ReflectionException(); } } catch (\ReflectionException $e) { // 操作不存在 if (method_exists($instance, '_empty')) { $method = new \ReflectionMethod($instance, '_empty'); $method->invokeArgs($instance, [$action, '']); } else { throw new Exception('[ ' . (new \ReflectionClass($instance))->getName() . ':' . $action . ' ] not exists ', 404); } } // 监听app_end Hook::listen('app_end'); return; }
/** * 获取和设置语言定义(不区分大小写) * * @param string|array $name 语言变量 * @param string $value 语言值 * * @return mixed */ function L($name = null, $value = null) { // 空参数返回所有定义 if (empty($name)) { return Lang::getAll(); } // 获取 if (is_string($name) && is_null($value)) { return Lang::get($name); } // 设置 if (is_string($name) && !is_null($value)) { return Lang::set($name, $value); } // 批量定义 if (is_array($name)) { return Lang::setAll($name); } }
/** * 获取错误信息 * ErrorException则使用错误级别作为错误编码 * @param \Exception $exception * @return string 错误信息 */ protected function getMessage(Exception $exception) { $message = $exception->getMessage(); if (IS_CLI) { return $message; } if (strpos($message, ':')) { $name = strstr($message, ':', true); $message = Lang::has($name) ? Lang::get($name) . strstr($message, ':') : $message; } elseif (strpos($message, ',')) { $name = strstr($message, ',', true); $message = Lang::has($name) ? Lang::get($name) . ':' . substr(strstr($message, ','), 1) : $message; } elseif (Lang::has($message)) { $message = Lang::get($message); } return $message; }