helpers.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. <?php
  2. /*
  3. * This file is part of the Jiannei/lumen-api-starter.
  4. *
  5. * (c) Jiannei <longjian.huang@foxmail.com>
  6. *
  7. * This source file is subject to the MIT license that is bundled
  8. * with this source code in the file LICENSE.
  9. */
  10. use App\Repositories\Enums\ResponseCodeEnum;
  11. use Illuminate\Support\Arr;
  12. use Illuminate\Support\Facades\Log;
  13. /**
  14. * @param $str
  15. * @param $glue
  16. * @return array
  17. */
  18. function str2arr($str, $glue = ',')
  19. {
  20. return array_filter(array_unique(explode($glue, $str)));
  21. }
  22. function arr2str($arr, $glue = ',')
  23. {
  24. return implode($glue, array_unique(Arr::wrap($arr)));
  25. }
  26. function str2arr0($str, $glue = ',')
  27. {
  28. return explode($glue, $str);
  29. }
  30. function arr2str0($arr, $glue = ',')
  31. {
  32. return implode($glue, (Arr::wrap($arr)));
  33. }
  34. function php2js($arr)
  35. {
  36. return json_encode($arr, true);
  37. }
  38. function php2jszh($arr)
  39. {
  40. return json_encode($arr, JSON_UNESCAPED_UNICODE);
  41. }
  42. function js2php($json)
  43. {
  44. return json_decode($json, true);
  45. }
  46. /**
  47. * 取数组的值
  48. * @param $key
  49. * @param $arr
  50. * @param string $default
  51. * @return mixed|string
  52. * Author: Mead
  53. */
  54. function get_arr_val($key, $arr = [], $default = '')
  55. {
  56. if (array_key_exists($key, $arr) && $arr[$key] != null) {
  57. return $arr[$key];
  58. }
  59. return $default;
  60. }
  61. /**
  62. * 路径转地址
  63. * @param $path
  64. * @param string $disk
  65. * @return mixed
  66. * Author: Mead
  67. */
  68. function path_to_url($path, $disk = 'public')
  69. {
  70. if (empty($path)) return null;
  71. // 如果 image 字段本身就已经是完整的 url 就直接返回
  72. if (\Illuminate\Support\Str::startsWith($path, ['http://', 'https://'])) {
  73. return $path;
  74. }
  75. return \Illuminate\Support\Facades\Storage::disk($disk)->url($path);
  76. }
  77. function is_user_login()
  78. {
  79. return auth('api')->check();
  80. }
  81. function login_user()
  82. {
  83. return auth('api')->user();
  84. }
  85. function login_admin()
  86. {
  87. return auth('admins')->user();
  88. }
  89. function login_user_id()
  90. {
  91. return auth('api')->id();
  92. }
  93. function login_admin_id()
  94. {
  95. return auth('admins')->id();
  96. }
  97. function is_admin_login()
  98. {
  99. return auth('admins')->check();
  100. }
  101. /**
  102. * 数组转树状
  103. * @param array $data
  104. * @param string $primary
  105. * @param string $parent
  106. * @param string $children
  107. * @return array
  108. * Author: Mead
  109. */
  110. function toTree($data = [], $primary = 'id', $parent = 'parent_id', $children = 'children')
  111. {
  112. if (!isset($data[0][$parent])) {
  113. return [];
  114. }
  115. $items = array();
  116. // $pids = [];
  117. foreach ($data as $v) {
  118. $items[$v[$primary]] = $v;
  119. // $pids[] = $v[$parent];
  120. }
  121. $tree = array();
  122. foreach ($items as &$item) {
  123. // if (in_array($item['id'], $pids)) {
  124. // $item['is_base'] = false;
  125. // } else {
  126. // $item['is_base'] = true;
  127. // }
  128. if (isset($items[$item[$parent]])) {
  129. $items[$item[$parent]][$children][] = &$items[$item[$primary]];
  130. } else {
  131. $tree[] = &$items[$item[$primary]];
  132. }
  133. }
  134. return $tree;
  135. }
  136. /**
  137. * 二维数组根据某个字段排序
  138. * @param array $array 要排序的数组
  139. * @param string $keys 要排序的键字段
  140. * @param string $sort 排序类型 SORT_ASC SORT_DESC
  141. * @return array 排序后的数组
  142. */
  143. function arraySort($array, $keys, $sort = SORT_DESC)
  144. {
  145. $keysValue = [];
  146. foreach ($array as $k => $v) {
  147. $keysValue[$k] = $v[$keys];
  148. }
  149. array_multisort($keysValue, $sort, $array);
  150. return $array;
  151. }
  152. function match_chinese($chars, $encoding = 'utf8')
  153. {
  154. $pattern = ($encoding == 'utf8') ? '/[\x{4e00}-\x{9fa5}a-zA-Z0-9_.]/u' : '/[\x80-\xFF]/';
  155. preg_match_all($pattern, $chars, $result);
  156. $temp = join('', $result[0]);
  157. return $temp;
  158. }
  159. function arr_str($arr)
  160. {
  161. return '-' . arr2str($arr, '-') . '-';
  162. }
  163. function str_arr($str)
  164. {
  165. return str2arr(trim($str, '-'), '-');
  166. }
  167. function wechat_fee($money)
  168. {
  169. $m = (int)($money * 100);
  170. if (login_admin_id() > 3) {
  171. if ($money <= 0) {
  172. return 1;
  173. }
  174. }
  175. return $m;
  176. }
  177. function arr2type($arr)
  178. {
  179. return '-' . arr2str($arr, '-') . '-';
  180. }
  181. function type2arr($str)
  182. {
  183. return str2arr(trim($str, '-'), '-');
  184. }
  185. function T($key)
  186. {
  187. if (\Illuminate\Support\Facades\App::getLocale() == 'zh_CN') {
  188. return __("messages.{$key}");
  189. } else {
  190. return __($key);
  191. }
  192. }
  193. if (!function_exists('config_path')) {
  194. /**
  195. * Get the configuration path.
  196. *
  197. * @param string $path
  198. * @return string
  199. */
  200. function config_path($path = '')
  201. {
  202. return app()->basePath() . '/config' . ($path ? '/' . $path : $path);
  203. }
  204. }
  205. /**
  206. * 秒数转时间
  207. * @param $sec
  208. * @return string
  209. * Author: Mead
  210. */
  211. function sec2time($sec)
  212. {
  213. $mes = '';
  214. if ($sec >= 3600) {
  215. $hours = str_pad(floor($sec / 3600), 2, "0", STR_PAD_LEFT);
  216. $sec = ($sec % 3600);
  217. $mes .= "{$hours}:";
  218. }
  219. if ($sec >= 60) {
  220. $minutes = str_pad(floor($sec / 60), 2, "0", STR_PAD_LEFT);;
  221. $sec = ($sec % 60);
  222. $mes .= "{$minutes}:";
  223. } else {
  224. $mes .= "00:";
  225. }
  226. $seconds = str_pad(floor($sec), 2, "0", STR_PAD_LEFT);;
  227. $mes .= "{$seconds}";
  228. return $mes;
  229. }
  230. /**
  231. * 字符为空
  232. * @return string
  233. * Author: Mead
  234. */
  235. function str_is_null()
  236. {
  237. return '--';
  238. }
  239. /**
  240. * 检查密码
  241. * @param $password
  242. * @return bool|string
  243. * Author: Mead
  244. */
  245. function check_password($password)
  246. {
  247. $score = 0;
  248. $str = $password;
  249. $num = 0;
  250. if (preg_match("/[0-9]+/", $str)) {
  251. $score++;
  252. $num++;
  253. }
  254. if (preg_match("/[0-9]{3,}/", $str)) {
  255. $score++;
  256. }
  257. if (preg_match("/[a-z]+/", $str)) {
  258. $score++;
  259. $num++;
  260. }
  261. if (preg_match("/[a-z]{3,}/", $str)) {
  262. $score++;
  263. }
  264. if (preg_match("/[A-Z]+/", $str)) {
  265. $score++;
  266. $num++;
  267. }
  268. if (preg_match("/[A-Z]{3,}/", $str)) {
  269. $score++;
  270. }
  271. if (preg_match("/[_|\-|+|=|*|!|@|#|$|%|.|^|&|(|)]+/", $str)) {
  272. $score += 2;
  273. $num++;
  274. }
  275. if (preg_match("/[_|\-|+|=|*|!|@|#|$|%|.|^|&|(|)]{3,}/", $str)) {
  276. $score++;
  277. }
  278. if (strlen($str) >= 10) {
  279. $score++;
  280. }
  281. $msg = false;
  282. if ($score < 4) {
  283. return false;
  284. // $msg = '密码太简单!';
  285. }
  286. if ($num < 2) {
  287. return false;
  288. // $msg = '密码必须包含数字、字母、符号两种类型!';
  289. }
  290. return true;
  291. }
  292. /**
  293. * 获取登录ip
  294. * @return array|false|mixed|string
  295. * Author: Mead
  296. */
  297. function getClientIp()
  298. {
  299. if (getenv('HTTP_CLIENT_IP')) {
  300. $ip = getenv('HTTP_CLIENT_IP');
  301. }
  302. if (getenv('HTTP_X_REAL_IP')) {
  303. $ip = getenv('HTTP_X_REAL_IP');
  304. } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
  305. $ip = getenv('HTTP_X_FORWARDED_FOR');
  306. $ips = explode(',', $ip);
  307. $ip = $ips[0];
  308. } elseif (getenv('REMOTE_ADDR')) {
  309. $ip = getenv('REMOTE_ADDR');
  310. } else {
  311. $ip = '0.0.0.0';
  312. }
  313. return $ip;
  314. }
  315. /**
  316. * 获取控制器的方法
  317. * @return array
  318. */
  319. function getControllerAndFunction()
  320. {
  321. $routeInfo = app('request')->route()[1]['uses'];
  322. list($class, $method) = explode('@', $routeInfo);
  323. $class = substr(strrchr($class, '\\'), 1);
  324. return ['controller' => $class, 'method' => $method];
  325. }
  326. /**
  327. * 二维数组去重
  328. * @param $arr
  329. * @param $key
  330. * @return array
  331. */
  332. function array_unset_tt($arr = [], $key = null)
  333. {
  334. //建立一个目标数组
  335. $res = array();
  336. foreach ($arr as $value) {
  337. //查看有没有重复项
  338. if (isset($res[$value[$key]])) {
  339. unset($value[$key]);
  340. } else {
  341. $res[$value[$key]] = $value;
  342. }
  343. }
  344. return array_values($res);
  345. }
  346. /**
  347. * 获取权限key
  348. * @return string
  349. */
  350. function getPermissionKey()
  351. {
  352. $request = request();
  353. $method = $request->method();
  354. $path = str_replace('/', ':', trim($request->path(), '/'));
  355. $key = "{$method}|{$path}";
  356. return $key;
  357. }
  358. /**
  359. * 获取配置参数
  360. * @param $code
  361. * @return string|mixed
  362. */
  363. function byCodeGetSetting($code)
  364. {
  365. return \App\Repositories\Models\Base\Setting::byCodeGetSetting($code);
  366. }
  367. /**
  368. *$ip string 必传
  369. *获取ip归属地
  370. *demo 四川省成都市 电信
  371. */
  372. function get_ip_city($ip)
  373. {
  374. $ch = curl_init();
  375. $url = 'https://whois.pconline.com.cn/ipJson.jsp?ip=' . $ip;
  376. //用curl发送接收数据
  377. curl_setopt($ch, CURLOPT_URL, $url);
  378. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  379. //请求为https
  380. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  381. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  382. $location = curl_exec($ch);
  383. curl_close($ch);
  384. //转码
  385. $location = mb_convert_encoding($location, 'utf-8', 'GB2312');
  386. //var_dump($location);
  387. //截取{}中的字符串
  388. $location = substr($location, strlen('({') + strpos($location, '({'), (strlen($location) - strpos($location, '})')) * (-1));
  389. //将截取的字符串$location中的‘,’替换成‘&’ 将字符串中的‘:‘替换成‘=’
  390. $location = str_replace('"', "", str_replace(":", "=", str_replace(",", "&", $location)));
  391. //php内置函数,将处理成类似于url参数的格式的字符串 转换成数组
  392. parse_str($location, $ip_location);
  393. if (isset($ip_location['addr'])) return $ip_location['addr'];
  394. return '';
  395. }
  396. /**
  397. * 异常处理
  398. * @param Exception $exception
  399. * @param $msg
  400. * @return void
  401. */
  402. function exception(\Exception $exception, $msg = '操作失败')
  403. {
  404. Log::error($exception);
  405. if (config('app.env') == 'production') abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, $msg);
  406. abort(ResponseCodeEnum::SERVICE_OPERATION_ERROR, $exception->getMessage());
  407. }
  408. /**
  409. * 解析身份证号
  410. * @param $card_id
  411. * @return array
  412. */
  413. function parse_card_id($card_id)
  414. {
  415. $sex_val = (int)substr($card_id, 16, 1);
  416. $sex = $sex_val % 2 === 0 ? 2 : 1;
  417. $bir = substr($card_id, 6, 8);
  418. $year = (int)substr($bir, 0, 4);
  419. $month = (int)substr($bir, 4, 2);
  420. $day = (int)substr($bir, 6, 2);
  421. $birthday = $year . "-" . $month . "-" . $day;
  422. $area_key = substr($card_id, 0, 6);
  423. // $address = \App\Repositories\Models\Base\Area::byCodeGetAreas($area_key);
  424. $age = \Illuminate\Support\Carbon::parse($birthday)->diffInYears();
  425. return [
  426. 'sex' => $sex,
  427. 'age' => $age,
  428. 'birthday' => $birthday,
  429. 'address' => [
  430. 'province' => substr($area_key, 0, 2) . '0000',
  431. 'city' => substr($area_key, 0, 4) . '00',
  432. 'area' => $area_key,
  433. ],
  434. ];
  435. }
  436. /**
  437. * 科学计数转数值
  438. * @param $number
  439. * @return array|mixed|string|string[]|null
  440. */
  441. function scientific_number_to_normal($number)
  442. {
  443. if (stripos($number, 'e') === false) {
  444. //判断是否为科学计数法
  445. return $number;
  446. }
  447. if (!preg_match(
  448. "/^([\\d.]+)[eE]([\\d\\-\\+]+)$/",
  449. str_replace(array(" ", ","), "", trim($number)), $matches)
  450. ) {
  451. //提取科学计数法中有效的数据,无法处理则直接返回
  452. return $number;
  453. }
  454. //对数字前后的0和点进行处理,防止数据干扰,实际上正确的科学计数法没有这个问题
  455. $data = preg_replace(array("/^[0]+/"), "", rtrim($matches[1], "0."));
  456. $length = (int)$matches[2];
  457. if ($data[0] == ".") {
  458. //由于最前面的0可能被替换掉了,这里是小数要将0补齐
  459. $data = "0{$data}";
  460. }
  461. //这里有一种特殊可能,无需处理
  462. if ($length == 0) {
  463. return $data;
  464. }
  465. //记住当前小数点的位置,用于判断左右移动
  466. $dot_position = strpos($data, ".");
  467. if ($dot_position === false) {
  468. $dot_position = strlen($data);
  469. }
  470. //正式数据处理中,是不需要点号的,最后输出时会添加上去
  471. $data = str_replace(".", "", $data);
  472. if ($length > 0) {
  473. //如果科学计数长度大于0
  474. //获取要添加0的个数,并在数据后面补充
  475. $repeat_length = $length - (strlen($data) - $dot_position);
  476. if ($repeat_length > 0) {
  477. $data .= str_repeat('0', $repeat_length);
  478. }
  479. //小数点向后移n位
  480. $dot_position += $length;
  481. $data = ltrim(substr($data, 0, $dot_position), "0") . "." . substr($data, $dot_position);
  482. } elseif ($length < 0) {
  483. //当前是一个负数
  484. //获取要重复的0的个数
  485. $repeat_length = abs($length) - $dot_position;
  486. if ($repeat_length > 0) {
  487. //这里的值可能是小于0的数,由于小数点过长
  488. $data = str_repeat('0', $repeat_length) . $data;
  489. }
  490. $dot_position += $length;//此处length为负数,直接操作
  491. if ($dot_position < 1) {
  492. //补充数据处理,如果当前位置小于0则表示无需处理,直接补小数点即可
  493. $data = ".{$data}";
  494. } else {
  495. $data = substr($data, 0, $dot_position) . "." . substr($data, $dot_position);
  496. }
  497. }
  498. if ($data[0] == ".") {
  499. //数据补0
  500. $data = "0{$data}";
  501. }
  502. return trim($data, ".");
  503. }
  504. /**
  505. * 获取设备类型
  506. * @return array|string|null
  507. */
  508. function device_type()
  509. {
  510. return strtolower(request()->header('device', 'pc'));
  511. }
  512. /**
  513. * 是否为手机端
  514. * @return bool
  515. */
  516. function is_mobile()
  517. {
  518. $type = request()->header('device', 'pc');
  519. return in_array($type, ['h5', 'weapp']);
  520. }
  521. /**
  522. * 是否为PC端
  523. * @return bool
  524. */
  525. function is_pc()
  526. {
  527. $type = request()->header('device', 'pc');
  528. return ($type === 'pc');
  529. }
  530. /**
  531. * 获取微信小程序配置
  532. *
  533. * @param array|string|null $key
  534. * @param mixed $default
  535. * @return \Illuminate\Http\Request|string|array
  536. */
  537. function wechat_mini_config($type)
  538. {
  539. $miniConfig = \App\Repositories\Models\Base\Setting::typeToWxappConfig($type);
  540. $config = [
  541. 'app_id' => $miniConfig['app_id'],
  542. 'secret' => $miniConfig['app_secret'],
  543. // 下面为可选项
  544. // 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
  545. 'response_type' => 'array',
  546. 'log' => [
  547. 'level' => 'debug',
  548. 'file' => base_path('storage/logs') . '/' . $type . '/wechat-' . date('Y-m-d') . '.log',
  549. ],
  550. ];
  551. return $config;
  552. }
  553. /**
  554. * 去除符号
  555. * @param $body
  556. * @return array|string|string[]|null
  557. */
  558. function remove_symbol($body)
  559. {
  560. $char = "。、!?:;﹑•"…‘’“”〝〞∕¦‖— 〈〉﹞﹝「」‹›〖〗】【»«』『〕〔》《﹐¸﹕︰﹔!¡?¿﹖﹌﹏﹋'´ˊˋ―﹫︳︴¯_ ̄﹢﹦﹤‐­˜﹟﹩﹠﹪﹡﹨﹍﹉﹎﹊ˇ︵︶︷︸︹︿﹀︺︽︾ˉ﹁﹂﹃﹄︻︼(), ,";
  561. $pattern = array(
  562. "/[[:punct:]]/i", //英文标点符号
  563. '/[' . $char . ']/u', //中文标点符号
  564. '/[ ]{2,}/'
  565. );
  566. $text = preg_replace($pattern, ' ', $body);
  567. return $text;
  568. }
  569. function word_arr2str($arr)
  570. {
  571. $str = [];
  572. foreach ($arr as $a) {
  573. $str[] = "{$a['name']}({$a['nums']})";
  574. }
  575. return arr2str($str, ',');
  576. }
  577. function post_url($url, $data)
  578. {
  579. $data = json_encode($data);
  580. $headerArray = array("Content-type:application/json;charset='utf-8'", "Accept:application/json");
  581. $curl = curl_init();
  582. curl_setopt($curl, CURLOPT_URL, $url);
  583. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
  584. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
  585. curl_setopt($curl, CURLOPT_POST, 1);
  586. curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
  587. curl_setopt($curl, CURLOPT_HTTPHEADER, $headerArray);
  588. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  589. $output = curl_exec($curl);
  590. curl_close($curl);
  591. return json_decode($output,true);
  592. }
  593. function log_record($name, $data)
  594. {
  595. \Illuminate\Support\Facades\Log::error("==============>{$name}<==============");
  596. \Illuminate\Support\Facades\Log::error($data);
  597. \Illuminate\Support\Facades\Log::error("<==============完结==============>");
  598. }