369 lines
12 KiB
PHP
Raw Normal View History

2024-08-31 01:03:37 +08:00
<?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);}