// +---------------------------------------------------------------------- declare (strict_types=1); /** * 应用公共函数库文件 */ use think\Response; use think\facade\Env; use think\facade\Log; use think\facade\Config; use think\facade\Request; use app\common\library\helper; use app\common\exception\BaseException; use think\exception\HttpResponseException; /** * 打印调试函数 * @param $content * @param bool $isDie * @param bool $export */ function pre($content, bool $isDie = true, bool $export = false) { header('Content-type: text/html; charset=utf-8'); $output = $export ? var_export($content, true) : print_r($content, true); echo "
{$output}"; $isDie && die; } /** * 规则:生成随机数,最多14位数字 * @return string */ function random_num($len = 9) { return substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 9); } /** * 规则:生成随机字符 * @return string */ function random_character($len = 8) { $arr = array_merge(range(0,9),range('a','z'),range('A','Z')); $str = ''; for ($i=0;$i<$len;$i++){ $str .= $arr[rand(0,count($arr)-1)]; } return $str; } /** * 输出错误信息 * @param string $message 报错信息 * @param int|null $status 状态码,默认为配置文件status.error * @param array $data 附加数据 * @throws BaseException */ function throwError(string $message, $status = null, array $data = []) { is_null($status) && $status = config('status.error'); throw new BaseException(['status' => $status, 'msg' => $message, 'data' => $data]); } /** * 下划线转驼峰 * @param $uncamelized_words * @param string $separator * @return string */ function camelize($uncamelized_words, $separator = '_') { $uncamelized_words = $separator . str_replace($separator, " ", strtolower($uncamelized_words)); return ltrim(str_replace(" ", "", ucwords($uncamelized_words)), $separator); } /** * 驼峰转下划线 * @param $camelCaps * @param string $separator * @return string */ function uncamelize($camelCaps, $separator = '_') { return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps)); } /** * 生成密码hash值 * @param $password * @return string */ function encryption_hash($password) { return password_hash($password, PASSWORD_DEFAULT); } /** * 获取当前域名及根路径 * @return string */ function base_url() { static $baseUrl = ''; if (empty($baseUrl)) { $request = Request::instance(); // url协议,设置强制https或自动获取 $scheme = Config::get('route')['url_force_https'] ? 'https' : $request->scheme(); // url子目录 $rootUrl = root_url(); // 拼接完整url $baseUrl = "{$scheme}://" . $request->host() . $rootUrl; } return $baseUrl; } /** * 获取当前uploads目录访问地址 * @return string */ function uploads_url() { return base_url() . 'uploads'; } /** * 获取当前url的子目录路径 * @return string */ function root_url() { static $rootUrl = ''; if (empty($rootUrl)) { $request = Request::instance(); $subUrl = str_replace('\\', '/', dirname($request->baseFile())); $rootUrl = $subUrl . ($subUrl === '/' ? '' : '/'); } return $rootUrl; } /** * 获取当前的应用名称 * @return mixed */ function app_name() { return app('http')->getName(); } /** * 获取web根目录 * @return string */ function web_path() { static $webPath = ''; if (empty($webPath)) { $request = Request::instance(); $webPath = dirname($request->server('SCRIPT_FILENAME')) . DIRECTORY_SEPARATOR; } return $webPath; } /** * 获取runtime根目录路径 * @return string */ function runtime_root_path() { return dirname(runtime_path()) . DIRECTORY_SEPARATOR; } /** * 写入日志 (使用tp自带驱动记录到runtime目录中) * @param $value * @param string $type */ function log_record($value, $type = 'info') { $content = is_string($value) ? $value : print_r($value, true); Log::record($content, $type); } /** * curl请求指定url (post) * @param $url * @param array $data * @return mixed */ function curl_post($url, $data = []) { $ch = curl_init(); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $result = curl_exec($ch); curl_close($ch); return $result; } /** * 多维数组合并 * @param $array1 * @param $array2 * @return array */ function array_merge_multiple($array1, $array2) { $merge = $array1 + $array2; $data = []; foreach ($merge as $key => $val) { if ( isset($array1[$key]) && is_array($array1[$key]) && isset($array2[$key]) && is_array($array2[$key]) ) { $data[$key] = is_assoc($array1[$key]) ? array_merge_multiple($array1[$key], $array2[$key]) : $array2[$key]; } else { $data[$key] = isset($array2[$key]) ? $array2[$key] : $array1[$key]; } } return $data; } /** * 判断是否为自定义索引数组 * @param array $array * @return bool */ function is_assoc(array $array) { if (empty($array)) return false; return array_keys($array) !== range(0, count($array) - 1); } /** * 二维数组排序 * @param $arr * @param $keys * @param bool $desc * @return mixed */ function array_sort($arr, $keys, $desc = false) { $key_value = $new_array = array(); foreach ($arr as $k => $v) { $key_value[$k] = $v[$keys]; } if ($desc) { arsort($key_value); } else { asort($key_value); } reset($key_value); foreach ($key_value as $k => $v) { $new_array[$k] = $arr[$k]; } return $new_array; } /** * 隐藏敏感字符 * @param $value * @return string */ function substr_cut($value) { $strlen = mb_strlen($value, 'utf-8'); if ($strlen <= 1) return $value; $firstStr = mb_substr($value, 0, 1, 'utf-8'); $lastStr = mb_substr($value, -1, 1, 'utf-8'); return $strlen == 2 ? $firstStr . str_repeat('*', $strlen - 1) : $firstStr . str_repeat("*", $strlen - 2) . $lastStr; } /** * 获取当前系统版本号 * @return mixed|null * @throws Exception */ function get_version() { static $version = []; if (!empty($version)) { return $version['version']; } // 读取version.json文件 $file = root_path() . '/version.json'; if (!file_exists($file)) { throw new Exception('version.json not found'); } // 解析json数据 $version = helper::jsonDecode(file_get_contents($file)); if (!is_array($version)) { throw new Exception('version cannot be decoded'); } return $version['version']; } /** * 获取全局唯一标识符 * @param bool $trim * @return string */ function get_guid_v4($trim = true) { // Windows if (function_exists('com_create_guid') === true) { $charid = com_create_guid(); return $trim == true ? trim($charid, '{}') : $charid; } // OSX/Linux if (function_exists('openssl_random_pseudo_bytes') === true) { $data = openssl_random_pseudo_bytes(16); $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100 $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10 return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); } // Fallback (PHP 4.2+) mt_srand(intval((double)microtime() * 10000)); $charid = strtolower(md5(uniqid((string)rand(), true))); $hyphen = chr(45); // "-" $lbrace = $trim ? "" : chr(123); // "{" $rbrace = $trim ? "" : chr(125); // "}" return $lbrace . substr($charid, 0, 8) . $hyphen . substr($charid, 8, 4) . $hyphen . substr($charid, 12, 4) . $hyphen . substr($charid, 16, 4) . $hyphen . substr($charid, 20, 12) . $rbrace; } /** * 时间戳转换日期 * @param $timeStamp * @return false|string */ function format_time($timeStamp) { return $timeStamp>0?date('Y-m-d H:i:s', $timeStamp):''; } /** * 左侧填充0 * @param $value * @param int $padLength * @return string */ function pad_left($value, $padLength = 2) { return \str_pad($value, $padLength, "0", STR_PAD_LEFT); } /** * 重写trim方法 (解决int类型过滤后后变为string类型) * @param $str * @return string */ function my_trim($str) { return is_string($str) ? trim($str) : $str; } /** * 重写htmlspecialchars方法 (解决int类型过滤后后变为string类型) * @param $string * @return string */ function my_htmlspecialchars($string) { return is_string($string) ? htmlspecialchars($string) : $string; } /** * 过滤emoji表情 * @param $text * @return null|string|string[] */ function filter_emoji($text) { if (!is_string($text)) { return $text; } // 此处的preg_replace用于过滤emoji表情 // 如需支持emoji表情, 需将mysql的编码改为utf8mb4 return preg_replace('/[\xf0-\xf7].{3}/', '', $text); } /** * 根据指定长度截取字符串 * @param $str * @param int $length * @return bool|string */ function str_substr($str, $length = 30) { if (strlen($str) > $length) { $str = mb_substr($str, 0, $length); } return $str; } /** * 结束执行 */ function app_end() { throw new HttpResponseException(Response::create()); } /** * 当前是否为调试模式 * @return bool */ function is_debug() { return (bool)Env::instance()->get('APP_DEBUG'); } /** * 文本左斜杠转换为右斜杠 * @param $string * @return mixed */ function convert_left_slash(string $string) { return str_replace('\\', '/', $string); } /** * 隐藏手机号中间四位 13012345678 -> 130****5678 * @param string $mobile 手机号 * @return string */ function hide_mobile(string $mobile) { return substr_replace($mobile, '****', 3, 4); } /** * 隐藏手机号中间四位 42102200201019999 -> 4210************999 * @param string $idcard 手机号 * @return string */ function hide_id_card(string $idcard) { return substr_replace($idcard, '***********', 4, 11); } /** * 生成用户昵称 */ function make_nickname(string $mobile) { return '用户' . substr($mobile, -4); } /** * 获取当前登录的商城ID * @return int $storeId */ function getStoreId() { return 10001; } /** * 获取缩短后的字符串 * @return string */ function limit_str(string $str,int $limit=6) { if(mb_strlen($str)<$limit){ return $str; }else{ return mb_substr(strip_tags($str),0,$limit,'UTF-8')."..."; } } /** * 获取指定范围的所有日期 * * @param int $start * @param int $end * @param string $format * @return array */ function period_date($start, $end, $format = 'Y-m-d') { $arr = []; while ($start <= $end) { $arr[] = date($format, $start); $start = strtotime('+1 day', $start); } return $arr; } /** * 获取指定范围的所有周 * * @param int $start * @param int $end * @param boolean 是否过滤不满一周的数据 * * @return array */ function period_week($start, $end, $filter = false) { //开始时间 $startDate = date('Y-m-d', $start); //结束时间 if (empty($end)) { $endDate = date('Y-m-d'); } else { $endDate = date('Y-m-d', $end); } //跨越天数 $n = (strtotime($endDate) - strtotime($startDate)) / 86400; //判断,跨度小于7天,可能是同一周,也可能是两周 $endDate = date("Y-m-d", strtotime("$endDate +1 day")); if ($n < 7) { //查开始时间 在 那周 的 位置 $day = date("w", strtotime($startDate)) - 1; //查开始时间 那周 的 周一 $week_start = date("Y-m-d", strtotime("$startDate -{$day} day")); //查开始时间 那周 的 周末 $day = 7 - $day; $week_end = date("Y-m-d", strtotime("$startDate +{$day} day")); //判断周末时间是否大于时间段的结束时间,如果大于,那就是时间段在同一周,否则时间段跨两周 if ($week_end >= $endDate) { $weekList[] = array('s' => $startDate, 'e' => date("Y-m-d", strtotime("$endDate -1 day"))); } else { $weekList[] = array('s' => $startDate, 'e' => date("Y-m-d", strtotime("$week_end -1 day"))); $weekList[] = array('s' => $week_end, 'e' => date("Y-m-d", strtotime("$endDate -1 day"))); } } else { //如果跨度大于等于7天,可能是刚好1周或跨2周或跨N周,先找出开始时间 在 那周 的 位置和那周的周末时间 $day = date("w", strtotime($startDate)) - 1; $week_start = date("Y-m-d", strtotime("$startDate -{$day} day")); $day = 7 - $day; $week_end = date("Y-m-d", strtotime("$startDate +{$day} day")); //先把开始时间那周写入数组 $weekList[] = array('s' => $startDate, 'e' => date("Y-m-d", strtotime("$week_end -1 day"))); //判断周末是否大于等于结束时间,不管大于(2周)还是等于(1周),结束时间都是时间段的结束时间。 if ($week_end >= $endDate) { $weekList[] = array('s' => $week_end, 'e' => date("Y-m-d", strtotime("$endDate -1 day"))); } else { //N周的情况用while循环一下,然后写入数组 while ($week_end <= $endDate) { $start = $week_end; $week_end = date("Y-m-d", strtotime("$week_end +7 day")); if ($week_end <= $endDate) { $weekList[] = array('s' => $start, 'e' => date("Y-m-d", strtotime("$week_end -1 day"))); } else { // 如果当前时间是每周第一天 if ($start == $endDate) { $weekList[] = array('s' => $start, 'e' => date("Y-m-d", strtotime("$endDate 0 day"))); } else { $weekList[] = array('s' => $start, 'e' => date("Y-m-d", strtotime("$endDate -1 day"))); } } } } } // 过滤不满一周天数的数据 $firstWeek = current($weekList); $lastWeek = end($weekList); $firstWeekDays = (strtotime($firstWeek['e']) - strtotime($firstWeek['s'])) / 86400; $lastWeekDays = (strtotime($lastWeek['e']) - strtotime($lastWeek['s'])) / 86400; if ($firstWeekDays < 7 && $filter) { array_shift($weekList); } if ($lastWeekDays < 7 && $filter) { array_pop($weekList); } return $weekList; } /** * 生成从开始月份到结束月份的月份数组 * @param int $start 开始时间戳 * @param int $end 结束时间戳 * @param boolean 是否过滤当前月等于最后一个月的数据 */ function period_month($start, $end, $filter = false) { if (!is_numeric($start) || !is_numeric($end) || ($end <= $start)) return ''; $start = date('Y-m', $start); $end = date('Y-m', $end); //转为时间戳 $start = strtotime($start . '-01'); $end = strtotime($end . '-01'); $i = 0; $d = array(); while ($start <= $end) { //这里累加每个月的的总秒数 计算公式:上一月1号的时间戳秒数减去当前月的时间戳秒数 $d[$i] = trim(date('Y-m', $start), ' '); $start += strtotime('+1 month', $start) - $start; $i++; } if (end($d) == date('Y-m') && $filter) { array_pop($d); } return $d; } function month_first_last($date) { $firstday = date('Y-m-01', strtotime($date)); $lastday = date('Y-m-d', strtotime("$firstday +1 month -1 day")); return ['s' => $firstday, 'e'=>$lastday]; } /** * 获取上月月份 * @param int $days 默认上个月 * @return false|string */ function last_month($format = "Y-m", $days = 1, $time = 0) { if (!$time) { $time = time(); } return date($format, strtotime(date('Y-m-01') . " -{$days} month", $time)); } function last_week_between_time() { $s = mktime(0,0,0,(int)date('m'),(int)(date('d')-date('w')+1-7),(int)date('Y')); $e = mktime(23,59,59,(int)date('m'),(int)(date('d')-date('w')+7-7),(int)date('Y')); return ['s' => $s, 'e'=>$e]; } /* POST */ function post_curl($posturl, $params, $method = 'POST', $header = '') { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $posturl); if ($header) curl_setopt($curl, CURLOPT_HTTPHEADER, $header); switch ($method) { case 'GET': curl_setopt($curl, CURLOPT_HTTPGET, 1); case 'POST': curl_setopt($curl, CURLOPT_POST, 1); break; case 'PUT': curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); break; case 'DELETE': curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); break; } curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, False); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($curl, CURLOPT_HEADER, FALSE); curl_setopt($curl, CURLOPT_POSTFIELDS, $params); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $retdata = curl_exec($curl); curl_close($curl); return $retdata; }