stringUtil.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. <?php
  2. namespace common\components;
  3. use Overtrue\Pinyin\Pinyin;
  4. use Yii;
  5. class stringUtil
  6. {
  7. const KEY = 'Aos4eLEmqpo8dmJleG610tR1KxUVQ5OzgkzpYM23PLqwSaU3Io';
  8. //oss的base64方法 ssh 20230111
  9. public static function ossBase64($str)
  10. {
  11. $str = base64_encode($str);
  12. $str = str_replace('/', '_', $str);
  13. $str = str_replace('+', '-', $str);
  14. $str = rtrim($str, '=');
  15. return $str;
  16. }
  17. public static function passwordCheck($password)
  18. {
  19. if (preg_match('/^([0-9]{6,16})$/', $password)) {
  20. util::fail('密码不能纯数字');
  21. }
  22. if (preg_match('/^[a-z A-Z]{6,16}$/', $password)) {
  23. util::fail('密码不能纯字母');
  24. }
  25. if (strlen($password) < 6) {
  26. util::fail('密码必须大于6位');
  27. }
  28. }
  29. //随机编号,英文开头,用于鲜花商品编号
  30. public static function buildRandNo($id)
  31. {
  32. return 'F' . $id . time();// F == flower
  33. }
  34. //创建微信Token使用
  35. public static function buildWxToken($id)
  36. {
  37. return 'wt' . $id . time();
  38. }
  39. //订单号,用于购买商品生成的订单等
  40. public static function buildOrderNo($id = 0)
  41. {
  42. mt_srand((double)microtime() * 1000000);
  43. $no = empty($id) ? '' : $id;
  44. $no .= date('ymdHis') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
  45. return $no;
  46. }
  47. //判断是否手机号
  48. public static function isMobile($no)
  49. {
  50. return preg_match("/^1[0-9]\d{9}$/", $no) == true ? true : false;
  51. }
  52. public static function isEmail($email)
  53. {
  54. $reg = '/\w+@\w+(?:\.\w+){1,3}/i';
  55. if (preg_match($reg, $email)) {
  56. return true;
  57. }
  58. return false;
  59. }
  60. //是否所有都是英文字母 ssh 2021.1
  61. public static function isLetter($str)
  62. {
  63. if (preg_match("/^[a-zA-Z\s]+$/", $str)) {
  64. return true;
  65. }
  66. return false;
  67. }
  68. static function subStringUtf8($string, $length, $ext = '')
  69. {
  70. $num = self::getWordNum($string);
  71. //echo $num;exit();
  72. //如果截取字数大于字符长度
  73. if ($num <= $length) {
  74. return $string;
  75. }
  76. $str_length = $length * 3; //总的字节数
  77. $slen = 0;
  78. $i = 0;
  79. $count = 0;
  80. while ($i <= $str_length && $count < $length) {
  81. if (isset($string[$i])) {
  82. $c = ord($string[$i]);
  83. //第一个字节大于224的,它与它之后的2个字节一起组成一个UTF-8字符
  84. if ($c >= 224) {
  85. $bits = 3;
  86. $count++;
  87. //第一个字节大于192小于224的,它与它之后的1个字节组成一个UTF-8字符
  88. } elseif ($c >= 192) {
  89. $count++;
  90. $bits = 2;
  91. //否则第一个字节本身就是一个英文字符(包括数字和一小部分标点符号)
  92. } else {
  93. $bits = 1;
  94. $count += 0.5;
  95. }
  96. }
  97. $slen = $slen + $bits;
  98. $i = $i + $bits;
  99. }
  100. return substr($string, 0, $slen) . $ext;
  101. }
  102. //返回中文字数(二个字母会当一个汉字)
  103. static function getWordNum($string, $code = 'utf-8')
  104. {
  105. $i = 0; //开始字节数
  106. $count = 0; //开始字数
  107. if ($code == 'utf-8') { //utf-8编码
  108. while (isset($string[$i]) && ord($string[$i]) != 0) { //还没有到结尾
  109. $b = ord($string[$i]);
  110. //第一个字节大于224的,它与它之后的2个字节一起组成一个UTF-8字符
  111. if ($b >= 224) {
  112. $i += 3;
  113. $count++;
  114. //第一个字节大于192小于224的,它与它之后的1个字节组成一个UTF-8字符
  115. } elseif ($b >= 192) {
  116. $i += 2;
  117. $count++;
  118. //否则第一个字节本身就是一个英文字符(包括数字和一小部分标点符号)
  119. } else {
  120. $i += 1;
  121. $count += 0.5;
  122. }
  123. }
  124. return ceil($count);
  125. }
  126. //gkb编码
  127. while (isset($string[$i]) && ord($string[$i]) != 0) {
  128. $b = ord($string[$i]);
  129. //第一个字节ASCII码>129的,它与它之后的1个字节一起组成一个gbk字符。
  130. if ($b > 129) {
  131. $i += 2;
  132. $count++;
  133. //第一个字节ASCII码<=129的,一个字节组成一个gbk字符。
  134. } else {
  135. $i++;
  136. $count += 0.5;
  137. }
  138. }
  139. return ceil($count);
  140. }
  141. //取汉字拼音首字母
  142. //https://github.com/overtrue/pinyin
  143. public static function py($string)
  144. {
  145. if (empty($string)) {
  146. return '';
  147. }
  148. //如果包含中文
  149. if (preg_match('/[\x{4e00}-\x{9fa5}]/u', $string) > 0) {
  150. $pinyin = new Pinyin();
  151. $string = $pinyin->abbr($string, PINYIN_KEEP_ENGLISH);
  152. }
  153. return strtolower($string);
  154. }
  155. //取随机数
  156. static function charsShuffle($length)
  157. {
  158. $str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  159. $key = '';
  160. for ($i = 0; $i < $length; $i++) {
  161. $pos = mt_rand(0, strlen($str) - 1);
  162. $key .= $str[$pos];
  163. }
  164. return $key;
  165. }
  166. //取随机数(小写)
  167. static function charsShuffleLowerCase($length)
  168. {
  169. $str = 'abcdefghijklmnopqrstuvwxyz0123456789';
  170. $key = '';
  171. for ($i = 0; $i < $length; $i++) {
  172. $pos = mt_rand(0, strlen($str) - 1);
  173. $key .= $str[$pos];
  174. }
  175. return $key;
  176. }
  177. //随机取数字
  178. static function getRandNum($num)
  179. {
  180. $shuffle = str_shuffle('1234567890');
  181. $number = substr($shuffle, 0, $num);
  182. return $number;
  183. }
  184. // $string: 明文 或 密文
  185. // $operation:DECODE表示解密,其它表示加密
  186. // $key: 密匙
  187. // $expiry:密文有效期
  188. public function authcode($string, $operation = 'DECODE', $expiry = 0)
  189. {
  190. // 动态密匙长度,相同的明文会生成不同密文就是依靠动态密匙
  191. $ckey_length = 4;
  192. // 密匙
  193. $key = md5(self::KEY);
  194. // 密匙a会参与加解密
  195. $keya = md5(substr($key, 0, 16));
  196. // 密匙b会用来做数据完整性验证
  197. $keyb = md5(substr($key, 16, 16));
  198. // 密匙c用于变化生成的密文
  199. $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
  200. // 参与运算的密匙
  201. $cryptkey = $keya . md5($keya . $keyc);
  202. $key_length = strlen($cryptkey);
  203. // 明文,前10位用来保存时间戳,解密时验证数据有效性,10到26位用来保存$keyb(密匙b),解密时会通过这个密匙验证数据完整性
  204. // 如果是解码的话,会从第$ckey_length位开始,因为密文前$ckey_length位保存 动态密匙,以保证解密正确
  205. $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
  206. $string_length = strlen($string);
  207. $result = '';
  208. $box = range(0, 255);
  209. $rndkey = array();
  210. // 产生密匙簿
  211. for ($i = 0; $i <= 255; $i++) {
  212. $rndkey[$i] = ord($cryptkey[$i % $key_length]);
  213. }
  214. // 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度
  215. for ($j = $i = 0; $i < 256; $i++) {
  216. $j = ($j + $box[$i] + $rndkey[$i]) % 256;
  217. $tmp = $box[$i];
  218. $box[$i] = $box[$j];
  219. $box[$j] = $tmp;
  220. }
  221. // 核心加解密部分
  222. for ($a = $j = $i = 0; $i < $string_length; $i++) {
  223. $a = ($a + 1) % 256;
  224. $j = ($j + $box[$a]) % 256;
  225. $tmp = $box[$a];
  226. $box[$a] = $box[$j];
  227. $box[$j] = $tmp;
  228. // 从密匙簿得出密匙进行异或,再转成字符
  229. $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
  230. }
  231. if ($operation == 'DECODE') {
  232. // substr($result, 0, 10) == 0 验证数据有效性
  233. // substr($result, 0, 10) - time() > 0 验证数据有效性
  234. // substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性
  235. // 验证数据有效性,请看未加密明文的格式
  236. if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
  237. return substr($result, 26);
  238. } else {
  239. return '';
  240. }
  241. } else {
  242. // 把动态密匙保存在密文里,这也是为什么同样的明文,生产不同密文后能解密的原因
  243. // 因为加密后的密文可能是一些特殊字符,复制过程可能会丢失,所以用base64编码
  244. return $keyc . str_replace('=', '', base64_encode($result));
  245. }
  246. }
  247. /**
  248. * 返回8位随机字符,重复概率较低
  249. */
  250. public static function getRandStr($id = null)
  251. {
  252. $chars = "0123456789abcdefghijklmnopqrstuvwxyz";
  253. $res = "";
  254. for ($i = 0; $i < 8; $i++) {
  255. $res .= $chars[mt_rand(0, strlen($chars) - 1)];
  256. }
  257. $rand = empty($id) ? $res : $res . $id;
  258. return $rand;
  259. }
  260. public static function randIP()
  261. {
  262. $arr_1 = array("218", "218", "66", "66", "218", "218", "60", "60", "202", "204", "66", "66", "66", "59", "61", "60", "222", "221", "66", "59", "60", "60", "66", "218", "218", "62", "63", "64", "66", "66", "122", "211");
  263. $randarr = mt_rand(0, count($arr_1));
  264. $ip1id = $arr_1[$randarr];
  265. $ip2id = round(rand(600000, 2550000) / 10000);
  266. $ip3id = round(rand(600000, 2550000) / 10000);
  267. $ip4id = round(rand(600000, 2550000) / 10000);
  268. return $ip1id . "." . $ip2id . "." . $ip3id . "." . $ip4id;
  269. }
  270. //写日志
  271. public static function log($content, $file)
  272. {
  273. $content .= "\r\n";
  274. $fh = fopen($file, 'ab'); //打开,追加模式
  275. fwrite($fh, $content);
  276. fclose($fh);
  277. }
  278. //减法
  279. public static function calcSub($a, $b)
  280. {
  281. return ($a * 1000 - $b * 1000) / 1000;
  282. }
  283. //加法
  284. public static function calcAdd($a, $b)
  285. {
  286. return ($a * 1000 + $b * 1000) / 1000;
  287. }
  288. public static function ride($a, $b)
  289. {
  290. }
  291. /**
  292. * 生成商家提现需要使用的订单号
  293. */
  294. public static function generateMerchantCashOrderNo($sjId)
  295. {
  296. return "C" . date('ymdHis') . $sjId . mt_rand(10000, 99999);
  297. }
  298. //生成用户需要使用的订单号 ssh 2019.4.20
  299. public static function generateOrderNo($sjId, $userId)
  300. {
  301. $userId = empty($userId) ? rand(12013120, 12536120) : $userId;
  302. if (strlen($userId) < 8) {
  303. exit('用户ID少于8位数');
  304. }
  305. $no = date('ymdHis') . $sjId . $userId . mt_rand(10000, 99999);
  306. if (strlen($no) > 32) {
  307. exit('订单位数大于32位');
  308. }
  309. return $no;
  310. }
  311. //微信32位的场景ID ssh 2019.9.4
  312. public static function generateSceneId($sjId)
  313. {
  314. $no = 'S' . date('YmdHis') . $sjId . mt_rand(100000, 999999);
  315. if (strlen($no) > 32) {
  316. $no = substr($no, 0, 32);
  317. }
  318. return $no;
  319. }
  320. //将加密窜转成可以在http上传输的字符
  321. public static function urlSafeB64Encode($string)
  322. {
  323. $data = base64_encode($string);
  324. $data = str_replace(array('+', '/', '='), array('-', '_', ''), $data);
  325. return $data;
  326. }
  327. //将url上传输的字符解密
  328. public static function urlSafeBase64Decode($string)
  329. {
  330. $data = str_replace(array('-', '_'), array('+', '/'), $string);
  331. $mod4 = strlen($data) % 4;
  332. if ($mod4) {
  333. $data .= substr('====', $mod4);
  334. }
  335. return base64_decode($data);
  336. }
  337. //中文二边保留,中间用*号代替 ssh 2019.8.13
  338. public static function replaceXH($name)
  339. {
  340. //获取字符串长度
  341. $strlen = mb_strlen($name, 'utf-8');
  342. //如果字符创长度小于2,不做任何处理
  343. if ($strlen < 2) {
  344. return $name;
  345. } else {
  346. //mb_substr — 获取字符串的部分
  347. $firstStr = mb_substr($name, 0, 1, 'utf-8');
  348. $lastStr = mb_substr($name, -1, 1, 'utf-8');
  349. //str_repeat — 重复一个字符串
  350. return $strlen == 2 ? $firstStr . str_repeat('*', mb_strlen($name, 'utf-8') - 1) : $firstStr . str_repeat("*", $strlen - 2) . $lastStr;
  351. }
  352. }
  353. //生成唯一的文件名称 ssh 2020.1.7
  354. public static function uniqueFileName()
  355. {
  356. //参考 https://www.cnblogs.com/yjf512/p/9057229.html
  357. //https://www.cnblogs.com/roluce/p/6026081.html
  358. return md5(uniqid(mt_rand(), true));
  359. }
  360. //生成短的随机名称,基于当前时间微秒数 ssh 2020.4.13
  361. public static function shortUniqueId($id)
  362. {
  363. //示例:05e946fc1008bc
  364. return uniqid($id);
  365. }
  366. //参数格式化,错误提示查看友好 ssh 2021.01.04
  367. public static function paramsFriend($params)
  368. {
  369. $str = "[";
  370. if (!empty($params) && is_array($params)) {
  371. foreach ($params as $name => $item) {
  372. $item = is_array($item) ? json_encode($item) : $item;
  373. $str .= "\n{$name}=>{$item}";
  374. }
  375. }
  376. $str .= "\n]";
  377. return $str;
  378. }
  379. }