util.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. <?php
  2. namespace common\components;
  3. use Yii;
  4. use yii\helpers\Json;
  5. class util
  6. {
  7. //判断是否微信浏览器
  8. public static function isWx()
  9. {
  10. if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') == true) {
  11. return true;
  12. }
  13. return false;
  14. }
  15. //根据两点间的经纬度计算距离
  16. public static function getDistance($lat1, $lng1, $lat2, $lng2)
  17. {
  18. $earthRadius = 6367000; //approximate radius of earth in meters
  19. /*
  20. Convert these degrees to radians
  21. to work with the formula
  22. */
  23. $lat1 = ($lat1 * pi()) / 180;
  24. $lng1 = ($lng1 * pi()) / 180;
  25. $lat2 = ($lat2 * pi()) / 180;
  26. $lng2 = ($lng2 * pi()) / 180;
  27. /*
  28. Using the
  29. Haversine formula
  30. http://en.wikipedia.org/wiki/Haversine_formula
  31. calculate the distance
  32. */
  33. $calcLongitude = $lng2 - $lng1;
  34. $calcLatitude = $lat2 - $lat1;
  35. $stepOne = pow(sin($calcLatitude / 2), 2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude / 2), 2);
  36. $stepTwo = 2 * asin(min(1, sqrt($stepOne)));
  37. $calculatedDistance = $earthRadius * $stepTwo;
  38. return round($calculatedDistance);
  39. }
  40. /**
  41. * 生成缩略图
  42. * @author yangzhiguo0903@163.com
  43. * @param string 源图绝对完整地址{带文件名及后缀名}
  44. * @param string 目标图绝对完整地址{带文件名及后缀名}
  45. * @param int 缩略图宽{0:此时目标高度不能为0,目标宽度为源图宽*(目标高度/源图高)}
  46. * @param int 缩略图高{0:此时目标宽度不能为0,目标高度为源图高*(目标宽度/源图宽)}
  47. * @param int 是否裁切{宽,高必须非0}
  48. * @param int /float 缩放{0:不缩放, 0<this<1:缩放到相应比例(此时宽高限制和裁切均失效)}
  49. * @return boolean
  50. */
  51. public static function img2thumb($src_img, $dst_img, $width = 75, $height = 75, $cut = 0, $proportion = 0)
  52. {
  53. if (!is_file($src_img)) {
  54. return false;
  55. }
  56. $ot = pathinfo($dst_img, PATHINFO_EXTENSION);
  57. $otfunc = 'image' . ($ot == 'jpg' ? 'jpeg' : $ot);
  58. $srcinfo = getimagesize($src_img);
  59. $src_w = $srcinfo[0];
  60. $src_h = $srcinfo[1];
  61. $type = strtolower(substr(image_type_to_extension($srcinfo[2]), 1));
  62. $createfun = 'imagecreatefrom' . ($type == 'jpg' ? 'jpeg' : $type);
  63. $dst_h = $height;
  64. $dst_w = $width;
  65. $x = $y = 0;
  66. /**
  67. * 缩略图不超过源图尺寸(前提是宽或高只有一个)
  68. */
  69. if (($width > $src_w && $height > $src_h) || ($height > $src_h && $width == 0) || ($width > $src_w && $height == 0)) {
  70. $proportion = 1;
  71. }
  72. if ($width > $src_w) {
  73. $dst_w = $width = $src_w;
  74. }
  75. if ($height > $src_h) {
  76. $dst_h = $height = $src_h;
  77. }
  78. if (!$width && !$height && !$proportion) {
  79. return false;
  80. }
  81. if (!$proportion) {
  82. if ($cut == 0) {
  83. if ($dst_w && $dst_h) {
  84. if ($dst_w / $src_w > $dst_h / $src_h) {
  85. $dst_w = $src_w * ($dst_h / $src_h);
  86. $x = 0 - ($dst_w - $width) / 2;
  87. } else {
  88. $dst_h = $src_h * ($dst_w / $src_w);
  89. $y = 0 - ($dst_h - $height) / 2;
  90. }
  91. } else if ($dst_w xor $dst_h) {
  92. if ($dst_w && !$dst_h) //有宽无高
  93. {
  94. $propor = $dst_w / $src_w;
  95. $height = $dst_h = $src_h * $propor;
  96. } else if (!$dst_w && $dst_h) //有高无宽
  97. {
  98. $propor = $dst_h / $src_h;
  99. $width = $dst_w = $src_w * $propor;
  100. }
  101. }
  102. } else {
  103. if (!$dst_h) //裁剪时无高
  104. {
  105. $height = $dst_h = $dst_w;
  106. }
  107. if (!$dst_w) //裁剪时无宽
  108. {
  109. $width = $dst_w = $dst_h;
  110. }
  111. $propor = min(max($dst_w / $src_w, $dst_h / $src_h), 1);
  112. $dst_w = (int)round($src_w * $propor);
  113. $dst_h = (int)round($src_h * $propor);
  114. $x = ($width - $dst_w) / 2;
  115. $y = ($height - $dst_h) / 2;
  116. }
  117. } else {
  118. $proportion = min($proportion, 1);
  119. $height = $dst_h = $src_h * $proportion;
  120. $width = $dst_w = $src_w * $proportion;
  121. }
  122. $src = $createfun($src_img);
  123. $dst = imagecreatetruecolor($width ? $width : $dst_w, $height ? $height : $dst_h);
  124. $white = imagecolorallocate($dst, 255, 255, 255);
  125. imagefill($dst, 0, 0, $white);
  126. if (function_exists('imagecopyresampled')) {
  127. imagecopyresampled($dst, $src, $x, $y, 0, 0, $dst_w, $dst_h, $src_w, $src_h);
  128. } else {
  129. imagecopyresized($dst, $src, $x, $y, 0, 0, $dst_w, $dst_h, $src_w, $src_h);
  130. }
  131. $otfunc($dst, $dst_img);
  132. imagedestroy($dst);
  133. imagedestroy($src);
  134. //return true;
  135. return ['width' => $src_w, 'height' => $src_h];//modify sofashi
  136. }
  137. /**
  138. * 输出字符并结束运行
  139. */
  140. public static function stop($string = '')
  141. {
  142. echo $string;
  143. Yii::$app->end();
  144. }
  145. public static function end()
  146. {
  147. Yii::$app->end();
  148. }
  149. /**
  150. * 输出json数据并结束运行
  151. */
  152. public static function encode($data)
  153. {
  154. echo Json::encode($data);
  155. exit();
  156. }
  157. /**
  158. * 组合需要的格式,输出json数据并结束运行
  159. * code A0001 正确 其它如:A0002表示错误
  160. */
  161. public static function failInfo($msg = '操作失败', $code = 'A0002', $data = [])
  162. {
  163. $arr = ['code' => $code, 'msg' => $msg, 'data' => $data];
  164. self::encode($arr);
  165. }
  166. public static function successInfo($msg = '操作成功', $code = 'A0001', $data = [])
  167. {
  168. $arr = ['code' => $code, 'msg' => $msg, 'data' => $data];
  169. self::encode($arr);
  170. }
  171. //操作成功,只关心数据的返回
  172. public static function sendJson($data)
  173. {
  174. $arr = ['code' => 1, 'msg' => '操作成功', 'data' => $data];
  175. self::encode($arr);
  176. }
  177. //只关心返回失败状态
  178. public static function sendFail($msg)
  179. {
  180. //要输出页面
  181. if (isset(Yii::$app->params['exportStyle']) && Yii::$app->params['exportStyle'] == 'web') {
  182. //确认平台
  183. if (Yii::$app->params['appStyle'] == 'backend') {
  184. //跳转 echo '<script> window.location.href=""; </script>';
  185. }
  186. if (Yii::$app->params['appStyle'] == 'mobile') {
  187. //跳转 echo '<script> window.location.href=""; </script>';
  188. }
  189. Yii::$app->end();
  190. }
  191. $arr = ['code' => 0, 'msg' => $msg, 'data' => []];
  192. self::encode($arr);
  193. Yii::$app->end();
  194. }
  195. //只关心返回成功状态
  196. public static function sendSuccess()
  197. {
  198. $arr = ['code' => 1, 'msg' => '操作成功', 'data' => []];
  199. self::encode($arr);
  200. }
  201. /**
  202. * 合并图片 ---lqh 2017-05-05
  203. * @param $background_img 背景原图
  204. * @param $inline_img 内嵌原图
  205. * @return mixed 合并图的路径名称
  206. */
  207. public static function mergeImg($background_img, $inline_img, $type = 'wx')
  208. {
  209. $app = Yii::getAlias("@app");
  210. $saveDir = $app . '/../images/qrcode/';
  211. $rand = stringUtil::buildOrderNo();
  212. $random = empty($unique) ? $rand : $unique . '_' . $rand;
  213. //背景框图
  214. $path_1 = $background_img;
  215. //二维码图片
  216. $path_2 = $inline_img;
  217. //将框和二维码图片分别取到两个画布中。 针对png格式
  218. $image_1 = imagecreatefrompng($path_1);
  219. $image_2 = imagecreatefrompng($path_2);
  220. //创建一个和框图片一样大小的真彩色画布(ps:只有这样才能保证后面copy二维码图片的时候不会失真)
  221. $image_3 = imageCreatetruecolor(imagesx($image_1), imagesy($image_1));
  222. //为真彩色画布创建白色背景,再设置为透明
  223. $color = imagecolorallocate($image_3, 255, 255, 255);
  224. imagefill($image_3, 0, 0, $color);
  225. imageColorTransparent($image_3, $color);
  226. //首先将框画布采样copy到真彩色画布中,不会失真
  227. imagecopyresampled($image_3, $image_1, 0, 0, 0, 0, imagesx($image_1), imagesy($image_1), imagesx($image_1), imagesy($image_1));
  228. //再将二维码图片copy到已经具有框图像的真彩色画布中,同样也不会失真
  229. //根据微信或则支付宝合并位置有所不同
  230. if ($type == 'wx') {
  231. imagecopymerge($image_3, $image_2, 220, 320, 0, 0, imagesx($image_2), imagesy($image_2), 100);
  232. } else {
  233. //支付宝
  234. imagecopymerge($image_3, $image_2, 450, 820, 0, 0, imagesx($image_2), imagesy($image_2), 100);
  235. }
  236. //将画布保存到指定的png文件
  237. imagepng($image_3, $saveDir . $random . '_merge.png');
  238. return '/qrcode/' . $random . '_merge.png';//组合图片
  239. }
  240. public static function mergeQrimg($backgroundImg, array $qrImg)
  241. {
  242. $app = Yii::getAlias("@app");
  243. $saveDir = $app . '/../images/qrcode/';
  244. $random = stringUtil::buildOrderNo();
  245. $dest = imagecreatefromjpeg($backgroundImg);
  246. // Get new sizes
  247. list($width, $height) = getimagesize($qrImg['wifi']);
  248. list($newwidth, $newheight) = getimagesize($qrImg['zhifubao']);
  249. $newwidth = $newwidth + 35;//下载的wifi二维码size太小,放大些
  250. $newheight = $newheight + 35;
  251. // Load
  252. $thumb = imagecreatetruecolor($newwidth, $newheight);
  253. $source = imagecreatefromjpeg($qrImg['wifi']);
  254. // Resize
  255. imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
  256. imagejpeg($thumb, $saveDir . "temp.jpeg");//Output image to file
  257. //微信(支付宝)二维码、WiFi二维码
  258. $zfbQrImg = imagecreatefrompng($qrImg['zhifubao']);
  259. $WXQrImg = imagecreatefrompng($qrImg['weixin']);
  260. $wifiQrImg = imagecreatefromjpeg($saveDir . "temp.jpeg");
  261. imagealphablending($dest, false);
  262. imagesavealpha($dest, true);
  263. imagecopymerge($dest, $zfbQrImg, 240, 538, 0, 0, imagesx($zfbQrImg), imagesy($zfbQrImg), 100);
  264. imagecopymerge($dest, $WXQrImg, 985, 538, 0, 0, imagesx($WXQrImg), imagesy($WXQrImg), 100);
  265. imagecopymerge($dest, $wifiQrImg, 1708, 520, 0, 0, imagesx($wifiQrImg), imagesy($wifiQrImg), 100);
  266. imagepng($dest, $saveDir . $random . '_fullQrImg.png');
  267. imagedestroy($dest);
  268. imagedestroy($zfbQrImg);
  269. imagedestroy($WXQrImg);
  270. imagedestroy($wifiQrImg);
  271. return '/qrcode/' . $random . '_fullQrImg.png';//组合图片
  272. }
  273. /*
  274. *功能:php完美实现下载远程图片保存到本地
  275. *参数:文件url,保存文件目录,保存文件名称,使用的下载方式
  276. *当保存文件名称为空时则使用远程文件原来的名称
  277. */
  278. function downLoadImage($url, $save_dir = '', $filename = '', $type = 0)
  279. {
  280. if (trim($url) == '') {
  281. return array('file_name' => '', 'save_path' => '', 'error' => 1);
  282. }
  283. if (trim($save_dir) == '') {
  284. $save_dir = './';
  285. }
  286. if (trim($filename) == '') {//保存文件名
  287. $ext = strrchr($url, '.');
  288. if ($ext != '.gif' && $ext != '.jpg') {
  289. return array('file_name' => '', 'save_path' => '', 'error' => 3);
  290. }
  291. $filename = time() . $ext;
  292. }
  293. if (0 !== strrpos($save_dir, '/')) {
  294. $save_dir .= '/';
  295. }
  296. //创建保存目录
  297. if (!file_exists($save_dir) && !mkdir($save_dir, 0777, true)) {
  298. return array('file_name' => '', 'save_path' => '', 'error' => 5);
  299. }
  300. //获取远程文件所采用的方法
  301. if ($type) {
  302. $ch = curl_init();
  303. $timeout = 5;
  304. curl_setopt($ch, CURLOPT_URL, $url);
  305. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  306. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
  307. $img = curl_exec($ch);
  308. curl_close($ch);
  309. } else {
  310. ob_start();
  311. readfile($url);
  312. $img = ob_get_contents();
  313. ob_end_clean();
  314. }
  315. //$size=strlen($img);
  316. //文件大小
  317. $fp2 = @fopen($save_dir . $filename, 'a');
  318. fwrite($fp2, $img);
  319. fclose($fp2);
  320. unset($img, $url);
  321. return array('file_name' => $filename, 'save_path' => $save_dir . $filename, 'error' => 0);
  322. }
  323. //获取服务器IP
  324. public static function serverIp()
  325. {
  326. if (isset($_SERVER)) {
  327. if ($_SERVER['SERVER_ADDR']) {
  328. $server_ip = $_SERVER['SERVER_ADDR'];
  329. } else {
  330. $server_ip = $_SERVER['LOCAL_ADDR'];
  331. }
  332. } else {
  333. $server_ip = getenv('SERVER_ADDR');
  334. }
  335. return $server_ip;
  336. }
  337. //获取huahuibao根目录 shish 2020.3.11
  338. public static function getRootDir()
  339. {
  340. $basePath = Yii::$app->basePath;
  341. if (Yii::$app->id == 'app-console') {
  342. $root = $basePath . "/../";
  343. } else {
  344. $root = $basePath . "/../../";
  345. }
  346. return $root;
  347. }
  348. //格式化输出;用于调试时使用 shish 2019.8.20
  349. public static function print_r($data)
  350. {
  351. echo "<pre>";
  352. print_r($data);
  353. Yii::$app->end();
  354. }
  355. //错误输出
  356. public static function fail($msg = '操作失败')
  357. {
  358. Yii::info($msg);
  359. self::encode(['code' => 0, 'msg' => $msg, 'data' => []]);
  360. }
  361. //成功输出内容
  362. public static function success($data, $msg = '操作成功')
  363. {
  364. self::encode(['code' => 1, 'msg' => $msg, 'data' => $data]);
  365. }
  366. //退出当前登陆 shish 2020.3.8
  367. public static function logout()
  368. {
  369. self::encode(['code' => 2, 'msg' => '当前登陆信息已失效,请重新登陆', 'data' => []]);
  370. }
  371. //只输出执行完成状态 shish 2020.3.11
  372. public static function complete($msg = '')
  373. {
  374. $msg = empty($msg) ? '操作成功' : $msg;
  375. self::encode(['code' => 1, 'msg' => $msg, 'data' => []]);
  376. }
  377. public static function notLogin()
  378. {
  379. self::encode(['code' => -1, 'msg' => '没有登陆', 'data' => []]);
  380. }
  381. //shisq
  382. public static function echoStatus($num, $key, $status = 'status')
  383. {
  384. $dictionary = \common\components\configDict::$dict[$key][$status];
  385. echo $dictionary[$num];
  386. }
  387. /**
  388. * 二维数组根据字段进行排序 shisq
  389. * @params array $array 需要排序的数组
  390. * @params string $field 排序的字段
  391. * @params string $sort 排序顺序标志 SORT_DESC 降序;SORT_ASC 升序
  392. */
  393. public static function arraySequence($array, $field, $sort = 'SORT_DESC')
  394. {
  395. $arrSort = array();
  396. foreach ($array as $uniqid => $row) {
  397. foreach ($row as $key => $value) {
  398. $arrSort[$key][$uniqid] = $value;
  399. }
  400. }
  401. array_multisort($arrSort[$field], constant($sort), $array);
  402. return $array;
  403. }
  404. }