= 4 ? '' : $match[0]; }, $str); } /** * @desc 字节转换 * @param int $numSize * @return string */ public static function sizeConvert(int $numSize) { if ($numSize >= 1073741824) { $charSize = round($numSize / pow(1024, 3) * 100) / 100 . ' GB'; } elseif ($numSize >= 1048576) { //转成MB $charSize = round($numSize / pow(1024, 2) * 100) / 100 . ' MB'; } elseif ($numSize >= 1024) { //转成KB $charSize = round($numSize / 1024 * 100) / 100 . ' KB'; } else { //不转换直接输出 $charSize = $numSize . ' B'; } return $charSize; } /** * @desc 数字单位转换 * @param int $number * @return string */ public static function numberConvert(int $number) { if ($number >= 1000 && $number < 10000) { $number = sprintf('%.1f', $number / 1000) . ' K'; } elseif ($number >= 10000) { $number = sprintf('%.1f', $number / 10000) . ' W'; } elseif ($number >= 1000000) { $number = sprintf('%.1f', $number / 10000) . ' M'; } return $number; } /** * @desc 生成 hash token * @param string $value * @return mixed */ public static function hashToken(string $value) { $hash = hash_hmac('sha1', $value . mt_rand() . time(), mt_rand(), true); $token = str_replace('=', '', strtr(base64_encode($hash), '+/', '-_')); return $token; } /** * @desc 是否微信环境 * @return bool|mixed */ public static function isWeixin() { return strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false ? true : false; } /** * @desc ssl 加密 * @param $str 待加密字符 * @param string $key 加密key * @param string $iv 偏移iv * @return string */ public static function encrypt($str, $key = 'cdlchdwxcdh5', $iv = 'cdlchd0123456789') { return bin2hex(openssl_encrypt($str, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv)); } /** * @desc ssl 解密 * @param $str 待解密字符 * @param string $key 加密key * @param string $iv 偏移iv * @return string */ public static function decrypt($str, $key = 'cdlchdwxcdh5', $iv = 'cdlchd0123456789') { return openssl_decrypt(hex2bin($str), 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv); } /** * @desc 记录日志 * @param array $data * @param string $remarks */ public static function apiLogs(array $data, string $remarks = '') { $request = \request(); $data = [ 'token' => $request->header('token', null), 'uid' => Auth::$userId, 'url' => $request->url(), 'controller' => $request->controller(), 'func' => $request->action(), 'method' => $request->method(), 'ip' => $request->ip(), 'params' => json_encode($data, 256), 'remarks' => $remarks, 'day' => strtotime('today'), 'create' => time() ]; $rdsConf = Config::get('lc.redis'); if ($rdsConf['log_open']) { $redis = Redis::instance(); $redis->select($rdsConf['db']); $redis->rPush(env('id') . '_apilogs', json_encode($data, 256)); } else { Db::name('api_logs')->insert($data); } } /** * @desc 将xml转为array * @param $xml * @return array * @throws \Exception */ public static function xmlToArray($xml) { if (!$xml) { throw new \Exception('xml数据异常!'); } //禁止引用外部xml实体 libxml_disable_entity_loader(true); $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $data; } /** * @desc 输出xml字符 * @param array $data * @return string * @throws \Exception */ public static function arrayToXml($data) { if (!is_array($data) || count($data) <= 0) { throw new \Exception('数组数据异常!'); } $xml = ''; foreach ($data as $key => $val) { if (is_numeric($val)) { $xml .= '<' . $key . '>' . $val . ''; } else { $xml .= '<' . $key . '>'; } } $xml .= ''; return $xml; } /** * @desc 按字典序生成签名 * @param array $data 签名数据 * @param string $key 前面key * @return string */ public static function makeSign(array $data, string $key) { // 1. 按字典序排序参数 ksort($data); $string = self::signUrlParams($data); // 2. 在string后加入KEY $string = $string . '&key=' . $key; // 3. MD5加密 $string = md5($string); // 4. 所有字符转为大写 return strtoupper($string); } /** * @desc 签名格式化成url参数 * @param array $params 格式化参数 * @return string */ private static function signUrlParams(array $params) { $buff = ''; foreach ($params as $k => $v) { if ($k != 'sign' && $v != '' && !is_array($v)) { $buff .= $k . '=' . $v . '&'; } } $buff = trim($buff, '&'); return $buff; } /** * @desc 获取毫秒级别的时间戳 */ public static function millisecond() { // 获取毫秒的时间戳 $time = explode(' ', microtime()); $time = $time[1] . ($time[0] * 1000); $time2 = explode('.', $time); $time = $time2[0]; return $time; } /** * @desc 产生随机字符串,不长于32位 * @param int $length * @return string 产生的随机字符串 */ public static function generateNonceStr($length = 32) { $chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; $str = ''; for ($i = 0; $i < $length; $i++) { $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); } return $str; } /** * @desc 对emoji表情转义 * @param $str * @return string */ public static function emojiEncode($str) { $strEncode = ''; $length = mb_strlen($str, 'utf-8'); for ($i = 0; $i < $length; $i++) { $tmpStr = mb_substr($str, $i, 1, 'utf-8'); if (strlen($tmpStr) >= 4) { $strEncode .= '[[EMOJI:' . rawurlencode($tmpStr) . ']]'; } else { $strEncode .= $tmpStr; } } return $strEncode; } /** * @desc 对emoji表情转反义 * @param $str * @return string|string[]|null */ public static function emojiDecode($str) { return preg_replace_callback('|\[\[EMOJI:(.*?)\]\]|', function ($matches) { return rawurldecode($matches[1]); }, $str); } /** * @desc 判断请求机型 * @return string */ public static function deviceType() { $agent = strtolower($_SERVER['HTTP_USER_AGENT']); $type = 'other'; //分别进行判断 if (strpos($agent, 'iphone') || strpos($agent, 'ipad')) { $type = 'ios'; } if (strpos($agent, 'android')) { $type = 'android'; } return $type; } /** * @desc 记录日志 * @param string $filename 文件名 * @param string $log 日志内容 * @param float|int $fileSize 文件日志大小,默认最大2M,超过则重命名 */ public static function log(string $filename, string $log, $fileSize = 2 * 1024 * 1024) { $path = dirname($filename); if (!is_dir($path)) { mkdir($path, 0755, true); } if (is_file($filename) && floor($fileSize) <= filesize($filename)) { try { rename($filename, dirname($filename) . DIRECTORY_SEPARATOR . time() . '-' . basename($filename)); } catch (\Exception $e) { // } } error_log($log, 3, $filename); } /** * 求两点之间的距离 * @param $thisLongitude 当前经度 * @param $thisLatitude 当前纬度 * @param $stayLongitude 待计算经度 * @param $stayLatitude 待计算纬度 * @param int $unit 单位,1米,2千米 * @param int $decimals 保留小数点几位 * @return string */ public static function calculateDistance($thisLongitude, $thisLatitude, $stayLongitude, $stayLatitude, $unit = 1, $decimals = 0) { // 原始坐标纬度弧度 deg2rad()函数将角度转换为弧度 $oriLatRad = deg2rad($thisLatitude); // 新坐标纬度弧度 $newLatRad = deg2rad($stayLatitude); // 坐标纬度弧度差 $diffLatRad = deg2rad($thisLatitude) - deg2rad($stayLatitude); // 经度弧度差 $diffLngRad = deg2rad($thisLongitude) - deg2rad($stayLongitude); // sin 求正弦值 参数单位为弧度 sin(2) => 0.90929742682568 // cos 求余弦值 参数单位为弧度 cos(0.2) => 0.98006657784124 // sqrt 求平方根 sqrt(2) => 1.4142135623731 // asin 求反正弦 参数单位为弧度 asin(2) => 1.4142135623731 // pow 求幂 pow(2, 2) => 4 $distance = 2 * asin(sqrt(pow(sin($diffLatRad / 2), 2) + cos($oriLatRad) * cos($newLatRad) * pow(sin($diffLngRad / 2), 2))) * 6378.137 * 1000; if ($unit == 2) { $distance = $distance / 1000; } return number_format($distance, $decimals); } /** * 导出csv数据 * @param $title 表名 * @param $cell 表头 * @param $data 数据 * @param null $closure */ public static function exportCsv($title, $cell, $data, $closure = null) { set_time_limit(0); ini_set('memory_limit', '1024M'); $output = fopen('php://output', 'w') or die("can't open php://output"); if (ob_get_contents()) { ob_clean(); } header("Content-Type: application/force-download"); header("Content-type: text/csv;charset=utf-8"); header("Content-Disposition: attachment; filename=" . $title . ".csv"); echo chr(0xEF) . chr(0xBB) . chr(0xBF); fputcsv($output, $cell); foreach ($data as $v) { if ($closure instanceof \Closure) { $v = $closure($v); } fputcsv($output, array_values($v)); } fclose($output) or die("can't close php://output"); exit; } }