common.func.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. <?php
  2. /**
  3. * 通用函数库
  4. * @auth nj911<nj-x@gmail.com>
  5. * @date: 2021-04-18 12:27
  6. */
  7. use Hashids\Hashids;
  8. /**
  9. * 获取分页start offset
  10. * @param $amount
  11. * @param int $page
  12. * @param int $page_size
  13. * @return int|mixed
  14. */
  15. function get_page_start($amount, $page = 1, $page_size = 20) : int
  16. {
  17. if (empty($amount)) {
  18. return $page_size;
  19. }
  20. $page_size = empty($page_size) ? 20 : $page_size;
  21. $page_most = ceil($amount / $page_size);
  22. if (isset($page)) {
  23. $page = intval($page);
  24. if ($page > $page_most) {
  25. $page = $page_most;
  26. }
  27. } else {
  28. $page = 1;
  29. }
  30. $page = max(1, $page); //找出最大值
  31. $start_limit = ($page - 1) * $page_size;
  32. return $start_limit;
  33. }
  34. /**
  35. * 随机生成指定长度字符串
  36. * @param int $len 长度
  37. * @return string
  38. */
  39. function rand_letter($len = 18) : string
  40. {
  41. $str = '';
  42. if ($len <= 0) {
  43. $len = 18;
  44. }
  45. $chars = "abcdefhjmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWYXZ";
  46. $clen = strlen($chars);
  47. $max = $clen - 1;
  48. for ($i = 0; $i < $len; $i++) {
  49. $str .= $chars[mt_rand(0, $max)];
  50. }
  51. return $str;
  52. }
  53. /**
  54. * 随机生成指定长度字符串
  55. * @param int $len 长度
  56. * @return string
  57. */
  58. function rand_str($len = 18)
  59. {
  60. $str = '';
  61. if ($len <= 0) {
  62. $len = 18;
  63. }
  64. $chars = "abcdefhjmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWYXZ";
  65. $clen = strlen($chars);
  66. $max = $clen - 1;
  67. for ($i = 0; $i < $len; $i++) {
  68. $str .= $chars[mt_rand(0, $max)];
  69. }
  70. return $str;
  71. }
  72. /**
  73. * 随机生成字符串
  74. * @param int $length 长度
  75. * @param int $numeric 纯数字
  76. * @return string
  77. */
  78. function random($length, $numeric = 0) : string
  79. {
  80. if (version_compare(PHP_VERSION, '4.2.0', '<')) {
  81. mt_srand((double)microtime() * 1000000);
  82. } else {
  83. mt_srand();
  84. }
  85. $seed = base_convert(md5(print_r($_SERVER, 1) . microtime()), 16, $numeric ? 10 : 35);
  86. $seed = $numeric ? (str_replace('0', '', $seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed));
  87. $hash = '';
  88. $max = strlen($seed) - 1;
  89. for ($i = 0; $i < $length; $i++) {
  90. $hash .= $seed[mt_rand(0, $max)];
  91. }
  92. return $hash;
  93. }
  94. /**
  95. * json响应成功
  96. * @param mixed $data 数据
  97. * @param string $message 消息
  98. * @return mixed
  99. */
  100. function json_success($data, $message = '操作成功')
  101. {
  102. $handshake = '';
  103. $data = [
  104. 'code' => 200,
  105. 'message' => $message,
  106. 'data' => $data,
  107. 'handshake' => $handshake,
  108. ];
  109. return response()->json($data);
  110. }
  111. /**
  112. * json响应失败
  113. * @param string $message 消息
  114. * @param int $code 代码
  115. * @return \Illuminate\Http\JsonResponse
  116. */
  117. function json_fail($message, $code = 500, $data = [])
  118. {
  119. $handshake = '';
  120. $data = [
  121. 'code' => $code,
  122. 'message' => $message,
  123. 'data' => $data,
  124. 'handshake' => $handshake,
  125. ];
  126. return response()->json($data);
  127. }
  128. /**
  129. * 字符串截取函数(按字个数)
  130. * @param string $string 需要截断的字符串
  131. * @param int $length 允许字符串显示的最大长度(按字个数)
  132. * @param string $dot 超出的部分所用替代标识符
  133. * @return string
  134. */
  135. function cutstr($string, $length, $dot = '') : string
  136. {
  137. if (function_exists('mb_strcut')) {
  138. if (mb_strlen($string) > $length) {
  139. return mb_substr($string, 0, $length - mb_strlen($dot)) . $dot;
  140. } else {
  141. return $string;
  142. }
  143. } else {
  144. return cut_no_mbstring($string, $length, $dot);
  145. }
  146. }
  147. /**
  148. * 没有mbstring库字符串截取指定长度
  149. * @param string $string 字符串
  150. * @param int $length 截取长度
  151. * @param string $dot 结尾的字符点点
  152. * @param string $charset 编码
  153. * @return string
  154. */
  155. function cut_no_mbstring($string, $length, $dot = '', $charset = 'utf-8')
  156. {
  157. if (strlen($string) <= $length) {
  158. return $string;
  159. }
  160. $strcut = '';
  161. if (strtolower($charset) == 'utf-8') {
  162. $n = $tn = $noc = 0;
  163. while ($n < strlen($string)) {
  164. $t = ord($string[$n]);
  165. if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
  166. $tn = 1;
  167. $n++;
  168. $noc++;
  169. } elseif (194 <= $t && $t <= 223) {
  170. $tn = 2;
  171. $n += 2;
  172. $noc += 2;
  173. } elseif (224 <= $t && $t < 239) {
  174. $tn = 3;
  175. $n += 3;
  176. $noc += 2;
  177. } elseif (240 <= $t && $t <= 247) {
  178. $tn = 4;
  179. $n += 4;
  180. $noc += 2;
  181. } elseif (248 <= $t && $t <= 251) {
  182. $tn = 5;
  183. $n += 5;
  184. $noc += 2;
  185. } elseif ($t == 252 || $t == 253) {
  186. $tn = 6;
  187. $n += 6;
  188. $noc += 2;
  189. } else {
  190. $n++;
  191. }
  192. if ($noc >= $length) {
  193. break;
  194. }
  195. }
  196. if ($noc > $length) {
  197. $n -= $tn;
  198. }
  199. $strcut = substr($string, 0, $n);
  200. } else {
  201. for ($i = 0; $i < $length - strlen($dot) - 1; $i++) {
  202. $strcut .= ord($string[$i]) > 127 ? $string[$i] . $string[++$i] : $string[$i];
  203. }
  204. }
  205. return $strcut . $dot;
  206. }
  207. /**
  208. * 获取IP信息
  209. * @return array
  210. */
  211. function client_ip_info()
  212. {
  213. $ip = request()->getClientIp();
  214. $arr_ipa = \Zhuzhichao\IpLocationZh\Ip::find($ip);
  215. array_pop($arr_ipa); //剔除最后一个下标, 国标
  216. $arr_ipa = array_filter($arr_ipa);
  217. $ip_address = !empty($arr_ipa) ? implode('|', $arr_ipa) : '';
  218. return [
  219. $ip,
  220. $ip_address,
  221. ];
  222. }
  223. /**
  224. * 格式化页码入参
  225. * @param $page
  226. * @return int
  227. */
  228. function format_page($page)
  229. {
  230. $page = intval($page);
  231. if ($page <= 0) {
  232. $page = 1;
  233. }
  234. if ($page > PHP_INT_MAX) {
  235. $page = PHP_INT_MAX;
  236. }
  237. return $page;
  238. }
  239. /**
  240. * 密码星号加密
  241. * @param string $str 输入的字符串
  242. * @return string
  243. */
  244. function pass_encode($str)
  245. {
  246. $len = strlen($str);
  247. if ($len < 1) {
  248. return '';
  249. }
  250. $new = '';
  251. for ($i = 0; $i < $len; $i++) {
  252. $new .= ($i == 0 || $i == $len - 1) ? $str[$i] : '*';
  253. }
  254. return $new;
  255. }
  256. /**
  257. * 密码星号解密
  258. * @param string $new 明文密码
  259. * @param string $old 原始密码
  260. * @return mixed
  261. */
  262. function pass_decode($new, $old)
  263. {
  264. return $new == pass_encode($old) ? $old : $new;
  265. }
  266. /**
  267. * 加密手机号
  268. * @param $mobile
  269. * @return string
  270. */
  271. function encode_mobile($mobile)
  272. {
  273. $str = '';
  274. if ($mobile) {
  275. $len = strlen($mobile);
  276. for ($i = 0; $i < $len; $i++) {
  277. $str .= ($i < 5 || $i > $len - 4) ? $mobile[$i] : '*';
  278. }
  279. }
  280. return $str;
  281. }
  282. /**
  283. * 更新OpCache
  284. * 生成缓存php文件的地方都需要调用此函数
  285. * @return void
  286. */
  287. function opcache_update()
  288. {
  289. if (function_exists('opcache_reset')) {
  290. opcache_reset();
  291. }
  292. }
  293. /**
  294. * 获取相对依赖双斜杠开头的URL地址
  295. * @param $url
  296. * @return mixed
  297. */
  298. function get_slashes_url($url)
  299. {
  300. if (preg_match('/^(http|https)\:\/\/(.*?)$/i', $url, $arr_matches)) {
  301. return '//' . $arr_matches[2];
  302. } else {
  303. return $url;
  304. }
  305. }
  306. /**
  307. * AES 加密
  308. * @param mixed $content 明文
  309. * @param string $key 密钥
  310. * @param string $iv 向量,必须为数字
  311. * @param string $cipher 算法.
  312. * @param int $option 标记的按位或: OPENSSL_RAW_DATA=1 、 OPENSSL_ZERO_PADDING=2.
  313. * @return string
  314. */
  315. function aes_encrypt($content, $key, $iv = '', $cipher = 'AES-256-CBC', $option = 1)
  316. {
  317. $ivLength = openssl_cipher_iv_length($cipher); // 向量长度.
  318. /*$iv = openssl_random_pseudo_bytes($ivLength); // 根据长度生成向量.*/
  319. //$option = OPENSSL_RAW_DATA; // 标记的按位或: OPENSSL_RAW_DATA=1 、 OPENSSL_ZERO_PADDING=2.
  320. $tag = null; // 使用 AEAD 密码模式(GCM 或 CCM)时传引用的验证标签.
  321. $aad = ''; // 附加的验证数据.
  322. $tagLength = 16; // 验证 tag 的长度。GCM 模式时,它的范围是 4 到 16.
  323. $iv = (string)$iv;
  324. return @openssl_encrypt($content, $cipher, $key, $option, $iv);
  325. }
  326. /**
  327. * AES 解密
  328. * @param string $content base64密文
  329. * @param string $key 密钥
  330. * @param string $iv 向量,必须为数字
  331. * @param string $cipher 算法.
  332. * @param int $option 标记的按位或: OPENSSL_RAW_DATA=1 、 OPENSSL_ZERO_PADDING=2.
  333. * @return string
  334. */
  335. function aes_decrypt($content, $key, $iv = '', $cipher = 'AES-256-CBC', $option = 1)
  336. {
  337. $iv = (string)$iv;
  338. return @openssl_decrypt($content, $cipher, $key, $option, $iv);
  339. }
  340. /**
  341. * 加密ID.
  342. * @param $id
  343. * @param int $length 长度
  344. * @return string
  345. */
  346. function hashEncodeId($id, $length = 6)
  347. {
  348. $hashids = new Hashids(config('hashids.salt', ''), 6);
  349. return $hashids->encode($id);
  350. }
  351. /**
  352. * 解密ID.
  353. * @param $str
  354. * @return string
  355. */
  356. function hashDecodeId($str)
  357. {
  358. $hashids = new Hashids(config('hashids.salt', ''), 6);
  359. $arr = $hashids->decode($str);
  360. return implode('', $arr);
  361. }
  362. /**
  363. /**
  364. * 简单的转html代码
  365. * @param string $str 源字符串.
  366. * @return string
  367. */
  368. function code2html($str)
  369. {
  370. $str = str_replace("<", "&lt;", $str);
  371. $str = str_replace(">", "&gt;", $str);
  372. $str = str_replace(" ", "&nbsp;", $str);
  373. $str = str_replace("\r\n", "<br />", $str);
  374. $str = str_replace("\n", "<br />", $str);
  375. return $str;
  376. }
  377. /**
  378. * 获取最大上传数量
  379. * @param int $config_size 配置最大尺寸
  380. * @return array
  381. */
  382. function get_upload_sys_info($config_size = 0) {
  383. $get_upload_max_size_units = strtoupper(trim(ini_get("upload_max_filesize"))); //获取服务器支持最大上传文件大小 有单位
  384. $get_upload_max_size = substr($get_upload_max_size_units,0,strlen($get_upload_max_size_units)-1); //无单位
  385. $units = substr($get_upload_max_size_units,-1,1); //获取单位
  386. switch($units) { //单位换算
  387. case "G":
  388. $k_upload_max_size = $get_upload_max_size*1024*1024;
  389. break;
  390. case "M":
  391. $k_upload_max_size = $get_upload_max_size*1024;
  392. break;
  393. case "K":
  394. default:
  395. $k_upload_max_size = $get_upload_max_size;
  396. break;
  397. }
  398. $upload_max_size = $k_upload_max_size;
  399. if($config_size) {
  400. if($config_size < $k_upload_max_size) {
  401. $upload_max_size = $config_size;
  402. }
  403. }
  404. $arr = array(
  405. 'get_upload_max_size_units' => $get_upload_max_size_units, //系统有单位大小
  406. 'get_upload_max_size' => $get_upload_max_size, //系统无单位大小
  407. 'k_upload_max_size' => $k_upload_max_size, //单位为K的大小
  408. 'upload_max_size' => $upload_max_size //当前环境下大小单位K
  409. );
  410. return $arr;
  411. }
  412. /**
  413. * 获取文件的扩展名,不包含.
  414. * @param string $filename 文件名
  415. * @return string
  416. */
  417. function file_ext($filename) {
  418. return strtolower(trim(substr(strrchr($filename, '.'), 1)));
  419. }
  420. /**
  421. * 获取远程文件的header信息
  422. * @param string $url url地址
  423. * @param string $return_type
  424. * @return array|bool|string
  425. */
  426. function get_remote_file_info($url, $return_type = 'exists') {
  427. $head = @get_headers($url, true);
  428. $request_status = false;
  429. if(is_array($head)) {
  430. $t = explode(" ",$head[0]);
  431. if(strtoupper($t[count($t)-1]) == "OK") {
  432. $request_status = true;
  433. }
  434. }
  435. if ($request_status) {
  436. if ($return_type == 'exists') {
  437. return $request_status;
  438. } elseif ($return_type == 'size') {
  439. return trim($head['Content-Length']); //单位bytes 字节
  440. } elseif ($return_type == 'type') {
  441. return trim($head['Content-Type']);
  442. } else {
  443. return $head;
  444. }
  445. } else {
  446. return false;
  447. }
  448. }
  449. function get_url_by_name($file_name)
  450. {
  451. $url = $file_name;
  452. $name = basename($file_name);
  453. $serverNo = substr($name, 0, 3);
  454. $conf = config('image_servers');
  455. if (isset($conf['servers'][$serverNo]['base_url'])) {
  456. $url = rtrim($conf['servers'][$serverNo]['base_url'], '/') . $file_name;
  457. }
  458. return $url;
  459. }
  460. /**
  461. * 凯撒对称加密核心算法
  462. * @param string $str 字符串源
  463. * @param string $type 类型,encode=加密,decode=解密
  464. * @param string $scale 范围, c=中文, l=字母, n=数字,多种用半角逗号分隔开
  465. * @param int $offset 偏移
  466. * @return string
  467. */
  468. function caesar_cipher($str, $type = 'encode', $scale = 'c,l,n', $offset = 3)
  469. {
  470. if (empty($str)) {
  471. return '';
  472. }
  473. if (!$offset) {
  474. // 无偏移, 直接返回原来的字符串
  475. return $str;
  476. }
  477. if (empty($scale)) {
  478. $scale = 'c,l,n';
  479. }
  480. if ($type == 'decode') {
  481. // 解密反向偏移
  482. $offset = -$offset;
  483. }
  484. $func = function ($match, $offset, $start, $end) {
  485. $min = ord($start);
  486. $max = ord($end);
  487. $flag_old = ord($match);
  488. $flag = $flag_old + $offset;
  489. if ($offset > 0) {
  490. if ($flag > $max) {
  491. $flag -= ($max - $min) + 1;
  492. }
  493. } elseif ($offset < 0) {
  494. if ($flag < $min) {
  495. $flag += ($max - $min) + 1;
  496. }
  497. }
  498. return chr($flag);
  499. };
  500. $arr_scale = explode(',', $scale); //允许的范围转换成数组,方便判断
  501. $pattern = '/[\x{4e00}-\x{9fbb}a-zA-Z0-9]/u';
  502. $result = preg_replace_callback(
  503. $pattern,
  504. function ($matches) use ($offset, $arr_scale, $func) {
  505. $str = $match = $matches[0];
  506. if (preg_match('/[\x{4e00}-\x{9fbb}]/u', $match)) {
  507. // 汉字
  508. if (in_array('c', $arr_scale)) {
  509. $min = intval(hexdec(unpack("H6codes", "一")['codes']));
  510. $max = intval(hexdec(unpack("H6codes", "龻")['codes']));
  511. $arr_hex = unpack("H6codes", $match);
  512. $zi_hex = $arr_hex['codes'];
  513. $zi_dec = intval(hexdec($zi_hex));
  514. $flag = $zi_dec + $offset;
  515. if ($offset > 0) {
  516. if ($flag > $max) {
  517. $flag -= ($max - $min) + 1;
  518. }
  519. } elseif ($offset < 0) {
  520. if ($flag < $min) {
  521. $flag += ($max - $min) + 1;
  522. }
  523. }
  524. $str_hex = dechex($flag);
  525. $str = pack("H". strlen($str_hex), $str_hex);
  526. }
  527. } elseif (preg_match('/[0-9]/', $match)) {
  528. // 数字
  529. if (in_array('n', $arr_scale)) {
  530. $str = $func($match, $offset, '0', '9');
  531. }
  532. } elseif (preg_match('/[a-z]/', $match)) {
  533. // 小写字母
  534. if (in_array('l', $arr_scale)) {
  535. $str = $func($match, $offset, 'a', 'z');
  536. }
  537. } elseif (preg_match('/[A-Z]/', $match)) {
  538. // 大写字母
  539. if (in_array('l', $arr_scale)) {
  540. $str = $func($match, $offset, 'A', 'Z');
  541. }
  542. }
  543. return $str;
  544. },
  545. $str
  546. );
  547. return $result;
  548. }
  549. /**
  550. * 凯撒对称加密
  551. * @param string $str 字符串源
  552. * @param string $scale 范围, c=中文, l=字母, n=数字,多种用半角逗号分隔开
  553. * @param int $offset 偏移
  554. * @return string
  555. */
  556. function caesar_encode($str, $scale = 'c,l,n', $offset = 3)
  557. {
  558. return caesar_cipher($str, 'encode', $scale, $offset);
  559. }
  560. /**
  561. * 凯撒对称解密
  562. * @param string $str 字符串源
  563. * @param string $scale 范围, c=中文, l=字母, n=数字,多种用半角逗号分隔开
  564. * @param int $offset 偏移
  565. * @return string
  566. */
  567. function caesar_decode($str, $scale = 'c,l,n', $offset = 3)
  568. {
  569. return caesar_cipher($str, 'decode', $scale, $offset);
  570. }
  571. /**
  572. * 文件hash md5,大文件针对前10M数据.
  573. * @var $filePath string 文件路径
  574. * @var $maxSize int 部分hash的尺寸,单位字节
  575. * @return string
  576. */
  577. function hash_md5_file($filePath, $maxSize = 10485760) {
  578. $fileSize = filesize($filePath);
  579. $md5fileMaxSize = 60 * 1024 * 1024;
  580. if ($fileSize <= $md5fileMaxSize) {
  581. return md5_file($filePath);
  582. } else {
  583. $chunkSize = 65536;
  584. $size = $maxSize;
  585. $fp = fopen($filePath, 'r');
  586. $cxt = hash_init('md5'); // 初始化.
  587. while ($size > 0) {
  588. $buffer = fread($fp, min($size, $chunkSize));
  589. hash_update($cxt, $buffer);
  590. $size -= $chunkSize;
  591. }
  592. $hash = hash_final($cxt);
  593. fclose($fp); // 记得释放文件.
  594. return $hash;
  595. }
  596. }
  597. /**
  598. * 转换至mongoISODate格式.
  599. * @param mixed $date 任意有效的时间格式.
  600. * @param mixed $tz 时区
  601. * @return \MongoDB\BSON\UTCDateTime
  602. */
  603. function toMongoIsoDate($date, $tz = null)
  604. {
  605. if (empty($tz)) {
  606. $tz = env('APP_TIMEZONE', null);
  607. }
  608. $millSecond = \Carbon\Carbon::parse($date)->timestamp * 1000;
  609. $isoDateObj = new MongoDB\BSON\UTCDateTime($millSecond);
  610. $isoDate = $isoDateObj->toDateTime()->setTimezone(new DateTimeZone($tz));
  611. return $isoDateObj;
  612. }
  613. /**
  614. * 修正东8区时间
  615. *
  616. * @param $date
  617. * @return false|string
  618. */
  619. function timeCorrection($date)
  620. {
  621. return date("Y-m-d H:i:s", strtotime($date . ' -8 hour'));
  622. }
  623. /**
  624. * mongoIso时间转CarbonTime时间
  625. * @param \MongoDB\BSON\UTCDateTime $utcDate
  626. * @return \Carbon\Carbon
  627. */
  628. function mongoIsoDateToCarbonTime(\MongoDB\BSON\UTCDateTime $utcDate)
  629. {
  630. return \Carbon\Carbon::parse($utcDate->toDateTime()->setTimezone(new DateTimeZone(env('APP_TIMEZONE'))));
  631. }