= 224) { $stringTMP = mb_substr($string, $i, 3); $i += 3; } elseif (ord($stringTMP) >= 192) { $stringTMP = mb_substr($string, $i, 2); $i += 2; } else { ++$i; } $stringLast[] = $stringTMP; } $stringLast = implode('', $stringLast); if ($append) { $stringLast .= '...'; } return $stringLast; } /** * 自定义日志 * * @param $name * @param string $filename * @return \Illuminate\Log\Writer */ function myLog($name, $filename = '') { if (!$filename) { $filename = $name; } $filename = $filename . '.log'; $logger = new Logger($name); $writer = new \Illuminate\Log\Writer($logger); $writer->useDailyFiles(storage_path('logs/' . $filename)); return $writer; } /** * 业务调试日志 * * @return Logger */ function commonLog() { $name = 'common'; $filename = $name . '.log'; $logger = new Logger($name); $logger->pushHandler(new StreamHandler(storage_path('logs/' . $filename), 'debug')); return $logger; } /** * @param $name * @return Logger */ function dLog($name) { $filename = $name . '-' . date('Y-m-d') . '.log'; $logger = new Logger($name); $logger->pushHandler(new StreamHandler(storage_path('logs/' . $filename), 'debug')); return $logger; } /** * 获取对象或数组的属性值 * * @param $param * @param $key * @param string $default * @return mixed|string */ function getProp($param, $key, $default = '') { $result = $default; if (is_object($param) && isset($param->$key)) { $result = $param->$key; } if (is_array($param) && isset($param[$key])) { $result = $param[$key]; } return $result; } /** * @param $data * @param array $trans * @return array */ function assetData($data, $trans = []): array { $result = []; if (empty($data)) { return $result; } if (empty($trans)) { return $data; } foreach ($trans as $tran) { [$originKey, $newKey, $conv, $default] = [$tran['o'], $tran['n'], $tran['conv'], $tran['default']]; if (isset($data[$originKey])) { $result[$newKey] = $conv(getProp($data, $originKey, $default)); } } return $result; } /** * 随机数 * * @param int $num * @return string * @throws Exception */ function random($num = 16) { $bytes = random_bytes($num); return bin2hex($bytes); } /** * 生成订单 * * @param string $prefix 订单前缀 * @return string */ function generateOrderSn($prefix = '') { return $prefix . date('YmdHis') . getMillisecond() . rand(1000, 9999); } /** * 分页数据 * * @param $data * @return array */ function getMeta($data) { $currentPage = (int)$data->currentPage(); $lastPage = (int)$data->lastPage(); return [ 'current_page' => $currentPage, 'next_page' => $currentPage >= $lastPage ? $lastPage : ++$currentPage, 'last_page' => $lastPage, 'per_page' => (int)$data->perPage(), 'total' => (int)$data->total(), 'is_end' => !$data->hasMorePages(), 'next_page_url' => (string)$data->nextPageUrl(), 'prev_page_url' => (string)$data->previousPageUrl() ]; } /** * 钉钉通知异常 * * @param $message */ function sendNotice($message) { $webHook = env('DD_WEB_HOOK'); $data = [ 'msgtype' => 'text', 'text' => [ 'content' => $message ], 'at' => [ 'isAll' => true ] ]; // 异步发送 $client = new GuzzleHttp\Client(); $client->post($webHook, ['json' => $data]); } /** * 判断数据是合法的json数据 * * @param $string * @return bool */ function is_json($string) { json_decode($string); return (json_last_error() == JSON_ERROR_NONE); } /** * 获取ip地址 * * @return mixed|string */ function getIpAddr() { $ipaddress = ''; if (isset($_SERVER['HTTP_CLIENT_IP'])) $ipaddress = $_SERVER['HTTP_CLIENT_IP']; else if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR']; else if (isset($_SERVER['HTTP_X_FORWARDED'])) $ipaddress = $_SERVER['HTTP_X_FORWARDED']; else if (isset($_SERVER['HTTP_FORWARDED_FOR'])) $ipaddress = $_SERVER['HTTP_FORWARDED_FOR']; else if (isset($_SERVER['HTTP_FORWARDED'])) $ipaddress = $_SERVER['HTTP_FORWARDED']; else if (isset($_SERVER['REMOTE_ADDR'])) $ipaddress = $_SERVER['REMOTE_ADDR']; else $ipaddress = 'UNKNOWN'; return $ipaddress; } /** * @param int $num * @return bool|string * @throws Exception */ function randStr($num = 5) { $str = 'QWERTYUIOPASDFGHJKLZXCVBNM1234567890qwertyuiopasdfghjklzxcvbnm'; return substr(str_shuffle($str), random_int(0, strlen($str) - 11), $num); } /** * 上传文件 * * @param $file * @return string * @throws Exception */ function uploadFile($file) { // 阿里云主账号 $accessKeyId = env('OSS_ACCESS_ID'); $accessKeySecret = env('OSS_ACCESS_KEY'); $endpoint = env('OSS_END_POINT'); $bucket = env('OSS_BUCKET'); // 设置文件名称。 $object = 'channel/file/contract/' . randStr(10) . '.pdf'; try { $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint); $ossImgBackData = $ossClient->uploadFile($bucket, $object, $file); } catch (OssException $e) { printf($e->getMessage()); return ''; } $urlArr = parse_url($ossImgBackData['oss-request-url']); return getProp($urlArr, 'path'); } /** * 下载文件到本地 * * @param $object * @param $localFile * @return string */ function downloadFile($object, $localFile) { // 阿里云主账号 $accessKeyId = env('OSS_ACCESS_ID'); $accessKeySecret = env('OSS_ACCESS_KEY'); $endpoint = env('OSS_END_POINT'); $bucket = env('OSS_BUCKET'); try { $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint); $ossClient->getObject($bucket, $object, [ OssClient::OSS_FILE_DOWNLOAD => $localFile ]); } catch (OssException $e) { printf($e->getMessage()); return ''; } } /** * 上传封面 * * @param $file * @return string * @throws Exception */ function uploadCoverFile($file) { // 阿里云主账号 $accessKeyId = env('OSS_ACCESS_ID'); $accessKeySecret = env('OSS_ACCESS_KEY'); $endpoint = env('OSS_END_POINT'); $bucket = env('OSS_BUCKET'); // 设置文件名称。 $object = 'books/cover/' . randStr(10) . '.' . $file->getClientOriginalExtension(); try { $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint); $ossImgBackData = $ossClient->uploadFile($bucket, $object, $file->path()); } catch (OssException $e) { printf($e->getMessage()); return ''; } $urlArr = parse_url($ossImgBackData['oss-request-url']); return getProp($urlArr, 'path') ? 'http://' . $bucket . '.' . $endpoint . getProp($urlArr, 'path') : ''; } function uploadAgreementFile($file) { // 阿里云主账号 $accessKeyId = env('OSS_ACCESS_ID'); $accessKeySecret = env('OSS_ACCESS_KEY'); $endpoint = env('OSS_END_POINT'); $bucket = env('OSS_BUCKET'); $file_name = $file->getClientOriginalName(); $file_name = str_replace('.' . $file->getClientOriginalExtension(), '', $file_name); // 设置文件名称。 $object = 'books/contract/' . $file_name . '-' . date('YmdHi') . '.' . $file->getClientOriginalExtension(); try { $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint); $ossImgBackData = $ossClient->uploadFile($bucket, $object, $file); } catch (OssException $e) { printf($e->getMessage()); return ''; } $urlArr = parse_url($ossImgBackData['oss-request-url']); return getProp($urlArr, 'path') ? 'http://' . $bucket . '.' . $endpoint . urldecode(getProp($urlArr, 'path')) : ''; } /** * 上传wap推荐图片 * * @param $file * @param $filename * @return string * @throws Exception */ function uploadWapRecommendPic($file, $filename) { // 阿里云主账号 $accessKeyId = env('OSS_ACCESS_ID'); $accessKeySecret = env('OSS_ACCESS_KEY'); $endpoint = env('OSS_END_POINT'); $bucket = env('OSS_BUCKET_YCSD'); // 设置文件名称。 $object = 'ycsd_web_3nd/images/homebanners/' . $filename . '.' . $file->getClientOriginalExtension(); try { $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint); $options = array( OssClient::OSS_HEADERS => array( 'Content-Type' => 'image/jpeg', 'Content-Disposition' => 'inline' ), ); $ossImgBackData = $ossClient->uploadFile($bucket, $object, $file->path(), $options); } catch (OssException $e) { printf($e->getMessage()); return ''; } $urlArr = parse_url($ossImgBackData['oss-request-url']); return getProp($urlArr, 'path') ? 'http://' . $bucket . '.' . $endpoint . getProp($urlArr, 'path') : ''; } /** * @param $path * @return Generator */ function readFileContent($path) { if ($handle = fopen($path, 'r')) { while (!feof($handle)) { yield trim(fgets($handle)); } fclose($handle); } } function exportFileCsv(array $headers, array $data, string $filename) { header("Content-type:application/vnd.ms-excel"); header("Content-Disposition:attachment;filename=" . $filename . ".csv"); $headers = collect($headers)->map(function ($item) { return "\"" . mb_convert_encoding($item, "GBK", "UTF-8") . "\""; })->all(); echo implode(",", $headers); echo "\r\n"; foreach ($data as $item) { $rows = collect($item)->map(function ($row) { return "\"" . mb_convert_encoding(is_numeric($row) && strlen($row) > 12 ? "'" . $row : $row, "GBK", "UTF-8") . "\""; })->all(); echo implode(",", $rows); echo "\r\n"; } exit(); } //function exportFileCsv(array $header, array $data, string $filename) { // header('Content-Encoding: UTF-8'); // header("Content-type:application/vnd.ms-excel;charset=UTF-8"); // header('Content-Disposition: attachment;filename="' . $filename . '.csv"'); // // //打开php标准输出流 // $fp = fopen('php://output', 'a'); // // //添加BOM头,以UTF8编码导出CSV文件,如果文件头未添加BOM头,打开会出现乱码。 // fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF)); // //添加导出标题 // fputcsv($fp, $header); // // foreach ($data as $k => $item) { // fputcsv($fp, $item); // if ($k % 5000 == 0) { // //每1万条数据就刷新缓冲区 // ob_flush(); // flush(); // } // } // exit(); //} //function exportFileCsv(array $header, array $data, string $filename) { // // header('Content-Type: application/vnd.ms-excel'); // header('Content-Disposition: attachment;filename="'.$filename.'.csv"'); // header('Cache-Control: max-age=0'); // // //打开PHP文件句柄,php://output 表示直接输出到浏览器 // $fp = fopen('php://output', 'a'); // // //输出Excel列名信息 // foreach ($header as $key => $value) { // //CSV的Excel支持GBK编码,一定要转换,否则乱码 // $header[$key] = iconv('utf-8', 'gbk', $value); // } // // //将数据通过fputcsv写到文件句柄 // fputcsv($fp, $header); // // //计数器 // $num = 0; // // //每隔$limit行,刷新一下输出buffer,不要太大,也不要太小 // $limit = 10000; // // //逐行取出数据,不浪费内存 // $count = count($data); // for ($i = 0; $i < $count; $i++) { // // $num++; // // //刷新一下输出buffer,防止由于数据过多造成问题 // if ($limit == $num) { // ob_flush(); // flush(); // $num = 0; // } // // $row = $data[$i]; // foreach ($row as $key => $value) { // $row[$key] = iconv('utf-8', 'gbk', $value); // } // // fputcsv($fp, $row); // } // exit(); //} // 获取除空格外的字数 function getSize(string $content) { $content = preg_replace('/\s+/', '', $content); return mb_strlen($content, 'utf-8'); } // 获取word字符数(不计空格) function getChargeSize(string $content) { //判断是否存在替换字符 $is_replace_count = substr_count($content, "龘"); try { //先将回车换行符做特殊处理 $str = preg_replace('/(\r\n+|\s+| +)/', "龘", $content); //处理英文字符数字,连续字母、数字、英文符号视为一个单词 $str = preg_replace('/[a-z_A-Z0-9-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",\'<>~`\?:;|]/', "m", $str); //合并字符m,连续字母、数字、英文符号视为一个单词 $str = preg_replace('/m+/', "*", $str); //去掉回车换行符 $str = preg_replace('/龘+/', "", $str); //返回字数 return mb_strlen($str) + $is_replace_count; } catch (\Exception $e) { return 0; } } // 将阿拉伯数字转换成中文 function chineseNum($figure, $capital = false, $mode = true) { if ($figure == '0') return '零'; $numberChar = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']; $unitChar = ['', '十', '百', '千', '', '万', '亿', '兆', '京', '垓', '秭', '穣', '沟', '涧', '正', '载', '极', '恒河沙', '阿僧祇', '那由他', '不可思议', '无量大数']; if ($capital !== false) { $numberChar = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']; $unitChar = ['', '拾', '佰', '仟', '', '万', '亿', '兆', '京', '垓', '秭', '穣', '沟', '涧', '正', '载', '极', '恒河沙', '阿僧祇', '那由他', '不可思议', '无量大数']; } $dec = "点"; $target = ''; $matches = []; if ($mode) { preg_match("/^0*(\d*)\.?(\d*)/", $figure, $matches); } else { preg_match("/(\d*)\.?(\d*)/", $figure, $matches); } list(, $number, $point) = $matches; if ($point) { $target = $dec . chineseNum($point, $capital, false); } if (!$number) { return $target; } $str = strrev($number); for ($i = 0; $i < strlen($str); $i++) { $out[$i] = $numberChar[$str[$i]]; if ($mode === false) { continue; } $out[$i] .= $str[$i] != '0' ? $unitChar[$i % 4] : ''; if ($i > 0 && $str[$i] + $str[$i - 1] == 0) { $out[$i] = ''; } if ($i % 4 == 0) { $temp = substr($str, $i, 4); $out[$i] = str_replace($numberChar[0], '', $out[$i]); if (strrev($temp) > 0) { $out[$i] .= $unitChar[4 + floor($i / 4)]; } else { $out[$i] .= $numberChar[0]; } } } $result = join('', array_reverse($out)) . $target; return mb_substr($result, 0, 2) == '一十' ? mb_substr($result, 1) : $result; } function addPrefix($str) { if (!$str) return ''; if (mb_substr($str, 0, 4) == 'http') return $str; if (mb_substr($str, 0, 7) == '/books/') return 'http://zwcontent.oss-cn-hangzhou.aliyuncs.com' . $str; if (mb_substr($str, 0, 6) == '/card/') return 'http://zwcontent.oss-cn-hangzhou.aliyuncs.com' . $str; if (mb_substr($str, 0, 15) == 'uploader/idcard') return 'http://zwcontent.oss-cn-hangzhou.aliyuncs.com/' . $str; if (mb_substr($str, 0, 6) == '/cover') return 'https://cdn-newyc.ycsd.cn/ycsd_cover/covermiddle' . mb_substr($str, 6); if (mb_substr($str, 0, 8) == '/images/') return 'https://cdn-newyc.ycsd.cn/ycsd_cover' . $str; } /** * 章节内容排版 * * @param $content * @return string */ function filterContent($content) { if (!$content) return ''; $content = str_replace( ['  ', '

', '
', '
', ' ', '

', '

', '“', '”', '…', '‘', '’', '—'], [' ', PHP_EOL, PHP_EOL, PHP_EOL, ' ', '', PHP_EOL, '“', '”', '...', '‘', '’', '-'], $content); $content = preg_replace('/(\r\n)+/', PHP_EOL, $content); // 段落首字母前加两个中文空格 $string = explode(PHP_EOL, $content); foreach ($string as $line => $text) { $string[$line] = str_replace([' ', "\r\n", "\r", "\n", ' '], '', $string[$line]); if (!$string[$line]) { unset($string[$line]); } else { $string[$line] = $string[$line] . PHP_EOL; // if (mb_substr($string[$line], 0, 1) == ' ') { // $string[$line] = str_replace(' ', '', $string[$line]); // 去除多个空格 // $string[$line] = '  ' . $string[$line].PHP_EOL; // } // if (mb_substr($string[$line], 0, 2) != '  ') { // $string[$line] = '  ' . $string[$line].PHP_EOL; // } // if (mb_substr($string[$line], 0, 2) == '  ' && str_replace(' ', '', $string[$line])) { // $string[$line] .= PHP_EOL; // } } } $content = implode(PHP_EOL, $string); return $content; } /** * 书籍简介排版 * * @param $content * @return string */ function filterContent2($content) { if (!$content) return ''; $content = str_replace( ['  ', '

', '
', '
', ' ', '

', '

', '“', '”', '…', '‘', '’', '—'], [' ', PHP_EOL, PHP_EOL, PHP_EOL, ' ', '', PHP_EOL, '“', '”', '...', '‘', '’', '-'], $content); $content = preg_replace('/(\r\n)+/', PHP_EOL, $content); // 段落首字母前加两个中文空格 $string = explode(PHP_EOL, $content); $content = ''; foreach ($string as $line => $text) { $string[$line] = str_replace([' ', "\r\n", "\r", "\n", ' ', '
'], '', $string[$line]); if (!$string[$line]) { unset($string[$line]); } else { $string[$line] = '  ' . $string[$line] . '
'; $content .= $string[$line]; } } $content = trim($content, '
'); return $content; } /** * 书籍简介排版-抖音版 * * @param $content * @return string */ function filterIntro($content) { if (!$content) return ''; $content = str_replace( ['  ', '

', '
', '
', ' ', '

', '

', '“', '”', '…', '‘', '’', '—'], [' ', ' ', ' ', ' ', ' ', '', ' ', '“', '”', '...', '‘', '’', '-'], $content); $content = preg_replace('/(\r\n)+/', PHP_EOL, $content); // 段落首字母前加两个中文空格 $string = explode(PHP_EOL, $content); $content = ''; foreach ($string as $line => $text) { $string[$line] = str_replace([' ', "\r\n", "\r", "\n", ' ', '
'], '', $string[$line]); if (!$string[$line]) { unset($string[$line]); } else { $content .= $string[$line]; } } $content = trim($content, '
'); return $content; } function sensitiveStr($list, $string) { $count = 0; //违规词的个数 $sensitiveWord = ''; //违规词 $stringAfter = $string; //替换后的内容 $total = count($list); $size = 500; $last = ceil($total / $size); $patternList = []; for ($page = 1; $page <= $last; $page++) { $arr = array_slice($list, $size * ($page - 1), $size); $filter = []; foreach ($arr as $v) { if (preg_match('/[^a-zA-Z0-9\|\p{Han}\·]/u', $v)) continue; $filter[] = $v; // $a = preg_replace('/[^a-zA-Z0-9\|\p{Han}]/u', '', $v); // if ($a) $filter[] = $a; } $pattern = "/" . implode("|", $filter) . "/i"; //定义正则表达式 if (preg_match_all($pattern, $string, $matches)) { //匹配到了结果 $patternList = array_merge($patternList, $matches[0]); //匹配到的数组 } } $sensitiveWord = ''; if ($patternList) { $count = count($patternList); // $sensitiveWord = implode(',', $patternList); //敏感词数组转字符串 $replaceArray = array_combine($patternList, array_fill(0, count($patternList), '*')); //把匹配到的数组进行合并,替换使用 $stringAfter = strtr($string, $replaceArray); //结果替换 // 将敏感词合并 $return_pattern = []; foreach ($patternList as $v) { if (!isset($return_pattern[$v])) { $return_pattern[$v] = [ 'word' => $v, 'count' => 1, ]; } else { $return_pattern[$v]['count'] += 1; } } foreach ($return_pattern as $v) { $sensitiveWord .= $v['word'] . ','; } } return [ 'count' => $count, 'sensitive_words' => trim($sensitiveWord, ','), 'content' => $stringAfter ]; } /** * 转换时间格式 * * @param $date * @param string $format * @return false|string */ function transDate($date, $format = 'Y-m-d H:i:s') { return strtotime($date) > 0 ? date($format, strtotime($date)) : ''; } /** * 根据网段获取计算所有IP * * @param string $segment 网段 '139.217.0.1/24' * @return array [网络地址:139.217.0.1 广播地址:139.217.0.255 IP列表: ['139.217.0.2','139.217.0.3'……'139.217.0.254']] */ function getIpBySegment($segment) { $segmentInfo = explode("/", $segment); $beginIpArray = explode(".", $segmentInfo[0]); $mask = intval($segmentInfo['1']); $endIp = array(); foreach ($beginIpArray as $ipKey => $item) { $beginFlag = 8 * ($ipKey); //0 8 16 24 $endFlag = 8 * ($ipKey + 1);//8 16 24 32 $decbinItem = str_pad(decbin($item), 8, "0", STR_PAD_LEFT); $endIp[] = $mask >= $endFlag ? $item : ($mask > $beginFlag ? bindec(str_pad(substr($decbinItem, 0, $mask - $beginFlag), 8, "1", STR_PAD_RIGHT)) : ($ipKey <= 2 ? pow(2, 8) - 1 : pow(2, 8) - 1)); } $ipArray = array(); for ($beginIp[0] = $beginIpArray[0]; $beginIp[0] <= $endIp[0]; $beginIp[0]++) { for ($beginIp[1] = $beginIpArray[1]; $beginIp[1] <= $endIp[1]; $beginIp[1]++) { for ($beginIp[2] = $beginIpArray[2]; $beginIp[2] <= $endIp[2]; $beginIp[2]++) { for ($beginIp[3] = $beginIpArray[3]; $beginIp[3] <= $endIp[3]; $beginIp[3]++) { $ipArray[] = implode(".", $beginIp); } } } } $network_ip_addr = $beginIpArray[0] . '.' . $beginIpArray[1] . '.' . $beginIpArray[2] . '.' . '0'; // 网络地址 $broadcast_ip_addr = end($ipArray); // 广播地址 if ($ipArray[0] == $network_ip_addr) { // 如果是网络地址则删掉 unset($ipArray[0]); } $last = count($ipArray); unset($ipArray[$last]); return [$network_ip_addr, $broadcast_ip_addr, $ipArray]; } /** * 在指定网段中分配子网段 * * @param string $segment 指定网段 * @param int $ipNum 需要的IP数 * @param array $usedIpArray 不可用(已经使用)的IP,默认为空数组 * @return bool|string 成功则返回分配的网段 */ function allocateSegment($segment, $ipNum, $usedIpArray = []) { $usedIpArray = empty($usedIpArray) ? [] : array_flip($usedIpArray); //计算需要多少个IP $i = 0; $ipCount = pow(2, $i); while ($ipCount < $ipNum) { $i++; $ipCount = pow(2, $i); } $newMask = 32 - $i; //大网段的开始和结束IP $segmentInfo = explode("/", $segment); //['139.217.0.1',24] $beginIpArray = explode(".", $segmentInfo[0]);//[139,217,0,1] $mask = intval($segmentInfo['1']); //24 if ($newMask < $mask) { return false; } $endIp = array(); $step = []; foreach ($beginIpArray as $ipKey => $item) { $beginFlag = 8 * ($ipKey); //0 8 16 24 $endFlag = 8 * ($ipKey + 1);//8 16 24 32 $step[$ipKey] = $newMask > $endFlag ? 1 : ($endFlag - $newMask < 8 ? pow(2, $endFlag - $newMask) : pow(2, 8)); $decbinItem = str_pad(decbin($item), 8, "0", STR_PAD_LEFT); $endIp[] = $mask >= $endFlag ? $item : ($mask > $beginFlag ? bindec(str_pad(substr($decbinItem, 0, $mask - $beginFlag), 8, "1", STR_PAD_RIGHT)) : ($ipKey <= 2 ? pow(2, 8) - 1 : pow(2, 8) - 1)); } //遍历生成网段 for ($beginIp[0] = $beginIpArray[0]; $beginIp[0] <= $endIp[0]; $beginIp[0] += $step[0]) { for ($beginIp[1] = $beginIpArray[1]; $beginIp[1] <= $endIp[1]; $beginIp[1] += $step[1]) { for ($beginIp[2] = $beginIpArray[2]; $beginIp[2] <= $endIp[2]; $beginIp[2] += $step[2]) { for ($beginIp[3] = $beginIpArray[3]; $beginIp[3] <= $endIp[3]; $beginIp[3] += $step[3]) { $newSegment = implode('.', $beginIp) . '/' . $newMask; //获取该网段所有的IP $ipArray = getIpBySegment($newSegment); $canUse = true; //判断该网段是否可用 if (!empty($usedIpArray)) { foreach ($ipArray as $ip) { if (isset($usedIpArray[$ip])) { $canUse = false; break; } } } if ($canUse) { return $newSegment; } } } } } return false; } function remove_xss($val) { // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed // this prevents some character re-spacing such as // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs $val = preg_replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '', $val); // straight replacements, the user should never need these since they're normal characters // this prevents like $search = 'abcdefghijklmnopqrstuvwxyz'; $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $search .= '1234567890!@#$%^&*()'; $search .= '~`";:?+/={}[]-_|\'\\'; for ($i = 0; $i < strlen($search); $i++) { // ;? matches the ;, which is optional // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars // @ @ search for the hex values $val = preg_replace('/(&#[xX]0{0,8}' . dechex(ord($search[$i])) . ';?)/i', $search[$i], $val); // with a ; // @ @ 0{0,7} matches '0' zero to seven times $val = preg_replace('/(�{0,8}' . ord($search[$i]) . ';?)/', $search[$i], $val); // with a ; } // now the only remaining whitespace attacks are \t, \n, and \r $ra1 = array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base'); $ra2 = array( 'onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload' ); $ra = array_merge($ra1, $ra2); $found = true; // keep replacing as long as the previous round replaced something while ($found == true) { $val_before = $val; for ($i = 0; $i < sizeof($ra); $i++) { $pattern = '/'; for ($j = 0; $j < strlen($ra[$i]); $j++) { if ($j > 0) { $pattern .= '('; $pattern .= '(&#[xX]0{0,8}([9ab]);)'; $pattern .= '|'; $pattern .= '|(�{0,8}([9|10|13]);)'; $pattern .= ')*'; } $pattern .= $ra[$i][$j]; } $pattern .= '/i'; $replacement = substr($ra[$i], 0, 2) . '' . substr($ra[$i], 2); // add in <> to nerf the tag $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags if ($val_before == $val) { // no replacements were made, so exit the loop $found = false; } } } return $val; } /** * 计算作者积分等级 * * @param $score */ function calcAuthorLevel($score): int { switch (true) { case $score <= 0: $level = 0; break; case $score <= 5000: $level = 1; break; case $score <= 50000: $level = 2; break; case $score <= 100000: $level = 3; break; case $score <= 300000: $level = 4; break; case $score <= 800000: $level = 5; break; case $score <= 1500000: $level = 6; break; case $score <= 2500000: $level = 7; break; case $score <= 5000000: $level = 8; break; case $score <= 10000000: $level = 9; break; default: $level = 10; break; } return $level; } /** * 运营数据(上传附件) * * @param $file * @return string * @throws Exception */ function uploadEnclosureFile($file) { // 阿里云主账号 $accessKeyId = env('OSS_ACCESS_ID'); $accessKeySecret = env('OSS_ACCESS_KEY'); $endpoint = env('OSS_END_POINT'); $bucket = env('OSS_BUCKET'); // 设置文件名称。 $object = 'books/enclosure/' . randStr(10) . '--' . $file->getClientOriginalName(); try { $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint); $ossImgBackData = $ossClient->uploadFile($bucket, $object, $file->path()); } catch (OssException $e) { printf($e->getMessage()); return ''; } $urlArr = parse_url($ossImgBackData['oss-request-url']); return getProp($urlArr, 'path') ? 'http://' . $bucket . '.' . $endpoint . getProp($urlArr, 'path') : ''; } // 获取当前域名是http还是https function getHttpType() { return ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://'; } // 根据id生成唯一邀请码 function enCodeId($user_id) { $key = 'XzeTdSPQc1uYHRBVWmUE6x94q25g3krfCGhb8FjtDZvMNKJpnayw7s'; $num = strlen($key); $code = ''; // 邀请码 while ($user_id > 0) { // 转进制 $mod = $user_id % $num; // 求模 $user_id = ($user_id - $mod) / $num; $code = $key[$mod] . $code; } $code = str_pad($code, 6, 'A', STR_PAD_LEFT); // 不足用0补充 return $code; } // 根据邀请码解密为id function deCodeId($code) { $key = 'XzeTdSPQc1uYHRBVWmUE6x94q25g3krfCGhb8FjtDZvMNKJpnayw7s'; $num = strlen($key); if (strrpos($code, '0') !== false) $code = substr($code, strrpos($code, '0') + 1); $len = strlen($code); $code = strrev($code); $user_id = 0; for ($i = 0; $i < $len; $i++) { $user_id += strpos($key, $code[$i]) * pow($num, $i); } return $user_id; } /** * 将二维数组按其中的某个数组排序(此方法适用于将数据库数据按数组取出后自动按ID排序的情况 ps:即未按该数组排序) * * @param array $array 二维数组 * @param array $sort 排序数组 * @param string $field 排序字段(二维数组和排序数组相同的字段) * @return array */ function sortByArray(array $array, array $sort, string $field): array { $data = []; if (is_array($array) && is_array($sort)) { foreach ($sort as $v) { foreach ($array as $key => $val) { if ($v == $val[$field]) { array_push($data, $array[$key]); } } } } return $data; } /** * 将二维数组按其中的字段排序(正序或倒序) * * @param array $array 二维数组 * @param string $field 排序字段 * @param mixed $type 排序方式(3倒序,4正序) * @return array|mixed */ function sortByField(array $array, string $field, $type): array { if (is_array($array)) { array_multisort(array_column($array, $field), $type, $array); } return $array; } // 生成用户邀请码 function setUserInviteCode($id) { return \Vinkla\Hashids\Facades\Hashids::connection('invite')->encode($id); } // 解密用户邀请码 function decodeUserInviteCode($code) { return \Vinkla\Hashids\Facades\Hashids::connection('invite')->decode($code); } function getMillisecond() { list($microsecond, $time) = explode(' ', microtime()); return (float)sprintf('%.0f', (floatval($microsecond) + floatval($time)) * 1000); } function get_client_ip($type = 0, $adv = false) { $type = $type ? 1 : 0; static $ip = null; if (null !== $ip) { return $ip[$type]; } if ($adv) { if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); $pos = array_search('unknown', $arr); if (false !== $pos) { unset($arr[$pos]); } $ip = trim($arr[0]); } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) { $ip = $_SERVER['HTTP_CLIENT_IP']; } elseif (isset($_SERVER['REMOTE_ADDR'])) { $ip = $_SERVER['REMOTE_ADDR']; } } elseif (isset($_SERVER['REMOTE_ADDR'])) { $ip = $_SERVER['REMOTE_ADDR']; } // IP地址合法验证 $long = sprintf("%u", ip2long($ip)); $ip = $long ? array($ip, $long) : array('0.0.0.0', 0); return $ip[$type]; } /** * 获取真实IP */ function _getIp() { if (getenv('HTTP_X_FORWARDED_FOR')) { $ip = getenv('HTTP_X_FORWARDED_FOR'); } else if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")) $ip = getenv("HTTP_CLIENT_IP"); else if (getenv("HTTP_X_FORWARD_FOR") && strcasecmp(getenv("HTTP_X_FORWARD_FOR"), "unknown")) $ip = getenv("HTTP_X_FORWARD_FOR"); else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown")) $ip = getenv("REMOTE_ADDR"); else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown")) $ip = $_SERVER['REMOTE_ADDR']; else $ip = "unknown"; return ($ip); } /** * 数组 转 对象 * * @param array $arr 数组 * @return object */ function array_to_object($arr) { if (gettype($arr) != 'array') { return; } foreach ($arr as $k => $v) { if (gettype($v) == 'array' || getType($v) == 'object') { $arr[$k] = (object)array_to_object($v); } } return (object)$arr; } /** * 对象 转 数组 * * @param object $obj 对象 * @return array */ function object_to_array($obj) { $obj = (array)$obj; foreach ($obj as $k => $v) { if (gettype($v) == 'resource') { return; } if (gettype($v) == 'object' || gettype($v) == 'array') { $obj[$k] = (array)object_to_array($v); } } return $obj; } /** * 检查是否为手机号码 */ function _isPhone($number) { return preg_match("/^1[34578][0-9]{9}$/", $number); } /** * 判断所传的参数是否缺少,如果缺少返回渠道的字段,正确返回0 * * @param array $param * @param array $must * @return int|mixed */ function checkParam(array $param, array $must) { foreach ($must as $item) { if (array_key_exists($item, $param) && $param[$item] != '') { } else { return $item; } } return 0; } /** * 对象 转 数组 * * @param object $obj 对象 * @return array */ function ignoreKeyInArray($targetArray, $delete_keys = [], $changes = []) { $change_keys = array_keys($changes); foreach ($targetArray as $key => $value) { if (in_array($key, $delete_keys) && isset($targetArray[$key])) unset($targetArray[$key]); if (in_array($key, $change_keys) && isset($targetArray[$key])) $targetArray[$key] = $changes[$key]; if (is_array($value)) ignoreKeyInArray($value, $delete_keys, $change_keys); } return $targetArray; } function itemTransform($trans, $data) { if ($data) { return $trans->transform($data); } else { return []; } } function collectionTransform($trans, $data) { $ret_data = []; if ($data) { foreach ($data as $item) { $ret_data[] = $trans->transform($item); } } return $ret_data; } function paginationTransform($trans, $paginator) { $ret = []; $ret['list'] = []; if ($paginator) { foreach ($paginator as $item) { $ret['list'][] = $trans->transform($item); } $ret['meta'] = [ 'total' => (int)$paginator->total(), 'per_page' => (int)$paginator->perPage(), 'current_page' => (int)$paginator->currentPage(), 'last_page' => (int)$paginator->lastPage(), 'next_page_url' => (string)$paginator->nextPageUrl(), 'prev_page_url' => (string)$paginator->previousPageUrl() ]; } return $ret; } /** * 加密site id */ function encodeDistributionChannelId($id) { $encrypt_pool = [ ]; if (isset($encrypt_pool[$id])) { return $encrypt_pool[$id]; } $hashids = new \Hashids\Hashids('', 16, 'abcdefghjklmnopqrstuvwxyz1234567890'); return $hashids->encode($id); } /** * 解密密site id */ function decodeDistributionChannelId($code) { $encrypt_pool = [ ]; if (isset($encrypt_pool[$code])) { return $encrypt_pool[$code]; } $hashids = new \Hashids\Hashids('', 16, 'abcdefghjklmnopqrstuvwxyz1234567890'); $res = $hashids->decode($code); if ($res && isset($res[0])) { return $res[0]; } return null; } //bid加密 function book_hash_encode($bid) { return Vinkla\Hashids\Facades\Hashids::encode($bid); } function decodeBid($encode_bid) { $bid = 0; try { $bid_arr = \Hashids::decode($encode_bid); if (isset($bid_arr[0])) { $bid = $bid_arr[0]; } } catch (\Exception $e) { return null; } return $bid; } /** * 获取当前域名 */ function _domain() { return str_replace('https://', '', str_replace('http://', '', url('/'))); } /** * 字符串转* * * @param $str // 待转的字符串 * @param $start // 转*起始位置 * @param int $end // 转*结束位置 * @param string $dot // 转换的字符(必须是单字符,默认是*) * @param string $charset // 编码方式 * @param string $end_char // 特殊字符(碰到此字符则确定end位置) * @return string */ function trans_pass($str, $start, $end = 0, $dot = "*", $charset = "UTF-8", $end_char = '@'): string { $len = mb_strlen($str, $charset); if ($start == 0 || $start > $len) { $start = 1; } if ($end != 0 && $end > $len) { $end = $len - 2; } if (strstr($str, $end_char)) { $end = $len - strrpos($str, $end_char); } $endStart = $len - $end; $top = mb_substr($str, 0, $start, $charset); $bottom = ""; if ($endStart > 0) { $bottom = mb_substr($str, $endStart, $end, $charset); } $len -= mb_strlen($top, $charset); $len -= mb_strlen($bottom, $charset); $newStr = $top; for ($i = 0; $i < $len; $i++) { $newStr .= $dot; } $newStr .= $bottom; return $newStr; } /** * 格式化章节内容 * * @param $content * @return false|string */ function formatContent($content) { if (!$content) return ''; $content = str_replace( ['  ', '

', '
', '
', ' ', '

', '

', '“', '”', '…'], [' ', PHP_EOL, PHP_EOL, PHP_EOL, ' ', '', PHP_EOL, '“', '”', '...'], $content); $content = str_replace([" ", '“', '…', '”', '

'], '', $content); // 段落首字母前加两个中文空格 $string = explode(PHP_EOL, $content); foreach ($string as $line => $text) { if (mb_substr($text, 0, 2) != '  ') $string[$line] = '  ' . $text; } $content = implode(PHP_EOL, $string); $content = mb_convert_encoding($content, 'UTF-8', 'UTF-8,GBK,GB2312'); $content = iconv('UTF-8', 'UTF-8//IGNORE', $content); return $content; } /** * 筛选出有效的id集合 * * @param array $ids * @return array */ function filterValidIds(array $ids): array { // 传参 if (empty($ids)) { return []; } $result = []; foreach ($ids as $id) { if (in_array($id, $result) || !is_numeric($id) || (int)$id < 1) { continue; } $result[] = (int)$id; } return $result; } function arrayToStr($map) { $isMap = isArrMap($map); $result = ""; if ($isMap) { $result = "map["; } $keyArr = array_keys($map); if ($isMap) { sort($keyArr); } $paramsArr = array(); foreach ($keyArr as $k) { $v = $map[$k]; if ($isMap) { if (is_array($v)) { $paramsArr[] = sprintf("%s:%s", $k, arrayToStr($v)); } else { $paramsArr[] = sprintf("%s:%s", $k, trim(strval($v))); } } else { if (is_array($v)) { $paramsArr[] = arrayToStr($v); } else { $paramsArr[] = trim(strval($v)); } } } $result = sprintf("%s%s", $result, join(" ", $paramsArr)); if (!$isMap) { $result = sprintf("[%s]", $result); } else { $result = sprintf("%s]", $result); } return $result; } function isArrMap($map) { foreach ($map as $k => $v) { if (is_string($k)) { return true; } } return false; } /** * 随机字符串 * * @param $length * @return string */ function makeRandStr($length): string { // 密码字符集,可任意添加你需要的字符 $str = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ]; // 在 $str 中随机取 $length 个数组元素键名 $keys = array_rand($str, $length); $password = ''; for ($i = 0; $i < $length; $i++) { // 将 $length 个数组元素连接成字符串 $password .= $str[$keys[$i]]; } return $password; } /** * 导出数据为excel表格 * * @param $data 一个二维数组,结构如同从数据库查出来的数组 * @param $title excel的第一行标题,一个数组,如果为空则没有标题 * @param $filename 下载的文件名 * @examlpe10 */ function exportExcel($data = [], $title = [], $filename = 'report') { ob_end_clean(); ob_start(); header("Content-type:application/octet-stream"); header("Accept-Ranges:bytes"); header("Content-type:application/vnd.ms-excel"); header("Content-Disposition:attachment;filename=" . $filename . ".xls"); header("Pragma: no-cache"); header("Expires: 0"); //导出xls 开始 if (!empty($title)) { foreach ($title as $k => $v) { $title[$k] = iconv("UTF-8", "GB2312", $v); } $title = implode("\t", $title); echo "$title\n"; } if (!empty($data)) { foreach ($data as $key => $val) { foreach ($val as $ck => $cv) { $data[$key][$ck] = iconv("UTF-8", "GB2312", $cv); } $data[$key] = implode("\t", $data[$key]); } echo implode("\n", $data); } } /** * 导出csv文件 * @param string $name * @param array $headers * @param array $data * @return void */ function exportCsv(string $name, array $headers, array $data = []) { header('Content-Description: File Transfer'); header('Content-Type: application/csv'); header("Content-Disposition: attachment; filename=".$name.".csv"); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); $handle = fopen('php://output', 'w'); ob_clean(); fputcsv($handle, $headers); if ($data) { foreach ($data as $row) { fputcsv($handle, $row); } } ob_flush(); fclose($handle); die(); }