common.php 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271
  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. print_r($event);
  491. $res = Event::trigger($event, $args);
  492. print_r($res);
  493. if (is_array($res)) {
  494. $res = array_filter($res);
  495. sort($res);
  496. }
  497. //只返回一个结果集
  498. if ($once) {
  499. return isset($res[0]) ? $res[0] : '';
  500. }
  501. return $res;
  502. }
  503. /**
  504. * 错误返回值函数
  505. * @param int $code
  506. * @param string $message
  507. * @param string $data
  508. * @return array
  509. */
  510. function error($code = -1, $message = '', $data = '')
  511. {
  512. return [
  513. 'code' => $code,
  514. 'message' => $message,
  515. 'data' => $data
  516. ];
  517. }
  518. /**
  519. * 返回值函数
  520. * @param int $code
  521. * @param string $message
  522. * @param string $data
  523. * @return array
  524. */
  525. function success($code = 0, $message = '', $data = '')
  526. {
  527. return [
  528. 'code' => $code,
  529. 'message' => $message,
  530. 'data' => $data
  531. ];
  532. }
  533. /**
  534. * 实例化Model
  535. *
  536. * @param string $name
  537. * Model名称
  538. */
  539. function model($table = '')
  540. {
  541. return new \app\model\Model($table);
  542. }
  543. /**
  544. * 获取带有表前缀的表名
  545. * @param string $table
  546. */
  547. function table($table = '')
  548. {
  549. return config('database.connections.prefix') . $table;
  550. }
  551. function xml_parser($str){
  552. $xml_parser = xml_parser_create();
  553. if(!xml_parse($xml_parser,$str,true)){
  554. xml_parser_free($xml_parser);
  555. return false;
  556. }
  557. else {
  558. return true;
  559. }
  560. }
  561. /**
  562. * 获取图片的真实路径
  563. *
  564. * @param string $path 图片初始路径
  565. * @param string $type 类型 big、mid、small
  566. * @return string 图片的真实路径
  567. */
  568. function img($path, $type = '')
  569. {
  570. $start = strripos($path, '.');
  571. $type = $type ? '_' . $type : '';
  572. $first = explode("/", $path);
  573. $path = substr_replace($path, $type, $start, 0);
  574. if (stristr($path, "http://") === false && stristr($path, "https://") === false) {
  575. if (is_numeric($first[0])) {
  576. $true_path = __ROOT__ . '/upload/' . $path;
  577. } else {
  578. $true_path = __ROOT__ . '/' . $path;
  579. }
  580. } else {
  581. $true_path = $path;
  582. }
  583. return $true_path;
  584. }
  585. /**
  586. * 获取标准二维码格式
  587. *
  588. * @param string $url
  589. * @param string $path
  590. * @param string $ext
  591. */
  592. function qrcode($url, $path, $qrcode_name)
  593. {
  594. if (!is_dir($path)) {
  595. $mode = intval('0777', 8);
  596. mkdir($path, $mode, true);
  597. chmod($path, $mode);
  598. }
  599. $path = $path . '/' . $qrcode_name . '.png';
  600. if (file_exists($path)) {
  601. unlink($path);
  602. }
  603. QRcode::png($url, $path, '', 4, 1);
  604. return $path;
  605. }
  606. /**
  607. * 前端页面api请求(通过api接口实现)
  608. * @param string $method
  609. * @param array $params
  610. * @return mixed
  611. */
  612. function api($method, $params = [])
  613. {
  614. //本地访问
  615. $data = get_api_data($method, $params);
  616. return $data;
  617. }
  618. /**
  619. * 获取Api类
  620. *
  621. * @param string $method
  622. */
  623. function get_api_data($method, $params)
  624. {
  625. $method_array = explode('.', $method);
  626. if ($method_array[0] == 'System') {
  627. $class_name = 'app\\api\\controller\\' . $method_array[1];
  628. if (!class_exists($class_name)) {
  629. return error();
  630. }
  631. $api_model = new $class_name($params);
  632. } else {
  633. $class_name = "addon\\{$method_array[0]}\\api\\controller\\" . $method_array[1];
  634. if (!class_exists($class_name)) {
  635. return error();
  636. }
  637. $api_model = new $class_name($params);
  638. }
  639. $function = $method_array[2];
  640. $data = $api_model->$function($params);
  641. return $data;
  642. }
  643. /**
  644. * 根据年份计算生肖
  645. * @param unknown $year
  646. */
  647. function get_zodiac($year)
  648. {
  649. $animals = array(
  650. '鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪'
  651. );
  652. $key = ($year - 1900) % 12;
  653. return $animals[ $key ];
  654. }
  655. /**
  656. * 计算.星座
  657. * @param int $month 月份
  658. * @param int $day 日期
  659. * @return str
  660. */
  661. function get_constellation($month, $day)
  662. {
  663. $constellations = array(
  664. '水瓶座', '双鱼座', '白羊座', '金牛座', '双子座', '巨蟹座',
  665. '狮子座', '处女座', '天秤座', '天蝎座', '射手座', '摩羯座'
  666. );
  667. if ($day <= 22) {
  668. if (1 != $month) {
  669. $constellation = $constellations[ $month - 2 ];
  670. } else {
  671. $constellation = $constellations[11];
  672. }
  673. } else {
  674. $constellation = $constellations[ $month - 1 ];
  675. }
  676. return $constellation;
  677. }
  678. /**
  679. * 数组键名转化为数字
  680. * @param $data
  681. */
  682. function arr_key_to_int($data, $clild_name)
  683. {
  684. $temp_data = array_values($data);
  685. foreach ($temp_data as $k => $v) {
  686. if (!empty($v[ $clild_name ])) {
  687. $temp_data[ $k ][ $clild_name ] = arr_key_to_int($v[ $clild_name ], $clild_name);
  688. }
  689. }
  690. return $temp_data;
  691. }
  692. /**
  693. * 以天为单位 计算间隔内的日期数组
  694. * @param $start_time
  695. * @param $end_time
  696. * @return array
  697. */
  698. function period_group($start_time, $end_time, $format = 'Ymd')
  699. {
  700. $type_time = 3600 * 24;
  701. $data = [];
  702. for ($i = $start_time; $i <= $end_time; $i += $type_time) {
  703. $data[] = date($format, $i);
  704. }
  705. return $data;
  706. }
  707. /**
  708. * 数组删除另一个数组
  709. * @param $arr
  710. * @param $del_arr
  711. * @return mixed
  712. */
  713. function arr_del_arr($arr, $del_arr)
  714. {
  715. foreach ($arr as $k => $v) {
  716. if (in_array($v, $del_arr)) {
  717. unset($arr[ $k ]);
  718. }
  719. }
  720. sort($arr);
  721. return $arr;
  722. }
  723. /**
  724. * 检测登录(应用于h5网页检测登录)
  725. * @param unknown $url
  726. */
  727. function check_auth($url = '')
  728. {
  729. $access_token = Session::get("access_token_" . request()->siteid());
  730. if (empty($access_token)) {
  731. if (!empty($url)) {
  732. Session::set("redirect_login_url", $url);
  733. }
  734. //尚未登录(直接跳转)
  735. return error(url('wap/login/login'));
  736. }
  737. $member_info = cache("member_info_" . request()->siteid() . $access_token);
  738. if (empty($member_info)) {
  739. $member_info = api("System.Member.memberInfo", [ 'access_token' => $access_token ]);
  740. if ($member_info['code'] == 0) {
  741. $member_info = $member_info['data'];
  742. cache("member_info_" . request()->siteid() . $access_token, $member_info);
  743. }
  744. }
  745. $member_info['access_token'] = $access_token;
  746. return success($member_info);
  747. }
  748. /**
  749. * 分割sql语句
  750. * @param string $content sql内容
  751. * @param bool $string 如果为真,则只返回一条sql语句,默认以数组形式返回
  752. * @param array $replace 替换前缀,如:['my_' => 'me_'],表示将表前缀my_替换成me_
  753. * @return array|string 除去注释之后的sql语句数组或一条语句
  754. */
  755. function parse_sql($content = '', $string = false, $replace = [])
  756. {
  757. // 纯sql内容
  758. $pure_sql = [];
  759. // 被替换的前缀
  760. $from = '';
  761. // 要替换的前缀
  762. $to = '';
  763. // 替换表前缀
  764. if (!empty($replace)) {
  765. $to = current($replace);
  766. $from = current(array_flip($replace));
  767. }
  768. if ($content != '') {
  769. // 多行注释标记
  770. $comment = false;
  771. // 按行分割,兼容多个平台
  772. $content = str_replace([ "\r\n", "\r" ], "\n", $content);
  773. $content = explode("\n", trim($content));
  774. // 循环处理每一行
  775. foreach ($content as $key => $line) {
  776. // 跳过空行
  777. if ($line == '') {
  778. continue;
  779. }
  780. // 跳过以#或者--开头的单行注释
  781. if (preg_match("/^(#|--)/", $line)) {
  782. continue;
  783. }
  784. // 跳过以/**/包裹起来的单行注释
  785. if (preg_match("/^\/\*(.*?)\*\//", $line)) {
  786. continue;
  787. }
  788. // 多行注释开始
  789. if (substr($line, 0, 2) == '/*') {
  790. $comment = true;
  791. continue;
  792. }
  793. // 多行注释结束
  794. if (substr($line, -2) == '*/') {
  795. $comment = false;
  796. continue;
  797. }
  798. // 多行注释没有结束,继续跳过
  799. if ($comment) {
  800. continue;
  801. }
  802. // 替换表前缀
  803. if ($from != '') {
  804. $line = str_replace('`' . $from, '`' . $to, $line);
  805. }
  806. // sql语句
  807. $pure_sql[] = $line;
  808. }
  809. // 只返回一条语句
  810. if ($string) {
  811. return implode($pure_sql, "");
  812. }
  813. // 以数组形式返回sql语句
  814. $pure_sql = implode($pure_sql, "\n");
  815. $pure_sql = explode(";\n", $pure_sql);
  816. }
  817. return $pure_sql;
  818. }
  819. /**
  820. * 执行sql
  821. * @param unknown $sql_name
  822. */
  823. function execute_sql($sql_name)
  824. {
  825. $sql_string = file_get_contents($sql_name);
  826. $sql_string = str_replace("{{prefix}}", config("database.connections.mysql.prefix"), $sql_string);
  827. if ($sql_string) {
  828. $sql = explode(";\n", str_replace("\r", "\n", $sql_string));
  829. foreach ($sql as $value) {
  830. $value = trim($value);
  831. if (!empty($value)) {
  832. \think\facade\Db::execute($value);
  833. }
  834. }
  835. }
  836. }
  837. /**
  838. * 检测目录读写权限
  839. */
  840. function check_dir_iswritable($dir)
  841. {
  842. $testDir = $dir;
  843. sp_dir_create($testDir);
  844. if (sp_testwrite($testDir)) {
  845. return true;
  846. } else {
  847. return false;
  848. }
  849. }
  850. /**
  851. * 检查测试文件是否可写入
  852. */
  853. function sp_testwrite($d)
  854. {
  855. $tfile = "_test.txt";
  856. $fp = @fopen($d . "/" . $tfile, "w");
  857. if (!$fp) {
  858. return false;
  859. }
  860. fclose($fp);
  861. $rs = @unlink($d . "/" . $tfile);
  862. if ($rs) {
  863. return true;
  864. }
  865. return false;
  866. }
  867. /**
  868. * 检查文件是否创建
  869. */
  870. function sp_dir_create($path, $mode = 0777)
  871. {
  872. if (is_dir($path))
  873. return true;
  874. $ftp_enable = 0;
  875. $path = sp_dir_path($path);
  876. $temp = explode('/', $path);
  877. $cur_dir = '';
  878. $max = count($temp) - 1;
  879. for ($i = 0; $i < $max; $i++) {
  880. $cur_dir .= $temp[ $i ] . '/';
  881. if (@is_dir($cur_dir))
  882. continue;
  883. @mkdir($cur_dir, 0777, true);
  884. @chmod($cur_dir, 0777);
  885. }
  886. return is_dir($path);
  887. }
  888. /**
  889. * 判断目录是否为空
  890. * @param $dir
  891. * @return bool
  892. */
  893. function dir_is_empty($dir)
  894. {
  895. $handle = opendir($dir);
  896. while (false !== ($entry = readdir($handle))) {
  897. if ($entry != "." && $entry != "..") {
  898. return FALSE;
  899. }
  900. }
  901. return TRUE;
  902. }
  903. /**
  904. * 创建文件夹
  905. *
  906. * @param string $path 文件夹路径
  907. * @param int $mode 访问权限
  908. * @param bool $recursive 是否递归创建
  909. * @return bool
  910. */
  911. function dir_mkdir($path = '', $mode = 0777, $recursive = true)
  912. {
  913. clearstatcache();
  914. if (!is_dir($path)) {
  915. mkdir($path, $mode, $recursive);
  916. return chmod($path, $mode);
  917. }
  918. return true;
  919. }
  920. /**
  921. * 文件夹文件拷贝
  922. *
  923. * @param string $src 来源文件夹
  924. * @param string $dst 目的地文件夹
  925. * @return bool
  926. */
  927. function dir_copy($src = '', $dst = '')
  928. {
  929. if (empty($src) || empty($dst)) {
  930. return false;
  931. }
  932. $dir = opendir($src);
  933. dir_mkdir($dst);
  934. while (false !== ($file = readdir($dir))) {
  935. if (($file != '.') && ($file != '..')) {
  936. if (is_dir($src . '/' . $file)) {
  937. dir_copy($src . '/' . $file, $dst . '/' . $file);
  938. } else {
  939. copy($src . '/' . $file, $dst . '/' . $file);
  940. }
  941. }
  942. }
  943. closedir($dir);
  944. return true;
  945. }
  946. /**查询存在目录
  947. * @param $dir
  948. */
  949. function sp_exist_dir($dir)
  950. {
  951. $is_exist = false;
  952. $is_write = false;
  953. while (!$is_exist) {
  954. $dir = dirname($dir);
  955. if (is_dir($dir) || $dir == ".") {
  956. $is_exist = true;
  957. if (is_writeable($dir)) {
  958. $is_write = true;
  959. }
  960. }
  961. }
  962. return $is_write;
  963. }
  964. /**
  965. * 拼接字符串
  966. * @param $string
  967. * @param $delimiter 分割字符
  968. * @param $value
  969. */
  970. function string_split($string, $delimiter, $value)
  971. {
  972. return empty($string) ? $value : $string . $delimiter . $value;
  973. }
  974. /**
  975. * $str为要进行截取的字符串,$length为截取长度(汉字算一个字,字母算半个字
  976. * @param $str
  977. * @param $length
  978. * @return string
  979. */
  980. function str_sub($str, $length = 10)
  981. {
  982. return mb_substr($str, 0, $length, 'UTF-8') . "...";
  983. }
  984. /**
  985. * 删除缓存文件使用
  986. * @param $dir
  987. */
  988. function rmdirs($dir)
  989. {
  990. $dir = 'runtime/' . $dir;
  991. $dh = opendir($dir);
  992. while ($file = readdir($dh)) {
  993. if ($file != "." && $file != "..") {
  994. $fullpath = $dir . "/" . $file;
  995. if (is_dir($fullpath)) {
  996. rmdirs($fullpath);
  997. } else {
  998. unlink($fullpath);
  999. }
  1000. }
  1001. }
  1002. closedir($dh);
  1003. }
  1004. /**
  1005. * 以天为单位 计算间隔内的日期数组
  1006. * @param $srart_time
  1007. * @param $end_time
  1008. * @return array
  1009. */
  1010. function periodGroup($srart_time, $end_time, $format = 'Ymd')
  1011. {
  1012. $type_time = 3600 * 24;
  1013. $data = [];
  1014. for ($i = $srart_time; $i <= $end_time; $i += $type_time) {
  1015. $data[] = date($format, $i);
  1016. }
  1017. return $data;
  1018. }
  1019. //解决个别中文乱码
  1020. function mbStrreplace($content, $to_encoding = "UTF-8", $from_encoding = "GBK")
  1021. {
  1022. $content = mb_convert_encoding($content, $to_encoding, $from_encoding);
  1023. $str = mb_convert_encoding(" ", $to_encoding, $from_encoding);
  1024. $content = mb_eregi_replace($str, " ", $content);
  1025. $content = mb_convert_encoding($content, $from_encoding, $to_encoding);
  1026. $content = trim($content);
  1027. return $content;
  1028. }
  1029. /**
  1030. * 将非UTF-8字符集的编码转为UTF-8
  1031. *
  1032. * @param mixed $mixed 源数据
  1033. *
  1034. * @return mixed utf-8格式数据
  1035. */
  1036. function charset2utf8($mixed)
  1037. {
  1038. if (is_array($mixed)) {
  1039. foreach ($mixed as $k => $v) {
  1040. if (is_array($v)) {
  1041. $mixed[ $k ] = charsetToUTF8($v);
  1042. } else {
  1043. $encode = mb_detect_encoding($v, array( 'ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5' ));
  1044. if ($encode == 'EUC-CN') {
  1045. $mixed[ $k ] = iconv('GBK', 'UTF-8', $v);
  1046. }
  1047. }
  1048. }
  1049. } else {
  1050. $encode = mb_detect_encoding($mixed, array( 'ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5' ));
  1051. if ($encode == 'EUC-CN') {
  1052. $mixed = iconv('GBK', 'UTF-8', $mixed);
  1053. }
  1054. }
  1055. return $mixed;
  1056. }
  1057. /**
  1058. * 过滤bom
  1059. * @param $filename
  1060. */
  1061. function check_bom ($filename) {
  1062. $contents = file_get_contents($filename);
  1063. $charset[1] = substr($contents, 0, 1);
  1064. $charset[2] = substr($contents, 1, 1);
  1065. $charset[3] = substr($contents, 2, 1);
  1066. if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191) {
  1067. $rest = substr($contents, 3);
  1068. return $rest;
  1069. }else{
  1070. return $contents;
  1071. }
  1072. }
  1073. /**
  1074. * 判断 文件/目录 是否可写(取代系统自带的 is_writeable 函数)
  1075. *
  1076. * @param string $file 文件/目录
  1077. * @return boolean
  1078. */
  1079. function is_write($file)
  1080. {
  1081. if (is_dir($file)) {
  1082. $dir = $file;
  1083. if ($fp = @fopen("$dir/test.txt", 'w')) {
  1084. @fclose($fp);
  1085. @unlink("$dir/test.txt");
  1086. $writeable = true;
  1087. } else {
  1088. $writeable = false;
  1089. }
  1090. } else {
  1091. if ($fp = @fopen($file, 'a+')) {
  1092. @fclose($fp);
  1093. $writeable = true;
  1094. } else {
  1095. $writeable = false;
  1096. }
  1097. }
  1098. return $writeable;
  1099. }
  1100. /**
  1101. * 是否是url链接
  1102. * @param unknown $string
  1103. * @return boolean
  1104. */
  1105. function is_url($string)
  1106. {
  1107. if (strstr($string, 'http://') === false && strstr($string, 'https://') === false) {
  1108. return false;
  1109. } else {
  1110. return true;
  1111. }
  1112. }
  1113. /**
  1114. * 根据两点间的经纬度计算距离
  1115. * @param float $lng1
  1116. * @param float $lat1
  1117. * @param float $lng2
  1118. * @param float $lat2
  1119. * @return number
  1120. */
  1121. function getDistance(float $lng1, float $lat1, float $lng2, float $lat2)
  1122. {
  1123. if (($lng1 == $lng2) && ($lat1 == $lat2)) {
  1124. return 0;
  1125. }
  1126. //将角度转为狐度
  1127. $radLat1 = deg2rad($lat1);//deg2rad()函数将角度转换为弧度
  1128. $radLat2 = deg2rad($lat2);
  1129. $radLng1 = deg2rad($lng1);
  1130. $radLng2 = deg2rad($lng2);
  1131. $a = $radLat1 - $radLat2;
  1132. $b = $radLng1 - $radLng2;
  1133. $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))) * 6378.137 * 1000;
  1134. return $s;
  1135. }
  1136. /**
  1137. * 变更会员积分等
  1138. * @param int $money 余额
  1139. * @param int $user_id 会员ID
  1140. * @param string $memo 备注
  1141. */
  1142. function memberMoneyChange($num, $type , $m_id, $title, $pm = 0,$link_id=0)
  1143. {
  1144. $member = Db::name('v4member')->where('member_id',$m_id)->find();
  1145. switch ($type){
  1146. case 1: //积分
  1147. $before = $member['integral'];
  1148. if ($pm==1)
  1149. $after = $member['integral']+$num;
  1150. else
  1151. $after = $member['integral']-$num;
  1152. $update_data = ['integral'=>$after];
  1153. break;
  1154. case 2: //抢购卡
  1155. $before = $member['snap_card'];
  1156. if ($pm==1)
  1157. $after = $member['snap_card']+$num;
  1158. else
  1159. $after = $member['snap_card']-$num;
  1160. $update_data = ['snap_card'=>$after];
  1161. break;
  1162. case 3: //余额
  1163. $before = $member['money'];
  1164. if ($pm==1)
  1165. $after = $member['money']+$num;
  1166. else
  1167. $after = $member['money']-$num;
  1168. $update_data = ['money'=>$after];
  1169. break;
  1170. }
  1171. try {
  1172. Db::name('v4member')->where('member_id',$m_id)->update($update_data);
  1173. $data = [
  1174. 'm_id'=>$m_id,
  1175. 'type'=>$type,
  1176. 'pm'=>$pm,
  1177. 'title'=>$title,
  1178. 'change'=>$num,
  1179. 'before'=>$before,
  1180. 'after'=>$after,
  1181. 'link_id'=>$link_id
  1182. ];
  1183. Db::name('v4member_balance')->insert($data);
  1184. return true;
  1185. }catch (\Exception $e){
  1186. return false;
  1187. }
  1188. }