common.php 27 KB

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