123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 |
- <?php
- namespace App\libs\helpers;
- use app\Auth;
- use App\libs\cache\redis\Redis;
- use Illuminate\Support\Facades\Config;
- use Illuminate\Support\Facades\DB;
- class Helper
- {
- /**
- * @desc 过滤emoji表情
- * @param $str
- * @return null|string|string[]
- */
- public static function filterEmoji($str)
- {
- return preg_replace_callback('/./u', function (array $match) {
- return strlen($match[0]) >= 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 = '<xml>';
- foreach ($data as $key => $val) {
- if (is_numeric($val)) {
- $xml .= '<' . $key . '>' . $val . '</' . $key . '>';
- } else {
- $xml .= '<' . $key . '><![CDATA[' . $val . ']]></' . $key . '>';
- }
- }
- $xml .= '</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;
- }
- }
|