common.php 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. <?php
  2. /**
  3. * Niushop商城系统 - 团队十年电商经验汇集巨献!
  4. * =========================================================
  5. * Copy right 2019-2029 山西牛酷信息科技有限公司, 保留所有权利。
  6. * ----------------------------------------------
  7. * 官方网址: https://www.niushop.com.cn
  8. * 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
  9. * 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
  10. * =========================================================
  11. */
  12. // 应用公共文件
  13. // 除了 E_NOTICE,报告其他所有错误
  14. //error_reporting(E_ALL ^ E_NOTICE);
  15. //error_reporting(E_ERROR | E_WARNING | E_PARSE);
  16. error_reporting(E_NOTICE);
  17. use extend\QRcode as QRcode;
  18. use think\facade\Session;
  19. use think\facade\Event;
  20. use app\model\system\Addon;
  21. /*****************************************************基础函数*********************************************************/
  22. /**
  23. * 把返回的数据集转换成Tree
  24. *
  25. * @param array $list
  26. * 要转换的数据集
  27. * @param string $pid
  28. * parent标记字段
  29. * @param string $level
  30. * level标记字段
  31. * @return array
  32. */
  33. function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = '_child', $root = 0)
  34. {
  35. // 创建Tree
  36. $tree = [];
  37. if (!is_array($list)) :
  38. return false;
  39. endif;
  40. // 创建基于主键的数组引用
  41. $refer = [];
  42. foreach ($list as $key => $data) {
  43. $refer[ $data[ $pk ] ] = &$list[ $key ];
  44. $refer[ $data[ $pk ] ][ $child ] = [];
  45. $refer[ $data[ $pk ] ]['child_num'] = 0;
  46. }
  47. foreach ($refer as $key => $data) {
  48. // 判断是否存在parent
  49. $parentId = $data[ $pid ];
  50. if ($root == $parentId) {
  51. $tree[ $key ] = &$refer[ $key ];
  52. } else if (isset($refer[ $parentId ])) {
  53. is_object($refer[ $parentId ]) && $refer[ $parentId ] = $refer[ $parentId ]->toArray();
  54. $parent = &$refer[ $parentId ];
  55. $parent[ $child ][ $key ] = &$refer[ $key ];
  56. $parent['child_num']++;
  57. }
  58. }
  59. return $tree;
  60. }
  61. /**
  62. * 将list_to_tree的树还原成列表
  63. *
  64. * @param array $tree
  65. * 原来的树
  66. * @param string $child
  67. * 孩子节点的键
  68. * @param string $order
  69. * 排序显示的键,一般是主键 升序排列
  70. * @param array $list
  71. * 过渡用的中间数组,
  72. * @return array 返回排过序的列表数组
  73. */
  74. function tree_to_list($tree, $child = '_child', $order = 'id', &$list = array())
  75. {
  76. if (is_array($tree)) {
  77. foreach ($tree as $key => $value) {
  78. $reffer = $value;
  79. if (isset($reffer[ $child ])) {
  80. unset($reffer[ $child ]);
  81. tree_to_list($value[ $child ], $child, $order, $list);
  82. }
  83. $list[] = $reffer;
  84. }
  85. $list = list_sort_by($list, $order, $sortby = 'asc');
  86. }
  87. return $list;
  88. }
  89. /**
  90. * 对查询结果集进行排序
  91. *
  92. * @access public
  93. * @param array $list
  94. * 查询结果
  95. * @param string $field
  96. * 排序的字段名
  97. * @param array $sortby
  98. * 排序类型
  99. * asc正向排序 desc逆向排序 nat自然排序
  100. * @return array
  101. */
  102. function list_sort_by($list, $field, $sortby = 'asc')
  103. {
  104. if (is_array($list)) {
  105. $refer = $resultSet = array();
  106. foreach ($list as $i => $data)
  107. $refer[ $i ] = &$data[ $field ];
  108. switch ($sortby) {
  109. case 'asc': // 正向排序
  110. asort($refer);
  111. break;
  112. case 'desc': // 逆向排序
  113. arsort($refer);
  114. break;
  115. case 'nat': // 自然排序
  116. natcasesort($refer);
  117. break;
  118. }
  119. foreach ($refer as $key => $val)
  120. $resultSet[] = &$list[ $key ];
  121. return $resultSet;
  122. }
  123. return false;
  124. }
  125. /**
  126. * 对象转化为数组
  127. * @param object $obj
  128. */
  129. function object_to_array($obj)
  130. {
  131. if (is_object($obj)) {
  132. $obj = (array) $obj;
  133. }
  134. if (is_array($obj)) {
  135. foreach ($obj as $key => $value) {
  136. $obj[ $key ] = object_to_array($value);
  137. }
  138. }
  139. return $obj;
  140. }
  141. /**
  142. * 系统加密方法
  143. *
  144. * @param string $data
  145. * 要加密的字符串
  146. * @param string $key
  147. * 加密密钥
  148. * @param int $expire
  149. * 过期时间 单位 秒
  150. * @return string
  151. */
  152. function encrypt($data, $key = '', $expire = 0)
  153. {
  154. $key = md5(empty ($key) ? 'niucloud' : $key);
  155. $data = base64_encode($data);
  156. $x = 0;
  157. $len = strlen($data);
  158. $l = strlen($key);
  159. $char = '';
  160. for ($i = 0; $i < $len; $i++) {
  161. if ($x == $l)
  162. $x = 0;
  163. $char .= substr($key, $x, 1);
  164. $x++;
  165. }
  166. $str = sprintf('%010d', $expire ? $expire + time() : 0);
  167. for ($i = 0; $i < $len; $i++) {
  168. $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1))) % 256);
  169. }
  170. return str_replace(array(
  171. '+',
  172. '/',
  173. '='
  174. ), array(
  175. '-',
  176. '_',
  177. ''
  178. ), base64_encode($str));
  179. }
  180. /**
  181. * 系统解密方法
  182. *
  183. * @param string $data
  184. * 要解密的字符串 (必须是encrypt方法加密的字符串)
  185. * @param string $key
  186. * 加密密钥
  187. * @return string
  188. */
  189. function decrypt($data, $key = '')
  190. {
  191. $key = md5(empty ($key) ? 'niucloud' : $key);
  192. $data = str_replace(array(
  193. '-',
  194. '_'
  195. ), array(
  196. '+',
  197. '/'
  198. ), $data);
  199. $mod4 = strlen($data) % 4;
  200. if ($mod4) {
  201. $data .= substr('====', $mod4);
  202. }
  203. $data = base64_decode($data);
  204. $expire = substr($data, 0, 10);
  205. $data = substr($data, 10);
  206. if ($expire > 0 && $expire < time()) {
  207. return '';
  208. }
  209. $x = 0;
  210. $len = strlen($data);
  211. $l = strlen($key);
  212. $char = $str = '';
  213. for ($i = 0; $i < $len; $i++) {
  214. if ($x == $l)
  215. $x = 0;
  216. $char .= substr($key, $x, 1);
  217. $x++;
  218. }
  219. for ($i = 0; $i < $len; $i++) {
  220. if (ord(substr($data, $i, 1)) < ord(substr($char, $i, 1))) {
  221. $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
  222. } else {
  223. $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
  224. }
  225. }
  226. return base64_decode($str);
  227. }
  228. /**
  229. * 数据签名认证
  230. */
  231. function data_auth_sign($data)
  232. {
  233. // 数据类型检测
  234. if (!is_array($data)) {
  235. $data = (array) $data;
  236. }
  237. ksort($data); // 排序
  238. $code = http_build_query($data); // url编码并生成query字符串
  239. $sign = sha1($code); // 生成签名
  240. return $sign;
  241. }
  242. /**
  243. * 重写md5加密方式
  244. *
  245. * @param unknown $str
  246. * @return string
  247. */
  248. function data_md5($str)
  249. {
  250. return '' === $str ? '' : md5(md5($str) . 'NiuCloud');
  251. }
  252. /**
  253. * 时间戳转时间
  254. */
  255. function time_to_date($time_stamp, $format = 'Y-m-d H:i:s')
  256. {
  257. if ($time_stamp > 0) {
  258. $time = date($format, $time_stamp);
  259. } else {
  260. $time = "";
  261. }
  262. return $time;
  263. }
  264. /**
  265. * 时间转时间戳
  266. */
  267. function date_to_time($date)
  268. {
  269. $time_stamp = strtotime($date);
  270. return $time_stamp;
  271. }
  272. /**
  273. * 获取唯一随机字符串
  274. * 创建时间:2018年8月7日15:54:16
  275. */
  276. function unique_random($len = 10)
  277. {
  278. $str = 'qwertyuiopasdfghjklzxcvbnm';
  279. str_shuffle($str);
  280. $res = 'nc_' . substr(str_shuffle($str), 0, $len) . date('is');
  281. return $res;
  282. }
  283. /**
  284. * 生成随机数
  285. * @param int $length
  286. * @return string
  287. */
  288. function random_keys($length)
  289. {
  290. $pattern = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMNOPQRSTUVWXYZ';
  291. $key = '';
  292. for ($i = 0; $i < $length; $i++) {
  293. $key .= $pattern{mt_rand(0, 35)}; //生成php随机数
  294. }
  295. return $key;
  296. }
  297. /**
  298. * 发送HTTP请求方法,目前只支持CURL发送请求
  299. *
  300. * @param string $url
  301. * 请求URL
  302. * @param array $params
  303. * 请求参数
  304. * @param string $method
  305. * 请求方法GET/POST
  306. * @return array $data 响应数据
  307. */
  308. function http($url, $timeout = 30, $header = array())
  309. {
  310. if (!function_exists('curl_init')) {
  311. throw new Exception('server not install curl');
  312. }
  313. $ch = curl_init();
  314. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  315. curl_setopt($ch, CURLOPT_HEADER, true);
  316. curl_setopt($ch, CURLOPT_URL, $url);
  317. curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
  318. if (!empty($header)) {
  319. curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  320. }
  321. $data = curl_exec($ch);
  322. list ($header, $data) = explode("\r\n\r\n", $data);
  323. $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  324. if ($http_code == 301 || $http_code == 302) {
  325. $matches = array();
  326. preg_match('/Location:(.*?)\n/', $header, $matches);
  327. $url = trim(array_pop($matches));
  328. curl_setopt($ch, CURLOPT_URL, $url);
  329. curl_setopt($ch, CURLOPT_HEADER, false);
  330. $data = curl_exec($ch);
  331. }
  332. if ($data == false) {
  333. curl_close($ch);
  334. }
  335. @curl_close($ch);
  336. return $data;
  337. }
  338. /**
  339. * 替换数组元素
  340. * @param array $array 数组
  341. * @param array $replace 替换元素['key' => 'value', 'key' => 'value']
  342. */
  343. function replace_array_element($array, $replace)
  344. {
  345. foreach ($replace as $k => $v) {
  346. if ($v == "unset" || $v == "") {
  347. unset($array[ $k ]);
  348. } else {
  349. $array[ $k ] = $v;
  350. }
  351. }
  352. return $array;
  353. }
  354. /**
  355. * 过滤特殊符号
  356. * 创建时间:2018年1月30日15:39:32
  357. * @param unknown $string
  358. * @return mixed
  359. */
  360. function ihtmlspecialchars($string)
  361. {
  362. if (is_array($string)) {
  363. foreach ($string as $key => $val) {
  364. $string[ $key ] = ihtmlspecialchars($val);
  365. }
  366. } else {
  367. $string = preg_replace('/&amp;((#(d{3,5}|x[a-fa-f0-9]{4})|[a-za-z][a-z0-9]{2,5});)/', '&\1',
  368. str_replace(array( '&', '"', '<', '>' ), array( '&amp;', '&quot;', '&lt;', '&gt;' ), $string));
  369. }
  370. return $string;
  371. }
  372. /********************************************* 插件,站点相关函数 ************************************************************************************
  373. *
  374. * /**
  375. * 插件显示内容里生成访问插件的url
  376. *
  377. * @param string $url
  378. * url
  379. * @param array $param
  380. * 参数
  381. * 格式:addon_url('HelloWorld://sitehome/Game/index', [])
  382. */
  383. function addon_url($url, $param = array())
  384. {
  385. if (strpos($url, 'http://') === 0 || strpos($url, 'https://') === 0) {
  386. return $url;
  387. }
  388. $parse_url = parse_url($url);
  389. $addon = isset($parse_url['scheme']) ? $parse_url['scheme'] : '';
  390. $controller = isset($parse_url['host']) ? $parse_url['host'] : '';
  391. $action = trim($parse_url['path'], '/');
  392. /* 解析URL带的参数 */
  393. if (isset($parse_url['query'])) {
  394. parse_str($parse_url['query'], $query);
  395. $param = array_merge($query, $param);
  396. }
  397. $url = $addon . '/' . $controller . '/' . $action;
  398. if (empty($addon)) {
  399. $url = $controller . '/' . $action;
  400. if (empty($controller)) {
  401. $url = $action;
  402. }
  403. }
  404. return url($url, $param);
  405. }
  406. /**
  407. * Url生成(重写url函数)
  408. * @param string $url 路由地址
  409. */
  410. function url(string $url = '', $vars = [])
  411. {
  412. if (!empty($vars)) {
  413. if (is_array($vars)) {
  414. $vars = http_build_query($vars);
  415. }
  416. $tag = REWRITE_MODULE ? '?' : '&';
  417. $var_url = $tag . $vars;
  418. } else {
  419. $var_url = '';
  420. }
  421. $url = $url . '.html';
  422. return ROOT_URL . '/' . $url . $var_url;
  423. }
  424. /**
  425. * 解析url的插件,模块,控制器,方法
  426. * @param unknown $url
  427. */
  428. function url_action($url)
  429. {
  430. if (empty($url)) {
  431. return [
  432. 'addon' => '',
  433. 'model' => 'index',
  434. 'controller' => 'index',
  435. 'action' => 'index'
  436. ];
  437. }
  438. if (!strstr($url, '://')) {
  439. $url_array = explode('/', $url);
  440. return [
  441. 'addon' => '',
  442. 'model' => $url_array[0],
  443. 'controller' => $url_array[1],
  444. 'action' => $url_array[2]
  445. ];
  446. } else {
  447. $url_addon_array = explode('://', $url);
  448. $addon = $url_addon_array[0];
  449. $url_array = explode('/', $url_addon_array[1]);
  450. return [
  451. 'addon' => $addon,
  452. 'model' => $url_array[0],
  453. 'controller' => $url_array[1],
  454. 'action' => $url_array[2]
  455. ];
  456. }
  457. }
  458. /**
  459. * 检测插件是否存在
  460. * @param unknown $name
  461. * @return number
  462. */
  463. function addon_is_exit($name)
  464. {
  465. $addon_model = new Addon();
  466. $addon_data = $addon_model->getAddonList([], 'name');
  467. $addons = array_column($addon_data['data'], 'name');
  468. if(in_array($name, $addons))
  469. {
  470. return 1;
  471. }else{
  472. return 0;
  473. }
  474. }
  475. /***************************************************niucloud系统函数***************************************************/
  476. /**
  477. * 处理事件
  478. *
  479. * @param string $event
  480. * 钩子名称
  481. * @param mixed $args
  482. * 传入参数
  483. * @param bool $once
  484. * 只获取一个有效返回值
  485. * @return void
  486. */
  487. function event($event, $args = [], $once = false)
  488. {
  489. $res = Event::trigger($event, $args);
  490. if (is_array($res)) {
  491. $res = array_filter($res);
  492. sort($res);
  493. }
  494. //只返回一个结果集
  495. if ($once) {
  496. return isset($res[0]) ? $res[0] : '';
  497. }
  498. return $res;
  499. }
  500. /**
  501. * 错误返回值函数
  502. * @param int $code
  503. * @param string $message
  504. * @param string $data
  505. * @return array
  506. */
  507. function error($code = -1, $message = '', $data = '')
  508. {
  509. return [
  510. 'code' => $code,
  511. 'message' => $message,
  512. 'data' => $data
  513. ];
  514. }
  515. /**
  516. * 返回值函数
  517. * @param int $code
  518. * @param string $message
  519. * @param string $data
  520. * @return array
  521. */
  522. function success($code = 0, $message = '', $data = '')
  523. {
  524. return [
  525. 'code' => $code,
  526. 'message' => $message,
  527. 'data' => $data
  528. ];
  529. }
  530. /**
  531. * 实例化Model
  532. *
  533. * @param string $name
  534. * Model名称
  535. */
  536. function model($table = '')
  537. {
  538. return new \app\model\Model($table);
  539. }
  540. /**
  541. * 获取带有表前缀的表名
  542. * @param string $table
  543. */
  544. function table($table = '')
  545. {
  546. return config('database.connections.prefix') . $table;
  547. }
  548. /**
  549. * 获取图片的真实路径
  550. *
  551. * @param string $path 图片初始路径
  552. * @param string $type 类型 big、mid、small
  553. * @return string 图片的真实路径
  554. */
  555. function img($path, $type = '')
  556. {
  557. $start = strripos($path, '.');
  558. $type = $type ? '_' . $type : '';
  559. $first = explode("/", $path);
  560. $path = substr_replace($path, $type, $start, 0);
  561. if (stristr($path, "http://") === false && stristr($path, "https://") === false) {
  562. if (is_numeric($first[0])) {
  563. $true_path = __ROOT__ . '/upload/' . $path;
  564. } else {
  565. $true_path = __ROOT__ . '/' . $path;
  566. }
  567. } else {
  568. $true_path = $path;
  569. }
  570. return $true_path;
  571. }
  572. /**
  573. * 获取标准二维码格式
  574. *
  575. * @param string $url
  576. * @param string $path
  577. * @param string $ext
  578. */
  579. function qrcode($url, $path, $qrcode_name)
  580. {
  581. if (!is_dir($path)) {
  582. $mode = intval('0777', 8);
  583. mkdir($path, $mode, true);
  584. chmod($path, $mode);
  585. }
  586. $path = $path . '/' . $qrcode_name . '.png';
  587. if (file_exists($path)) {
  588. unlink($path);
  589. }
  590. QRcode::png($url, $path, '', 4, 1);
  591. return $path;
  592. }
  593. /**
  594. * 前端页面api请求(通过api接口实现)
  595. * @param string $method
  596. * @param array $params
  597. * @return mixed
  598. */
  599. function api($method, $params = [])
  600. {
  601. //本地访问
  602. $data = get_api_data($method, $params);
  603. return $data;
  604. }
  605. /**
  606. * 获取Api类
  607. *
  608. * @param string $method
  609. */
  610. function get_api_data($method, $params)
  611. {
  612. $method_array = explode('.', $method);
  613. if ($method_array[0] == 'System') {
  614. $class_name = 'app\\api\\controller\\' . $method_array[1];
  615. if (!class_exists($class_name)) {
  616. return error();
  617. }
  618. $api_model = new $class_name($params);
  619. } else {
  620. $class_name = "addon\\{$method_array[0]}\\api\\controller\\" . $method_array[1];
  621. if (!class_exists($class_name)) {
  622. return error();
  623. }
  624. $api_model = new $class_name($params);
  625. }
  626. $function = $method_array[2];
  627. $data = $api_model->$function($params);
  628. return $data;
  629. }
  630. /**
  631. * 根据年份计算生肖
  632. * @param unknown $year
  633. */
  634. function get_zodiac($year)
  635. {
  636. $animals = array(
  637. '鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪'
  638. );
  639. $key = ($year - 1900) % 12;
  640. return $animals[ $key ];
  641. }
  642. /**
  643. * 计算.星座
  644. * @param int $month 月份
  645. * @param int $day 日期
  646. * @return str
  647. */
  648. function get_constellation($month, $day)
  649. {
  650. $constellations = array(
  651. '水瓶座', '双鱼座', '白羊座', '金牛座', '双子座', '巨蟹座',
  652. '狮子座', '处女座', '天秤座', '天蝎座', '射手座', '摩羯座'
  653. );
  654. if ($day <= 22) {
  655. if (1 != $month) {
  656. $constellation = $constellations[ $month - 2 ];
  657. } else {
  658. $constellation = $constellations[11];
  659. }
  660. } else {
  661. $constellation = $constellations[ $month - 1 ];
  662. }
  663. return $constellation;
  664. }
  665. /**
  666. * 数组键名转化为数字
  667. * @param $data
  668. */
  669. function arr_key_to_int($data, $clild_name)
  670. {
  671. $temp_data = array_values($data);
  672. foreach ($temp_data as $k => $v) {
  673. if (!empty($v[ $clild_name ])) {
  674. $temp_data[ $k ][ $clild_name ] = arr_key_to_int($v[ $clild_name ], $clild_name);
  675. }
  676. }
  677. return $temp_data;
  678. }
  679. /**
  680. * 以天为单位 计算间隔内的日期数组
  681. * @param $start_time
  682. * @param $end_time
  683. * @return array
  684. */
  685. function period_group($start_time, $end_time, $format = 'Ymd')
  686. {
  687. $type_time = 3600 * 24;
  688. $data = [];
  689. for ($i = $start_time; $i <= $end_time; $i += $type_time) {
  690. $data[] = date($format, $i);
  691. }
  692. return $data;
  693. }
  694. /**
  695. * 数组删除另一个数组
  696. * @param $arr
  697. * @param $del_arr
  698. * @return mixed
  699. */
  700. function arr_del_arr($arr, $del_arr)
  701. {
  702. foreach ($arr as $k => $v) {
  703. if (in_array($v, $del_arr)) {
  704. unset($arr[ $k ]);
  705. }
  706. }
  707. sort($arr);
  708. return $arr;
  709. }
  710. /**
  711. * 检测登录(应用于h5网页检测登录)
  712. * @param unknown $url
  713. */
  714. function check_auth($url = '')
  715. {
  716. $access_token = Session::get("access_token_" . request()->siteid());
  717. if (empty($access_token)) {
  718. if (!empty($url)) {
  719. Session::set("redirect_login_url", $url);
  720. }
  721. //尚未登录(直接跳转)
  722. return error(url('wap/login/login'));
  723. }
  724. $member_info = cache("member_info_" . request()->siteid() . $access_token);
  725. if (empty($member_info)) {
  726. $member_info = api("System.Member.memberInfo", [ 'access_token' => $access_token ]);
  727. if ($member_info['code'] == 0) {
  728. $member_info = $member_info['data'];
  729. cache("member_info_" . request()->siteid() . $access_token, $member_info);
  730. }
  731. }
  732. $member_info['access_token'] = $access_token;
  733. return success($member_info);
  734. }
  735. /**
  736. * 分割sql语句
  737. * @param string $content sql内容
  738. * @param bool $string 如果为真,则只返回一条sql语句,默认以数组形式返回
  739. * @param array $replace 替换前缀,如:['my_' => 'me_'],表示将表前缀my_替换成me_
  740. * @return array|string 除去注释之后的sql语句数组或一条语句
  741. */
  742. function parse_sql($content = '', $string = false, $replace = [])
  743. {
  744. // 纯sql内容
  745. $pure_sql = [];
  746. // 被替换的前缀
  747. $from = '';
  748. // 要替换的前缀
  749. $to = '';
  750. // 替换表前缀
  751. if (!empty($replace)) {
  752. $to = current($replace);
  753. $from = current(array_flip($replace));
  754. }
  755. if ($content != '') {
  756. // 多行注释标记
  757. $comment = false;
  758. // 按行分割,兼容多个平台
  759. $content = str_replace([ "\r\n", "\r" ], "\n", $content);
  760. $content = explode("\n", trim($content));
  761. // 循环处理每一行
  762. foreach ($content as $key => $line) {
  763. // 跳过空行
  764. if ($line == '') {
  765. continue;
  766. }
  767. // 跳过以#或者--开头的单行注释
  768. if (preg_match("/^(#|--)/", $line)) {
  769. continue;
  770. }
  771. // 跳过以/**/包裹起来的单行注释
  772. if (preg_match("/^\/\*(.*?)\*\//", $line)) {
  773. continue;
  774. }
  775. // 多行注释开始
  776. if (substr($line, 0, 2) == '/*') {
  777. $comment = true;
  778. continue;
  779. }
  780. // 多行注释结束
  781. if (substr($line, -2) == '*/') {
  782. $comment = false;
  783. continue;
  784. }
  785. // 多行注释没有结束,继续跳过
  786. if ($comment) {
  787. continue;
  788. }
  789. // 替换表前缀
  790. if ($from != '') {
  791. $line = str_replace('`' . $from, '`' . $to, $line);
  792. }
  793. // sql语句
  794. $pure_sql[] = $line;
  795. }
  796. // 只返回一条语句
  797. if ($string) {
  798. return implode($pure_sql, "");
  799. }
  800. // 以数组形式返回sql语句
  801. $pure_sql = implode($pure_sql, "\n");
  802. $pure_sql = explode(";\n", $pure_sql);
  803. }
  804. return $pure_sql;
  805. }
  806. /**
  807. * 执行sql
  808. * @param unknown $sql_name
  809. */
  810. function execute_sql($sql_name)
  811. {
  812. $sql_string = file_get_contents($sql_name);
  813. $sql_string = str_replace("{{prefix}}", config("database.connections.mysql.prefix"), $sql_string);
  814. if ($sql_string) {
  815. $sql = explode(";\n", str_replace("\r", "\n", $sql_string));
  816. foreach ($sql as $value) {
  817. $value = trim($value);
  818. if (!empty($value)) {
  819. \think\facade\Db::execute($value);
  820. }
  821. }
  822. }
  823. }
  824. /**
  825. * 检测目录读写权限
  826. */
  827. function check_dir_iswritable($dir)
  828. {
  829. $testDir = $dir;
  830. sp_dir_create($testDir);
  831. if (sp_testwrite($testDir)) {
  832. return true;
  833. } else {
  834. return false;
  835. }
  836. }
  837. /**
  838. * 检查测试文件是否可写入
  839. */
  840. function sp_testwrite($d)
  841. {
  842. $tfile = "_test.txt";
  843. $fp = @fopen($d . "/" . $tfile, "w");
  844. if (!$fp) {
  845. return false;
  846. }
  847. fclose($fp);
  848. $rs = @unlink($d . "/" . $tfile);
  849. if ($rs) {
  850. return true;
  851. }
  852. return false;
  853. }
  854. /**
  855. * 检查文件是否创建
  856. */
  857. function sp_dir_create($path, $mode = 0777)
  858. {
  859. if (is_dir($path))
  860. return true;
  861. $ftp_enable = 0;
  862. $path = sp_dir_path($path);
  863. $temp = explode('/', $path);
  864. $cur_dir = '';
  865. $max = count($temp) - 1;
  866. for ($i = 0; $i < $max; $i++) {
  867. $cur_dir .= $temp[ $i ] . '/';
  868. if (@is_dir($cur_dir))
  869. continue;
  870. @mkdir($cur_dir, 0777, true);
  871. @chmod($cur_dir, 0777);
  872. }
  873. return is_dir($path);
  874. }
  875. /**
  876. * 判断目录是否为空
  877. * @param $dir
  878. * @return bool
  879. */
  880. function dir_is_empty($dir)
  881. {
  882. $handle = opendir($dir);
  883. while (false !== ($entry = readdir($handle))) {
  884. if ($entry != "." && $entry != "..") {
  885. return FALSE;
  886. }
  887. }
  888. return TRUE;
  889. }
  890. /**
  891. * 创建文件夹
  892. *
  893. * @param string $path 文件夹路径
  894. * @param int $mode 访问权限
  895. * @param bool $recursive 是否递归创建
  896. * @return bool
  897. */
  898. function dir_mkdir($path = '', $mode = 0777, $recursive = true)
  899. {
  900. clearstatcache();
  901. if (!is_dir($path)) {
  902. mkdir($path, $mode, $recursive);
  903. return chmod($path, $mode);
  904. }
  905. return true;
  906. }
  907. /**
  908. * 文件夹文件拷贝
  909. *
  910. * @param string $src 来源文件夹
  911. * @param string $dst 目的地文件夹
  912. * @return bool
  913. */
  914. function dir_copy($src = '', $dst = '')
  915. {
  916. if (empty($src) || empty($dst)) {
  917. return false;
  918. }
  919. $dir = opendir($src);
  920. dir_mkdir($dst);
  921. while (false !== ($file = readdir($dir))) {
  922. if (($file != '.') && ($file != '..')) {
  923. if (is_dir($src . '/' . $file)) {
  924. dir_copy($src . '/' . $file, $dst . '/' . $file);
  925. } else {
  926. copy($src . '/' . $file, $dst . '/' . $file);
  927. }
  928. }
  929. }
  930. closedir($dir);
  931. return true;
  932. }
  933. /**查询存在目录
  934. * @param $dir
  935. */
  936. function sp_exist_dir($dir)
  937. {
  938. $is_exist = false;
  939. $is_write = false;
  940. while (!$is_exist) {
  941. $dir = dirname($dir);
  942. if (is_dir($dir) || $dir == ".") {
  943. $is_exist = true;
  944. if (is_writeable($dir)) {
  945. $is_write = true;
  946. }
  947. }
  948. }
  949. return $is_write;
  950. }
  951. /**
  952. * 拼接字符串
  953. * @param $string
  954. * @param $delimiter 分割字符
  955. * @param $value
  956. */
  957. function string_split($string, $delimiter, $value)
  958. {
  959. return empty($string) ? $value : $string . $delimiter . $value;
  960. }
  961. /**
  962. * $str为要进行截取的字符串,$length为截取长度(汉字算一个字,字母算半个字
  963. * @param $str
  964. * @param $length
  965. * @return string
  966. */
  967. function str_sub($str, $length = 10)
  968. {
  969. return mb_substr($str, 0, $length, 'UTF-8') . "...";
  970. }
  971. /**
  972. * 删除缓存文件使用
  973. * @param $dir
  974. */
  975. function rmdirs($dir)
  976. {
  977. $dir = 'runtime/' . $dir;
  978. $dh = opendir($dir);
  979. while ($file = readdir($dh)) {
  980. if ($file != "." && $file != "..") {
  981. $fullpath = $dir . "/" . $file;
  982. if (is_dir($fullpath)) {
  983. rmdirs($fullpath);
  984. } else {
  985. unlink($fullpath);
  986. }
  987. }
  988. }
  989. closedir($dh);
  990. }
  991. /**
  992. * 以天为单位 计算间隔内的日期数组
  993. * @param $srart_time
  994. * @param $end_time
  995. * @return array
  996. */
  997. function periodGroup($srart_time, $end_time, $format = 'Ymd')
  998. {
  999. $type_time = 3600 * 24;
  1000. $data = [];
  1001. for ($i = $srart_time; $i <= $end_time; $i += $type_time) {
  1002. $data[] = date($format, $i);
  1003. }
  1004. return $data;
  1005. }
  1006. //解决个别中文乱码
  1007. function mbStrreplace($content, $to_encoding = "UTF-8", $from_encoding = "GBK")
  1008. {
  1009. $content = mb_convert_encoding($content, $to_encoding, $from_encoding);
  1010. $str = mb_convert_encoding(" ", $to_encoding, $from_encoding);
  1011. $content = mb_eregi_replace($str, " ", $content);
  1012. $content = mb_convert_encoding($content, $from_encoding, $to_encoding);
  1013. $content = trim($content);
  1014. return $content;
  1015. }
  1016. /**
  1017. * 将非UTF-8字符集的编码转为UTF-8
  1018. *
  1019. * @param mixed $mixed 源数据
  1020. *
  1021. * @return mixed utf-8格式数据
  1022. */
  1023. function charset2utf8($mixed)
  1024. {
  1025. if (is_array($mixed)) {
  1026. foreach ($mixed as $k => $v) {
  1027. if (is_array($v)) {
  1028. $mixed[ $k ] = charsetToUTF8($v);
  1029. } else {
  1030. $encode = mb_detect_encoding($v, array( 'ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5' ));
  1031. if ($encode == 'EUC-CN') {
  1032. $mixed[ $k ] = iconv('GBK', 'UTF-8', $v);
  1033. }
  1034. }
  1035. }
  1036. } else {
  1037. $encode = mb_detect_encoding($mixed, array( 'ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5' ));
  1038. if ($encode == 'EUC-CN') {
  1039. $mixed = iconv('GBK', 'UTF-8', $mixed);
  1040. }
  1041. }
  1042. return $mixed;
  1043. }
  1044. /**
  1045. * 过滤bom
  1046. * @param $filename
  1047. */
  1048. function check_bom ($filename) {
  1049. $contents = file_get_contents($filename);
  1050. $charset[1] = substr($contents, 0, 1);
  1051. $charset[2] = substr($contents, 1, 1);
  1052. $charset[3] = substr($contents, 2, 1);
  1053. if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191) {
  1054. $rest = substr($contents, 3);
  1055. return $rest;
  1056. }else{
  1057. return $contents;
  1058. }
  1059. }
  1060. /**
  1061. * 判断 文件/目录 是否可写(取代系统自带的 is_writeable 函数)
  1062. *
  1063. * @param string $file 文件/目录
  1064. * @return boolean
  1065. */
  1066. function is_write($file)
  1067. {
  1068. if (is_dir($file)) {
  1069. $dir = $file;
  1070. if ($fp = @fopen("$dir/test.txt", 'w')) {
  1071. @fclose($fp);
  1072. @unlink("$dir/test.txt");
  1073. $writeable = true;
  1074. } else {
  1075. $writeable = false;
  1076. }
  1077. } else {
  1078. if ($fp = @fopen($file, 'a+')) {
  1079. @fclose($fp);
  1080. $writeable = true;
  1081. } else {
  1082. $writeable = false;
  1083. }
  1084. }
  1085. return $writeable;
  1086. }
  1087. /**
  1088. * 是否是url链接
  1089. * @param unknown $string
  1090. * @return boolean
  1091. */
  1092. function is_url($string)
  1093. {
  1094. if (strstr($string, 'http://') === false && strstr($string, 'https://') === false) {
  1095. return false;
  1096. } else {
  1097. return true;
  1098. }
  1099. }
  1100. /**
  1101. * 根据两点间的经纬度计算距离
  1102. * @param float $lng1
  1103. * @param float $lat1
  1104. * @param float $lng2
  1105. * @param float $lat2
  1106. * @return number
  1107. */
  1108. function getDistance(float $lng1, float $lat1, float $lng2, float $lat2)
  1109. {
  1110. if (($lng1 == $lng2) && ($lat1 == $lat2)) {
  1111. return 0;
  1112. }
  1113. //将角度转为狐度
  1114. $radLat1 = deg2rad($lat1);//deg2rad()函数将角度转换为弧度
  1115. $radLat2 = deg2rad($lat2);
  1116. $radLng1 = deg2rad($lng1);
  1117. $radLng2 = deg2rad($lng2);
  1118. $a = $radLat1 - $radLat2;
  1119. $b = $radLng1 - $radLng2;
  1120. $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))) * 6378.137 * 1000;
  1121. return $s;
  1122. }