= 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", ' ', '', '
', '“', '”', '…', '‘', '’', '—'], [' ', ' ', ' ', ' ', ' ', '', ' ', '“', '”', '...', '‘', '’', '-'], $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", ' ', '', '
', '“', '”', '…'], [' ', 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(); }