$code ?: 0, 'msg' => $msg, 'data' => $data ]; $response = \think\Response::create($result, 'json', $status_code)->header($header); throw new \think\exception\HttpResponseException($response); } } /** * 过滤掉字符串中的 sql 关键字 */ if (!function_exists('filter_sql')) { function filter_sql($str) { $str = strtolower($str); // 转小写 $str = str_replace("and", "", $str); $str = str_replace("execute", "", $str); $str = str_replace("update", "", $str); $str = str_replace("count", "", $str); $str = str_replace("chr", "", $str); $str = str_replace("mid", "", $str); $str = str_replace("master", "", $str); $str = str_replace("truncate", "", $str); $str = str_replace("char", "", $str); $str = str_replace("declare", "", $str); $str = str_replace("select", "", $str); $str = str_replace("create", "", $str); $str = str_replace("delete", "", $str); $str = str_replace("insert", "", $str); $str = str_replace("union", "", $str); $str = str_replace("alter", "", $str); $str = str_replace("into", "", $str); $str = str_replace("'", "", $str); $str = str_replace("or", "", $str); $str = str_replace("=", "", $str); return $str; } } /** * 检测字符串是否是版本号 */ if (!function_exists('is_version_str')) { /** * 检测字符串是否是版本号 * @param string $version * @return boolean */ function is_version_str($version) { $match = "/^([0-9]\d|[0-9])(\.([0-9]\d|\d))+/"; return preg_match($match, $version) ? true : false; } } /** * 删除目录 */ if (!function_exists('rmdirs')) { /** * 删除目录 * @param string $dirname 目录 * @param bool $withself 是否删除自身 * @return boolean */ function rmdirs($dirname, $withself = true) { if (!is_dir($dirname)) { return false; } $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($dirname, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); foreach ($files as $fileinfo) { if ($fileinfo->isDir() === 'rmdir') rmdir(($fileinfo->getRealPath())); if ($fileinfo->isDir() === 'unlink') unlink(($fileinfo->getRealPath())); } if ($withself) { @rmdir($dirname); } return true; } } /** * 复制目录 */ if (!function_exists('copydirs')) { /** * 复制目录 * @param string $source 源文件夹 * @param string $dest 目标文件夹 */ function copydirs($source, $dest) { if (!is_dir($dest)) { @mkdir($dest, 0755, true); } foreach ($iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST ) as $item) { if ($item->isDir()) { $sontDir = $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName(); if (!is_dir($sontDir)) { @mkdir($sontDir, 0755, true); } } else { copy($item, $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName()); } } } } if (!function_exists('is_url')) { function is_url($url) { if (preg_match("/^(http:\/\/|https:\/\/)/", $url)) { return true; } return false; } } /** * 快捷设置跨域请求头(跨域中间件失效时,一些特殊拦截时候需要用到) */ if (!function_exists('set_cors')) { /** * 快捷设置跨域请求头(跨域中间件失效时,一些特殊拦截时候需要用到) * * @return void */ function set_cors() { $header = [ 'Access-Control-Allow-Origin' => '*', // 规避跨域 'Access-Control-Allow-Credentials' => 'true', 'Access-Control-Max-Age' => 1800, 'Access-Control-Allow-Methods' => 'GET, POST, PATCH, PUT, DELETE, OPTIONS', 'Access-Control-Allow-Headers' => 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With, platform', ]; // 直接将 header 添加到响应里面 foreach ($header as $name => $val) { header($name . (!is_null($val) ? ':' . $val : '')); } if (request()->isOptions()) { // 如果是预检直接返回响应,后续都不在执行 exit; } } } if (!function_exists('sheep_config')) { /** * 获取SheepAdmin配置 * @param string $code 配置名 * @return string */ function sheep_config(string $code, $cache = true) { return \app\admin\model\shopro\Config::getConfigs($code, $cache); } } /** * 获取前端用户 */ if (!function_exists('auth_user')) { function auth_user($throwException = false) { if (\app\common\library\Auth::instance()->isLogin()) { return \app\common\library\Auth::instance()->getUser(); } if ($throwException) { error_stop('请登录后操作', 0, null, 401); } return null; } } /** * 获取管理员信息 */ if (!function_exists('auth_admin')) { function auth_admin() { if (\app\admin\library\Auth::instance()->isLogin()) { $admin = \app\admin\library\Auth::instance()->getUserInfo(); // 这里获取的是个数组,转为模型 if ($admin) { return \app\admin\model\shopro\Admin::where('id', $admin['id'])->find(); } } return null; } } if (!function_exists('has_redis')) { /** * 判断是否配置好了 redis * * @param boolean $is_exception 是否 抛出异常 * @return boolean */ function has_redis($is_exception = false, $cache = true) { $key = 'has_redis'; if ($cache && cache('?' . $key)) { // 使用缓存,并且存在缓存 return cache($key); } $error_msg = ''; try { addons\shopro\facade\Redis::ping(); } catch (\BadFunctionCallException $e) { // 缺少扩展 $error_msg = $e->getMessage() ? $e->getMessage() : "缺少 redis 扩展"; } catch (\RedisException $e) { // 连接拒绝 \think\Log::write('redis connection redisException fail: ' . $e->getMessage()); $error_msg = $e->getMessage() ? $e->getMessage() : "redis 连接失败"; } catch (\Exception $e) { // 异常 \think\Log::write('redis connection fail: ' . $e->getMessage()); $error_msg = $e->getMessage() ? $e->getMessage() : "redis 连接异常"; } cache($key, ($error_msg ? false : true), 10); // 保存缓存 if ($error_msg) { if ($is_exception) { throw new \Exception($error_msg); } else { return false; } } return true; } } if (!function_exists('redis_cache')) { /** * 缓存管理 * @param mixed $name 缓存名称,如果为数组表示进行缓存设置 * @param mixed $value 缓存值 * @param mixed $options 缓存参数 * @param string $tag 缓存标签 * @return mixed */ function redis_cache($name = null, $value = '', $ttl = null) { $cache = new \addons\shopro\library\RedisCache; if ($name === null) { return $cache; } elseif ('' === $value) { // 获取缓存 return 0 === strpos($name, '?') ? $cache->has(substr($name, 1)) : $cache->get($name); } elseif (is_null($value)) { // 删除缓存 return $cache->delete($name); } else { // 缓存数据 return $cache->set($name, $value, $ttl); } } } /** * 检测系统必要环境 */ if (!function_exists('check_env')) { function check_env($need = [], $is_throw = true) { $need = is_string($need) ? [$need] : $need; // 检测是否安装浮点数运算扩展 if (in_array('bcmath', $need)) { if (!extension_loaded('bcmath')) { if ($is_throw) { error_stop('请安装浮点数扩展 【bcmath】'); } else { return false; } } } // 检测是否安装了队列 if (in_array('queue', $need)) { if (!class_exists(\think\Queue::class)) { if ($is_throw) { error_stop('请安装 【topthink/think-queue:v1.1.6 队列扩展】'); } else { return false; } } } // 检查是否有分销功能 if (in_array('commission', $need)) { if (!class_exists(\addons\shopro\listener\Commission::class)) { if ($is_throw) { error_stop('请先升级 【shopro】'); } else { return false; } } } // 检查是否安装了支付扩展包 if (in_array('yansongda', $need)) { //读取插件的状态,epay为插件标识 $info = get_addon_info('epay'); if (!$info || !$info['state']) { if ($is_throw) { error_stop('请确保【微信支付宝整合插件】已安装并启用'); } else { return false; } } if (version_compare($info['version'], '1.3.0') < 0) { if ($is_throw) { error_stop('请安装【微信支付宝整合插件】v1.3.0 及以上版本'); } else { return false; } } } return true; } } if (!function_exists('diff_in_time')) { /** * 计算两个时间相差多少天,多少小时,多少分钟 * * @param int $first 要比较的第一个时间 Carbon 或者时间格式 * @param mixed $second 要比较的第二个时间 Carbon 或者时间格式 * @param bool $format 是否格式化为字符串 * @return string|array */ function diff_in_time($first, $second = null, $format = true, $simple = false) { $second = is_null($second) ? time() : $second; $diff = abs($first - $second); // 取绝对值 $years = floor($diff / (86400 * 365)); $surplus = $diff % (86400 * 365); $days = floor($surplus / 86400); $surplus = $surplus % 86400; $hours = floor($surplus / 3600); $surplus = $surplus % 3600; $minutes = floor($surplus / 60); $surplus = $surplus % 60; $second = $surplus; if (!$format) { return compact('years', 'days', 'hours', 'minutes', 'second'); } $format_text = ''; $start = false; if ($years) { $start = true; $format_text .= $years . '年'; } if ($start || $days) { $start = true; $format_text .= ($days % 365) . '天'; } if ($start || $hours) { $start = true; $format_text .= ($hours % 24) . '时'; } if ($start || $minutes) { $start = true; $format_text .= ($minutes % 60) . '分钟'; } if (($start || $second) && !$simple) { $start = true; $format_text .= ($second % 60) . '秒'; } return $format_text; } } if (!function_exists('short_var_export')) { /** * 使用短标签打印或返回数组结构 * @param mixed $data * @param boolean $return 是否返回数据 * @return string */ function short_var_export($expression, $return = FALSE) { $export = var_export($expression, TRUE); $patterns = [ "/array \(/" => '[', "/^([ ]*)\)(,?)$/m" => '$1]$2', "/=>[ ]?\n[ ]+\[/" => '=> [', "/([ ]*)(\'[^\']+\') => ([\[\'])/" => '$1$2 => $3', ]; $export = preg_replace(array_keys($patterns), array_values($patterns), $export); if ((bool)$return) return $export; else echo $export; } } if (!function_exists('get_sn')) { /** * 获取唯一编号 * * @param mixed $id 唯一标识 * @param string $type 类型 * @return string */ function get_sn($id, $type = '') { $id = (string)$id; $rand = $id < 9999 ? mt_rand(100000, 99999999) : mt_rand(100, 99999); $sn = date('Yhis') . $rand; $id = str_pad($id, (24 - strlen($sn)), '0', STR_PAD_BOTH); return $type . $sn . $id; } } if (!function_exists('string_hide')) { /** * 隐藏部分字符串 * * @param string $string 原始字符串 * @param int $start 开始位置 * @return string */ function string_hide($string, $start = 2) { if (mb_strlen($string) > $start) { $hide = mb_substr($string, 0, $start) . '***'; } else { $hide = $string . '***'; } return $hide; } } if (!function_exists('account_hide')) { /** * 隐藏账号部分字符串 * * @param string $string 原始字符串 * @param int $start 开始位置 * @param int $end 开始位置 * @return string */ function account_hide($string, $start = 2, $end = 2) { $hide = mb_substr($string, 0, $start) . '*****' . mb_substr($string, -$end); return $hide; } } if (!function_exists('gen_random_str')) { /** * 随机生成字符串 * @param int $length 字符串长度 * @return bool $upper 默认小写 */ function gen_random_str($length = 10, $upper = false) { if ($upper) { $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; } else { $characters = '0123456789abcdefghijklmnopqrstuvwxyz'; } $randomString = ''; for ($i = 0; $i < $length; $i++) { $randomString .= $characters[rand(0, strlen($characters) - 1)]; } return $randomString; } } if (!function_exists('random_mobile')) { /** * 随机生成字符串 * @param int $length 字符串长度 * @return bool $upper 默认小写 */ function random_mobile() { $mobile = '1'; $second = [3, 5, 7, 8, 9]; return $mobile . $second[array_rand($second)] . mt_rand(100000000, 999999999); } } if (!function_exists('random_email')) { /** * 随机生成字符串 * @param int $length 字符串长度 * @return bool $upper 默认小写 */ function random_email($prefix = '') { $first = [ random_mobile(), gen_random_str(mt_rand(6, 15), mt_rand(0, 1)), ]; $first_name = $prefix ?: $first[array_rand($first)]; $suffix = [ '@gmail.com', '@msn.com', '@qq.com', '@163.com', '@163.net', '@126.com', '@139.com', '@189.cn', '@sina.com', ]; return $first_name . $suffix[array_rand($suffix)]; } } if (!function_exists('format_log_error')) { /** * 格式化记录日志,重要地方使用 * * @param object $error * @param string $name * @param string $message * @return void */ function format_log_error($error, $name = 'QUEUE', $message = '') { $logInfo = [ "========== $name LOG INFO BEGIN ==========", '[ Message ] ' . var_export('[' . $error->getCode() . ']' . $error->getMessage() . ' ' . $message, true), '[ File ] ' . var_export($error->getFile() . ':' . $error->getLine(), true), '[ Trace ] ' . var_export($error->getTraceAsString(), true), "============================================= $name LOG INFO ENDED ==========", ]; $logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL; \think\Log::error($logInfo); } } if (!function_exists('set_token_in_header')) { /** * 设置token令牌到响应的header中 * * @param string $token * @return void */ function set_token_in_header($token) { header("Access-Control-Expose-Headers: token"); header("token: $token"); } } if (!function_exists('morph_to')) { /** * 多态关联 * * @param array|object $items * @param array $morphs * @param array $fields * @return array|object */ function morph_to($items, $morphs, $fields) { if ($items instanceof \think\Paginator) { $data = $items->items(); } else if ($items instanceof \think\Collection) { $data = $items; } else { $data = collection($items); } $allIds = []; foreach ($data as $item) { $allIds[$item[$fields[0]]][] = $item[$fields[1]]; } $morphsData = []; foreach ($allIds as $key => $ids) { $morphData = (new $morphs[$key])::where('id', 'in', $ids)->select(); $morphsData[$key] = array_column($morphData, null, 'id'); } $morph_key = strstr($fields[0], '_', true); foreach ($data as &$item) { $item->{$morph_key} = $morphsData[$item[$fields[0]]][$item[$fields[1]]] ?? null; } if ($items instanceof \think\Paginator) { $items->data = $items; } else { $items = $data; } return $items; } } if (!function_exists('image_resize_save')) { /** * 图片裁剪缩放并保存 * @param string $image_url 图片地址 * @param string $save_path 保存地址 * @param string $target_w 目标宽度 * @param string $target_h 目标高度 * @return void */ function image_resize_save($image_url, $save_path, $target_w = 200, $target_h = 200) { $dst_h = 200; $dst_w = 200; list($src_w, $src_h) = getimagesize($image_url); $dst_scale = $dst_h / $dst_w; // 目标图像长宽比,正方形 $src_scale = $src_h / $src_w; // 原图长宽比 if ($src_scale >= $dst_scale) { // 过高 $w = intval($src_w); $h = intval($dst_scale * $w); $x = 0; $y = ($src_h - $h) / 3; } else { // 过宽 $h = intval($src_h); $w = intval($h / $dst_scale); $x = ($src_w - $w) / 2; $y = 0; } // 剪裁 $source = imagecreatefrompng($image_url); $croped = imagecreatetruecolor($w, $h); imagecopy($croped, $source, 0, 0, $x, $y, $src_w, $src_h); if ($w > $dst_w) { $scale = $dst_w / $w; $target = imagecreatetruecolor($dst_w, $dst_h); $final_w = intval($w * $scale); $final_h = intval($h * $scale); imagecopyresampled($target, $croped, 0, 0, 0, 0, $final_w, $final_h, $w, $h); } // 创建目录 $dir = dirname($save_path); if (!is_dir($dir)) { @mkdir($dir, 0755, true); } imagejpeg($target, $save_path); imagedestroy($target); } } if (!function_exists('get_addonnames')) { /** * 获取已安装的插件 * * @param $type enable:已安装启用的插件,disabled:已安装禁用的插件,all:所有插件 */ function get_addonnames($type = 'enable') { $key = 'shopro_fa_addons_list'; if (redis_cache('?' . $key)) { $addons = redis_cache($key); } else { $addons = get_addon_list(); redis_cache($key, $addons, 300); } $addonList = [ 'all' => [], 'enable' => [], 'disabled' => [] ]; foreach ($addons as $addon_name => $info) { $addonList['all'][] = $addon_name; $addonList[($info['state'] == 1 ? 'enable' : 'disabled')][] = $addon_name; } return $addonList[$type] ?? []; } } /** * 删除 sql mode 指定模式,或者直接关闭 sql mode */ if (!function_exists('closeStrict')) { function closeStrict($modes = []) { $modes = array_filter(is_array($modes) ? $modes : [$modes]); $result = \think\Db::query("SELECT @@session.sql_mode "); $newModes = $oldModes = explode(',', ($result[0]['@@session.sql_mode'] ?? '')); if ($modes) { foreach ($modes as $mode) { $delkey = array_search($mode, $newModes); if ($delkey !== false) { unset($newModes[$delkey]); } } $newModes = join(',', array_values(array_filter($newModes))); } else { $newModes = ''; } \think\Db::execute("set session sql_mode='" . $newModes . "'"); return $oldModes; } } /** * 重新打开被关闭的 sql mode */ if (!function_exists('recoverStrict')) { function recoverStrict($modes = [], $append = false) { if ($append) { $result = \think\Db::query("SELECT @@session.sql_mode "); $oldModes = explode(',', ($result[0]['@@session.sql_mode'] ?? '')); $modes = array_values(array_filter(array_unique(array_merge($oldModes, $modes)))); } \think\Db::execute("set session sql_mode='" . join(',', $modes) . "'"); } } // **********************以下方法请忽略********************* // 当前方法直接返回 $value, 请忽略该方法 if (!function_exists('config_show')) { function config_show($value, $data) { if (class_exists(\app\common\library\ShowHow::class)) { return \app\common\library\ShowHow::configHide($value, $data); } return $value; } } // 当前方法直接返回 $config, 请忽略该方法 if (!function_exists('pay_config_show')) { function pay_config_show($config) { if (class_exists(\app\common\library\ShowHow::class)) { return \app\common\library\ShowHow::payConfigHide($config); } return $config; } } // 当前方法全部返回 true, 请忽略该方法 if (!function_exists('operate_filter')) { function operate_filter($is_exception = true) { if (class_exists(\app\common\library\ShowHow::class)) { return \app\common\library\ShowHow::operateFilter($is_exception); } return true; } } // 当前方法全部返回 true, 请忽略 if (!function_exists('operate_disabled')) { function operate_disabled($is_exception = true) { if (class_exists(\app\common\library\ShowHow::class)) { return \app\common\library\ShowHow::operateDisabled($is_exception); } return true; } }