369 lines
12 KiB
PHP
369 lines
12 KiB
PHP
![]() |
<?php
|
|||
|
|
|||
|
/**
|
|||
|
* 快速文件数据读取和保存 针对简单类型数据 字符串、数组
|
|||
|
* @param string $name 缓存名称
|
|||
|
* @param mixed $value 缓存值
|
|||
|
* @param string $path 缓存路径
|
|||
|
* @return mixed
|
|||
|
*/
|
|||
|
function think_var_cache($name, $value = '', $path = TEMP_PATH) {
|
|||
|
static $_cache = array();
|
|||
|
$filename = $path . $name . '.php';
|
|||
|
if ('' !== $value) {
|
|||
|
if (is_null($value)) {
|
|||
|
return false !== strpos($name, '*') ? array_map("unlink", glob($filename)) : unlink($filename);
|
|||
|
} else {
|
|||
|
$dir = dirname($filename);
|
|||
|
if (!is_dir($dir)){mkdir($dir, DEFAULT_PERRMISSIONS, true);}
|
|||
|
$_cache[$name] = $value;
|
|||
|
return file_put_contents($filename,"<?php \n return " . var_export($value, true) . ";");
|
|||
|
}
|
|||
|
}
|
|||
|
if (isset($_cache[$name])){
|
|||
|
return $_cache[$name];
|
|||
|
}
|
|||
|
// 获取缓存数据
|
|||
|
if (is_file($filename)) {
|
|||
|
$value = include $filename;
|
|||
|
$_cache[$name] = $value;
|
|||
|
} else {
|
|||
|
$value = false;
|
|||
|
}
|
|||
|
return $value;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 自定义异常处理
|
|||
|
* @param string $msg 异常消息
|
|||
|
* @param string $type 异常类型 默认为ThinkException
|
|||
|
* @param integer $code 异常代码 默认为0
|
|||
|
* @return void
|
|||
|
*/
|
|||
|
function think_exception($msg) {
|
|||
|
$error = is_object($msg) ? $msg->getMessage() : $msg;
|
|||
|
$trace = is_object($msg) ? $msg->getTrace() : debug_backtrace();
|
|||
|
if(is_object($msg) && is_array($trace)){
|
|||
|
$lastAt = array('file'=>$msg->getFile(),'line'=>$msg->getLine());
|
|||
|
$trace = array_merge(array($lastAt),$trace);
|
|||
|
}
|
|||
|
$trace = get_caller_trace($trace,false);
|
|||
|
write_log($error."\n".get_caller_msg_parse($trace)."\n".json_encode($GLOBALS['in']),'error');
|
|||
|
if(defined('GLOBAL_DEBUG') && GLOBAL_DEBUG ){$trace[] = $error;pr($trace);exit;}
|
|||
|
|
|||
|
$desc = is_array($trace) ? implode("\n",array_slice($trace,-2)) : '';
|
|||
|
$desc = preg_replace("/{\w+}#/",'',$desc);
|
|||
|
think_error_parse($error);
|
|||
|
$action = defined('ACTION') ? ' <span style="color:#888;font-size:12px;font-weight:200;">('.ACTION.')</span>' : '';
|
|||
|
$error = "<div class='desc'>".$error.$action."</div>";
|
|||
|
$error = $error.'<div style="border-top:1px dotted #eee;padding-top:10px;"><code>'.$desc.'</code></div>';
|
|||
|
$error = $error.'<div style="color:#ccc;font-size:12px;"><code>['.think_system_info().']</code></div>';
|
|||
|
show_tips($error,'',0,'',false);
|
|||
|
}
|
|||
|
|
|||
|
function think_error_parse(&$error){
|
|||
|
$errList = array(
|
|||
|
'using password' => LNG('ERROR_DB_PWD'),
|
|||
|
'timed out' => LNG('ERROR_DB_TIMEOUT'),
|
|||
|
'connection refused' => LNG('ERROR_DB_CONN_RFS'),
|
|||
|
'getaddrinfo failed' => LNG('ERROR_DB_ADR'),
|
|||
|
'_NOT_SUPPORT_' => LNG('ERROR_DB_NOT_SUPPORT'),
|
|||
|
'Access denied' => LNG('ERROR_DB_XS_DENNIED'),
|
|||
|
'Unknown database' => LNG('ERROR_DB_NOT_EXIST'),
|
|||
|
);
|
|||
|
$errMsg = LNG('explorer.systemError');
|
|||
|
// $errMsg = '数据库操作异常,请检查对应服务及相关配置。';
|
|||
|
foreach($errList as $key => $msg) {
|
|||
|
if(stripos($error, $key) !== false) {
|
|||
|
$errMsg = $msg; break;
|
|||
|
}
|
|||
|
}
|
|||
|
$error = clear_html($error).'<br/>' . $errMsg;
|
|||
|
}
|
|||
|
|
|||
|
// 加入 系统版本/php版本/数据库类型;
|
|||
|
function think_system_info(){
|
|||
|
$version = php_uname('s').' '.php_uname('r');
|
|||
|
$dbType = _get($GLOBALS['config'],'database.DB_TYPE','');
|
|||
|
if($dbType == 'pdo'){
|
|||
|
$dsn = explode(':',_get($GLOBALS['config'],'database.DB_DSN',''));
|
|||
|
$dbType = 'pdo.'.$dsn[0];
|
|||
|
}
|
|||
|
$kodVersion = KOD_VERSION.'.'.KOD_VERSION_BUILD;
|
|||
|
return $version.'/'.PHP_VERSION.'/'.$dbType.'/'.$kodVersion;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 获取和设置语言定义(不区分大小写)
|
|||
|
*/
|
|||
|
function think_lang($name = null, $value = null) {
|
|||
|
return $name;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 取得对象实例 支持调用类的静态方法
|
|||
|
* @param string $name 类名
|
|||
|
* @param string $method 方法名,如果为空则返回实例化对象
|
|||
|
* @param array $args 调用参数
|
|||
|
* @return object
|
|||
|
*/
|
|||
|
function think_get_instance_of($name, $method = '', $args = array()) {
|
|||
|
static $_instance = array();
|
|||
|
$identify = empty($args) ? $name . $method : $name . $method . think_guid($args);
|
|||
|
if (!isset($_instance[$identify])) {
|
|||
|
if (class_exists($name)) {
|
|||
|
$o = new $name();
|
|||
|
if (method_exists($o, $method)) {
|
|||
|
if (!empty($args)) {
|
|||
|
$_instance[$identify] = call_user_func_array(array(&$o, $method), $args);
|
|||
|
} else {
|
|||
|
$_instance[$identify] = $o->$method();
|
|||
|
}
|
|||
|
} else {
|
|||
|
$_instance[$identify] = $o;
|
|||
|
}
|
|||
|
} else {
|
|||
|
think_exception(think_lang('_CLASS_NOT_EXIST_') . ':' . $name);
|
|||
|
}
|
|||
|
}
|
|||
|
return $_instance[$identify];
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 根据PHP各种类型变量生成唯一标识号
|
|||
|
* @param mixed $mix 变量
|
|||
|
* @return string
|
|||
|
*/
|
|||
|
function think_guid($mix) {
|
|||
|
if (is_object($mix) && function_exists('spl_object_hash')) {
|
|||
|
return spl_object_hash($mix);
|
|||
|
} elseif (is_resource($mix)) {
|
|||
|
$mix = get_resource_type($mix) . strval($mix);
|
|||
|
} else {
|
|||
|
$mix = serialize($mix);
|
|||
|
}
|
|||
|
return md5($mix);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 获取和设置配置参数 支持批量定义
|
|||
|
* @param string|array $name 配置变量
|
|||
|
* @param mixed $value 配置值
|
|||
|
* @return mixed
|
|||
|
*/
|
|||
|
function think_config($name = null, $value = null) {
|
|||
|
static $_config = array();
|
|||
|
// 无参数时获取所有
|
|||
|
if (empty($name)) {
|
|||
|
if (!empty($value) && $array = think_cache('c_' . $value)) {
|
|||
|
$_config = array_merge($_config, array_change_key_case($array));
|
|||
|
}
|
|||
|
return $_config;
|
|||
|
}
|
|||
|
// 优先执行设置获取或赋值
|
|||
|
if (is_string($name)) {
|
|||
|
if (!strpos($name, '.')) {
|
|||
|
$name = strtolower($name);
|
|||
|
if (is_null($value))
|
|||
|
return isset($_config[$name]) ? $_config[$name] : null;
|
|||
|
$_config[$name] = $value;
|
|||
|
return;
|
|||
|
}
|
|||
|
// 二维数组设置和获取支持
|
|||
|
$name = explode('.', $name);
|
|||
|
$name[0] = strtolower($name[0]);
|
|||
|
if (is_null($value))
|
|||
|
return isset($_config[$name[0]][$name[1]]) ? $_config[$name[0]][$name[1]] : null;
|
|||
|
$_config[$name[0]][$name[1]] = $value;
|
|||
|
return;
|
|||
|
}
|
|||
|
// 批量设置
|
|||
|
if (is_array($name)) {
|
|||
|
$_config = array_merge($_config, array_change_key_case($name));
|
|||
|
if (!empty($value)) {// 保存配置值
|
|||
|
think_cache('c_' . $value, $_config);
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
return null; // 避免非法参数
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 字符串命名风格转换
|
|||
|
* type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
|
|||
|
* @param string $name 字符串
|
|||
|
* @param integer $type 转换类型
|
|||
|
* @return string
|
|||
|
*/
|
|||
|
function think_parse_name($name, $type = 0) {
|
|||
|
if ($type) {
|
|||
|
$result = preg_replace_callback("/_([a-zA-Z])/", function($matches) {
|
|||
|
return strtoupper($matches[1]);
|
|||
|
},$name);
|
|||
|
return ucfirst($result);
|
|||
|
// return ucfirst(@preg_replace("/_([a-zA-Z])/e", "strtoupper('\\1')", $name));
|
|||
|
} else {
|
|||
|
return lcfirst($name);//数据库字段以小驼峰命名方式
|
|||
|
// return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 设置和获取统计数据
|
|||
|
* 使用方法:
|
|||
|
* <code>
|
|||
|
* think_action_status('db',1); // 记录数据库操作次数
|
|||
|
* think_action_status('read',1); // 记录读取次数
|
|||
|
* echo think_action_status('db'); // 获取当前页面数据库的所有操作次数
|
|||
|
* echo think_action_status('read'); // 获取当前页面读取次数
|
|||
|
* </code>
|
|||
|
* @param string $key 标识位置
|
|||
|
* @param integer $step 步进值
|
|||
|
* @return mixed
|
|||
|
*/
|
|||
|
function think_action_status($key, $step = 0, $save = false) {
|
|||
|
static $_num = array();
|
|||
|
if (!isset($_num[$key])) {
|
|||
|
$_num[$key] = (false !== $save) ? think_cache('N_' . $key) : 0;
|
|||
|
}
|
|||
|
if (empty($step)){
|
|||
|
return $_num[$key];
|
|||
|
}else{
|
|||
|
$_num[$key] = $_num[$key] + (int) $step;
|
|||
|
}
|
|||
|
if (false !== $save) { // 保存结果
|
|||
|
think_cache('N_' . $key, $_num[$key], $save);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 缓存管理
|
|||
|
* @param mixed $name 缓存名称,如果为数组表示进行缓存设置
|
|||
|
* @param mixed $value 缓存值
|
|||
|
* @param mixed $options 缓存参数
|
|||
|
* @return mixed
|
|||
|
*/
|
|||
|
function think_cache($name, $value = '', $options = null) {
|
|||
|
static $_cache = array();
|
|||
|
$timeout = isset($options['expire']) ? $options['expire'] : false;
|
|||
|
// 超时时间为0,则代表内存缓存;
|
|||
|
if($timeout === false ){
|
|||
|
if ($value === '') {
|
|||
|
return $_cache[$name];
|
|||
|
} elseif (is_null($value)) {
|
|||
|
return $_cache[$name] = null;
|
|||
|
} else {
|
|||
|
return $_cache[$name] = $value;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ($value === '') {
|
|||
|
return Cache::get($name);
|
|||
|
} elseif (is_null($value)) {
|
|||
|
return Cache::remove($name);
|
|||
|
} else {
|
|||
|
return Cache::set($name,$value,$timeout);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 记录和统计时间(微秒)和内存使用情况
|
|||
|
* 使用方法:
|
|||
|
* <code>
|
|||
|
* think_status('begin'); // 记录开始标记位
|
|||
|
* // ... 区间运行代码
|
|||
|
* think_status('end'); // 记录结束标签位
|
|||
|
* echo think_status('begin','end',6); // 统计区间运行时间 精确到小数后6位
|
|||
|
* echo think_status('begin','end','m'); // 统计区间内存使用情况
|
|||
|
* 如果end标记位没有定义,则会自动以当前作为标记位
|
|||
|
* 其中统计内存使用需要 MEMORY_LIMIT_ON 常量为true才有效
|
|||
|
* </code>
|
|||
|
* @param string $start 开始标签
|
|||
|
* @param string $end 结束标签
|
|||
|
* @param integer|string $dec 小数位或者m
|
|||
|
* @return mixed
|
|||
|
*/
|
|||
|
function think_status($start, $end = '', $dec = 4) {
|
|||
|
static $_info = array();
|
|||
|
static $_mem = array();
|
|||
|
if (is_float($end)) { // 记录时间
|
|||
|
$_info[$start] = $end;
|
|||
|
} elseif (!empty($end)) { // 统计时间和内存使用
|
|||
|
if (!isset($_info[$end]))
|
|||
|
$_info[$end] = microtime(TRUE);
|
|||
|
if (MEMORY_LIMIT_ON && $dec == 'm') {
|
|||
|
if (!isset($_mem[$end]))
|
|||
|
$_mem[$end] = memory_get_usage();
|
|||
|
return number_format(($_mem[$end] - $_mem[$start]) / 1024);
|
|||
|
}else {
|
|||
|
return number_format(($_info[$end] - $_info[$start]), $dec);
|
|||
|
}
|
|||
|
} else { // 记录时间和内存使用
|
|||
|
$_info[$start] = microtime(TRUE);
|
|||
|
if (MEMORY_LIMIT_ON)
|
|||
|
$_mem[$start] = memory_get_usage();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 添加和获取页面Trace记录
|
|||
|
* @param string $value 变量
|
|||
|
* @param string $label 标签
|
|||
|
* @param string $level 日志级别
|
|||
|
* @param boolean $record 是否记录日志
|
|||
|
* @return void
|
|||
|
*/
|
|||
|
function think_trace($value = '[think]', $label = '', $level = 'DEBUG', $record = false) {
|
|||
|
static $_trace = array();
|
|||
|
static $_logTemp = array();
|
|||
|
|
|||
|
$info = ($label ? $label.':':'').print_r($value, true);
|
|||
|
if ($level == 'ERR') return think_exception($info);
|
|||
|
if (defined('GLOBAL_DEBUG') && !GLOBAL_DEBUG ) return;
|
|||
|
if ($value == '[trace]') return $_trace;
|
|||
|
if ($value == '[think]') return think_exception($_trace);
|
|||
|
if ($label == '_log_'){
|
|||
|
if(!$_trace[$level]){$_trace[$level] = array();$_logTemp[$level] = TIME_FLOAT;}
|
|||
|
if($value === false){$_trace[$level] = array();$_logTemp[$level] = TIME_FLOAT;return;}
|
|||
|
|
|||
|
if(is_array($value)){$value = json_encode($value);}
|
|||
|
$timeNow = timeFloat();$timeNowArr = explode('.',$timeNow.'000');
|
|||
|
$timeShow = date('i:s.',$timeNowArr[0]).substr($timeNowArr[1],0,4);
|
|||
|
$_trace[$level][] = $timeShow.': '.$value.'('.sprintf('%.4f',$timeNow - $_logTemp[$level]).'s)';
|
|||
|
$_logTemp[$level] = $timeNow;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ($label == '_count_'){
|
|||
|
if(!$_trace[$level]){$_trace[$level] = array();}
|
|||
|
if(!$_trace[$level][$value]){$_trace[$level][$value] = 0;}
|
|||
|
$_trace[$level][$value] += 1;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
$logMax = 10;//最多纪录前10条sql; 避免额外开销及内存不可控
|
|||
|
$level = strtoupper($level);
|
|||
|
$keyTrace = $level.'-trace';
|
|||
|
$keyList = $level.'-list';
|
|||
|
$keyTime = $level.'-allTime';
|
|||
|
if (!isset($_trace[$keyList])) {
|
|||
|
$_trace[$keyTrace] = array();
|
|||
|
$_trace[$keyList] = array();
|
|||
|
$_trace[$keyTime] = 0.0;
|
|||
|
}
|
|||
|
|
|||
|
$useTime = substr($info,strrpos($info,'[ RunTime:')+10,-5);
|
|||
|
$_trace[$keyTime] = sprintf('%.5f',$_trace[$keyTime] + $useTime );
|
|||
|
$timeNow = timeFloat();$timeNowArr = explode('.',$timeNow.'000');
|
|||
|
$timeShow = date('i:s.',$timeNowArr[0]).substr($timeNowArr[1],0,4);
|
|||
|
$index = count($_trace[$keyList]) + 1;
|
|||
|
$index = $index < 10 ? '0'.$index.'' : $index.'';
|
|||
|
$_trace[$keyList][$index] = $timeShow.'['.$useTime.'s]: '.substr($info,0,-21);
|
|||
|
if(count($_trace[$keyList]) < $logMax){
|
|||
|
$trace = array_slice(get_caller_info(),4,-1); // 5ms 每个;
|
|||
|
$_trace[$keyTrace][$index]= array_merge(array($timeShow.'['.$useTime.'s]: ',$info),$trace);
|
|||
|
}
|
|||
|
if ($record){write_log($info,$level);}
|
|||
|
}
|
|||
|
function trace_log($value,$key='_log'){ think_trace($value,'_log_',$key);}
|
|||
|
function trace_count($value,$key='_count'){think_trace($value,'_count_',$key);}
|