CrossPHP
  • Namespace
  • Class
  • Download

Namespaces

  • Cross
    • Auth
    • Cache
      • Driver
      • Request
    • Core
    • DB
      • Connecter
      • Drivers
      • SQLAssembler
    • Exception
    • Http
    • I
    • Lib
      • Document
    • Module
    • MVC
    • Runtime
  • None

Classes

  • Cross\Auth\CookieAuth
  • Cross\Auth\SessionAuth
  • Cross\Cache\Driver\FileCacheDriver
  • Cross\Cache\Driver\MemcacheDriver
  • Cross\Cache\Driver\RedisDriver
  • Cross\Cache\Request\FileCache
  • Cross\Cache\Request\Memcache
  • Cross\Cache\Request\RedisCache
  • Cross\Cache\RequestCache
  • Cross\Core\Annotate
  • Cross\Core\Application
  • Cross\Core\ArrayMap
  • Cross\Core\Config
  • Cross\Core\CrossArray
  • Cross\Core\Delegate
  • Cross\Core\FrameBase
  • Cross\Core\Helper
  • Cross\Core\HttpAuth
  • Cross\Core\Loader
  • Cross\Core\Rest
  • Cross\Core\Router
  • Cross\DB\Connecter\BaseConnecter
  • Cross\DB\Connecter\MySQLConnecter
  • Cross\DB\Connecter\PgSQLConnecter
  • Cross\DB\Connecter\SQLiteConnecter
  • Cross\DB\DBFactory
  • Cross\DB\Drivers\CouchDriver
  • Cross\DB\Drivers\MongoDriver
  • Cross\DB\Drivers\PDOSqlDriver
  • Cross\DB\SQLAssembler\MySQLAssembler
  • Cross\DB\SQLAssembler\PgSQLAssembler
  • Cross\DB\SQLAssembler\SQLAssembler
  • Cross\DB\SQLAssembler\SQLiteAssembler
  • Cross\Http\Request
  • Cross\Http\Response
  • Cross\Lib\Array2XML
  • Cross\Lib\Document\CallTree
  • Cross\Lib\Document\CallTreeToHTML
  • Cross\Lib\Document\HTML
  • Cross\Lib\StringToPHPStream
  • Cross\Module\SQLModule
  • Cross\MVC\Controller
  • Cross\MVC\Module
  • Cross\MVC\View
  • Cross\Runtime\ClosureContainer

Interfaces

  • Cross\I\CacheInterface
  • Cross\I\HttpAuthInterface
  • Cross\I\PDOConnecter
  • Cross\I\RequestCacheInterface
  • Cross\I\RouterInterface
  • Cross\I\SqlInterface

Exceptions

  • Cross\Exception\CacheException
  • Cross\Exception\CoreException
  • Cross\Exception\CrossException
  • Cross\Exception\FrontException

Functions

  • ascLogo
  • line
  • tBody
  • th
  • tHead
  1 <?php
  2 /**
  3  * Cross - a micro PHP 5 framework
  4  *
  5  * @link        http://www.crossphp.com
  6  * @license     MIT License
  7  */
  8 
  9 namespace Cross\Core;
 10 
 11 use Cross\Http\Request;
 12 use DOMDocument;
 13 
 14 /**
 15  * @author wonli <wonli@live.com>
 16  * Class Helper
 17  * @package Cross\Core
 18  */
 19 class Helper
 20 {
 21     /**
 22      * 截取字符串
 23      *
 24      * @param string $str 要截取的字符串参数
 25      * @param string $len 截取的长度
 26      * @param string $enc 字符串编码
 27      * @return string
 28      */
 29     public static function subStr($str, $len, $enc = 'utf8')
 30     {
 31         if (self::strLen($str) > $len) {
 32             return mb_substr($str, 0, $len, $enc) . '...';
 33         } else {
 34             return $str;
 35         }
 36     }
 37 
 38     /**
 39      * 安全的截取HTML字符串
 40      *
 41      * @param string $str 要截取的字符串参数
 42      * @param string $len 截取的长度
 43      * @param string $enc 字符串编码
 44      * @return string
 45      */
 46     public static function subStrHTML($str, $len, $enc = 'utf8')
 47     {
 48         $str = self::subStr($str, $len, $enc);
 49         return self::formatHTMLString($str);
 50     }
 51 
 52     /**
 53      * 处理HTML字符串,清除未闭合的HTML标签等
 54      *
 55      * @param string $str HTML字符串
 56      * @param bool $removing_doctype
 57      * @return string
 58      */
 59     public static function formatHTMLString($str, $removing_doctype = true)
 60     {
 61         $DOCUMENT = new DOMDocument();
 62         @$DOCUMENT->loadHTML(mb_convert_encoding($str, 'HTML-ENTITIES', 'UTF-8'));
 63         $content = $DOCUMENT->saveHTML($DOCUMENT->documentElement);
 64         if ($removing_doctype) {
 65             return preg_replace('~<(?:!DOCTYPE|/?(?:html|body))[^>]*>\s*~i', '', $content);
 66         }
 67 
 68         return $content;
 69     }
 70 
 71     /**
 72      * 计算字符串长度
 73      *
 74      * @param string $str 要计算的字符串
 75      * @param string $enc 默认utf8编码
 76      * @return int
 77      */
 78     public static function strLen($str, $enc = 'gb2312')
 79     {
 80         return min(array(mb_strlen($str, $enc), mb_strlen($str, 'utf-8')));
 81     }
 82 
 83     /**
 84      * 将指定编码的字符串分割为数组
 85      *
 86      * @param string $str
 87      * @param string $charset 字符编码 默认utf-8
 88      * @return array
 89      */
 90     static function stringToArray($str, $charset = 'utf-8')
 91     {
 92         if ($charset != 'utf-8') {
 93             $str = iconv($charset, 'utf-8', $str);
 94         }
 95 
 96         $result = array();
 97         for ($i = 0, $str_len = mb_strlen($str, 'utf-8'); $i < $str_len; $i++) {
 98             $result[] = mb_substr($str, $i, 1, 'utf-8');
 99         }
100 
101         return $result;
102     }
103 
104     /**
105      * 返回一个10位的md5编码后的str
106      *
107      * @param string $str
108      * @return string
109      */
110     static function md10($str = '')
111     {
112         return substr(md5($str), 10, 10);
113     }
114 
115     /**
116      * 取得文件扩展名
117      *
118      * @param string $file 文件名
119      * @return string
120      */
121     static function getExt($file)
122     {
123         return pathinfo($file, PATHINFO_EXTENSION);
124     }
125 
126     /**
127      * 创建文件夹
128      *
129      * @param string $path
130      * @param int $mode
131      * @param bool $recursive
132      * @return bool
133      */
134     static function createFolders($path, $mode = 0755, $recursive = true)
135     {
136         if (!is_dir($path)) {
137             return mkdir($path, $mode, $recursive);
138         }
139 
140         return true;
141     }
142 
143     /**
144      * 根据文件名创建文件
145      *
146      * @param string $file_name
147      * @param int $mode
148      * @param int $dir_mode
149      * @return bool
150      */
151     static function mkfile($file_name, $mode = 0644, $dir_mode = 0755)
152     {
153         if (!file_exists($file_name)) {
154             $file_path = dirname($file_name);
155             $createFolder = self::createFolders($file_path, $dir_mode, true);
156             if ($createFolder) {
157                 $fp = fopen($file_name, 'w+');
158                 if ($fp) {
159                     fclose($fp);
160                     chmod($file_name, $mode);
161                     return true;
162                 }
163             }
164 
165             return false;
166         }
167         return true;
168     }
169 
170     /**
171      * 验证电子邮件格式
172      *
173      * @param string $email
174      * @param string $add_valid_expr
175      * @return bool
176      */
177     static function validEmail($email, $add_valid_expr = "/^[a-zA-Z0-9]([\w\-\.]?)+/")
178     {
179         if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
180 
181             if ($add_valid_expr) {
182                 list($valid_string,) = explode('@', $email);
183                 if (!preg_match($add_valid_expr, $valid_string)) {
184                     return false;
185                 }
186             }
187 
188             return true;
189         }
190 
191         return false;
192     }
193 
194     /**
195      * 返回一个指定长度的随机数
196      *
197      * @param int $length
198      * @param int $numeric
199      * @return string
200      */
201     static function random($length, $numeric = 0)
202     {
203         $seed = md5(print_r($_SERVER, 1) . microtime(true));
204         if ($numeric) {
205             $seed = str_replace('0', '', base_convert($seed, 16, 10)) . '0123456789';
206         } else {
207             $seed = base_convert($seed, 16, 35) . 'zZz' . strtoupper($seed);
208         }
209 
210         $hash = '';
211         $max = strlen($seed) - 1;
212         for ($i = 0; $i < $length; $i++) {
213             $hash .= $seed[mt_rand(0, $max)];
214         }
215 
216         return $hash;
217     }
218 
219     /**
220      * 解析@到某某
221      *
222      * @param string $str
223      * @return array
224      */
225     static function parseAt($str)
226     {
227         preg_match_all("/@([^@^\\s^:]{1,})([\\s\\:\\,\\;]{0,1})/", $str, $result);
228         return $result;
229     }
230 
231     /**
232      * 过滤非法标签
233      *
234      * @param string $str
235      * @param string $disallowable
236      * @return mixed
237      */
238     static function stripSelectedTags($str, $disallowable = '<script><iframe><style><link>')
239     {
240         $disallowable = trim(str_replace(array('>', '<'), array('', '|'), $disallowable), '|');
241         $str = str_replace(array('&lt;', '&gt;'), array('<', '>'), $str);
242         $str = preg_replace("~<({$disallowable})[^>]*>(.*?<\s*\/(\\1)[^>]*>)?~is", '$2', $str);
243 
244         return $str;
245     }
246 
247     /**
248      * 转换html实体编码
249      *
250      * @param string $str
251      * @return string
252      */
253     static function convertTags($str)
254     {
255         return str_replace(array('<', '>', "'", '"'), array('&lt;', '&gt;', '&#039;', '&quot;'), $str);
256     }
257 
258     /**
259      * 字符串加密解密算法
260      *
261      * @param string $string
262      * @param string $operation
263      * @param string $key
264      * @param int $expiry
265      * @return string
266      */
267     static function authCode($string, $operation = 'DECODE', $key = 'crossphp', $expiry = 0)
268     {
269         $c_key_length = 4;
270         $key = md5($key);
271 
272         $key_a = md5(substr($key, 0, 16));
273         $key_b = md5(substr($key, 16, 16));
274         $key_c = $c_key_length ? ($operation == 'DECODE' ? substr($string, 0, $c_key_length) :
275             substr(md5(microtime()), -$c_key_length)) : '';
276 
277         $crypt_key = $key_a . md5($key_a . $key_c);
278         $key_length = strlen($crypt_key);
279 
280         $string = $operation == 'DECODE' ?
281             base64_decode(substr($string, $c_key_length)) :
282             sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $key_b), 0, 16) . $string;
283 
284         $result = array();
285         $box = range(0, 255);
286         $string_length = strlen($string);
287 
288         $rnd_key = array();
289         for ($i = 0; $i <= 255; $i++) {
290             $rnd_key[$i] = $crypt_key[$i % $key_length];
291         }
292         $rnd_key = array_map('ord', $rnd_key);
293 
294         for ($j = $i = 0; $i < 256; $i++) {
295             $j = ($j + $box[$i] + $rnd_key[$i]) % 256;
296             $tmp = $box[$i];
297             $box[$i] = $box[$j];
298             $box[$j] = $tmp;
299         }
300 
301         $p1 = $p2 = array();
302         for ($a = $j = $i = 0; $i < $string_length; $i++) {
303             $a = ($a + 1) % 256;
304             $j = ($j + $box[$a]) % 256;
305             $tmp = $box[$a];
306             $box[$a] = $box[$j];
307             $box[$j] = $tmp;
308             $p1[] = $string[$i];
309             $p2[] = $box[($box[$a] + $box[$j]) % 256];
310         }
311 
312         if (!empty($p1)) {
313             $p1 = array_map('ord', $p1);
314             foreach ($p1 as $k => $pv) {
315                 $result[] = $pv ^ $p2[$k];
316             }
317 
318             unset($p1, $p2, $box, $tmp, $rnd_key);
319             $result = implode('', array_map('chr', $result));
320         }
321 
322         if ($operation == 'DECODE') {
323             if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) &&
324                 substr($result, 10, 16) == substr(md5(substr($result, 26) . $key_b), 0, 16)
325             ) {
326                 return substr($result, 26);
327             } else {
328                 return '';
329             }
330         } else {
331             return $key_c . str_replace('=', '', base64_encode($result));
332         }
333     }
334 
335     /**
336      * 简单字符串加解密
337      *
338      * @param string $str
339      * @param string $key
340      * @param string $operation encode加密 其他任意字符解密
341      * @return string
342      */
343     static function encodeParams($str, $key, $operation = 'encode')
344     {
345         $result = '';
346         static $key_cache;
347         if (!isset($key_cache[$key])) {
348             $key_cache[$key] = md5($key);
349         }
350 
351         $key = $key_cache[$key];
352         if ($operation == 'encode') {
353             $str = (string)$str;
354         } else {
355             //校验数据完整性
356             //省略校验要解密的参数是否是一个16进制的字符串
357             $str_head = substr($str, 0, 5);
358             $str = substr($str, 5);
359             if ($str_head != substr(md5($str . $key), 9, 5)) {
360                 return $result;
361             }
362 
363             $str = pack('H*', $str);
364         }
365 
366         if (!$str) {
367             return $result;
368         }
369 
370         for ($str_len = strlen($str), $i = 0; $i < $str_len; $i++) {
371             $result .= chr(ord($str[$i]) ^ ord($key[$i % 32]));
372         }
373 
374         if ($operation == 'encode') {
375             $result = bin2hex($result);
376             $result = substr(md5($result . $key), 9, 5) . $result;
377         }
378 
379         return $result;
380     }
381 
382     /**
383      * 生成四层深度的路径
384      * <pre>
385      * 如 id = 31 拼成如下路径
386      * 000/00/00/31
387      * </pre>
388      *
389      * @param int $id
390      * @param string $path_name
391      * @return string
392      */
393     static function getPath($id, $path_name = '')
394     {
395         $id = (string)abs($id);
396         $id = str_pad($id, 9, '0', STR_PAD_LEFT);
397         $dir1 = substr($id, 0, 3);
398         $dir2 = substr($id, 3, 2);
399         $dir3 = substr($id, 5, 2);
400 
401         return $path_name . '/' . $dir1 . '/' . $dir2 . '/' . $dir3 . '/' . substr($id, -2) . '/';
402     }
403 
404     /**
405      * 发送一个curl请求
406      *
407      * @param string $url
408      * @param array|string $vars
409      * @param string $method
410      * @param int $timeout
411      * @param bool $CA
412      * @param string $cacert http://curl.haxx.se/ca/cacert.pem
413      * @return int|mixed|string
414      */
415     static function curlRequest($url, $vars = array(), $method = 'POST', $timeout = 10, $CA = false, $cacert = '')
416     {
417         $method = strtoupper($method);
418         $SSL = substr($url, 0, 8) == "https://" ? true : false;
419         if ($method == 'GET' && !empty($vars)) {
420             $params = is_array($vars) ? http_build_query($vars) : $vars;
421             $url = rtrim($url, '?');
422             if (false === strpos($url . $params, '?')) {
423                 $url = $url . '?' . ltrim($params, '&');
424             } else {
425                 $url = $url . $params;
426             }
427         }
428 
429         $ch = curl_init();
430         curl_setopt($ch, CURLOPT_URL, $url);
431         curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
432         curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout - 3);
433         curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
434         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
435         curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
436         curl_setopt($ch, CURLOPT_HTTPHEADER, array("X-HTTP-Method-Override: {$method}"));
437 
438         if ($SSL && $CA && $cacert) {
439             curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
440             curl_setopt($ch, CURLOPT_CAINFO, $cacert);
441             curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
442         } else if ($SSL && !$CA) {
443             curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
444             curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
445         }
446 
447         if ($method == 'POST' || $method == 'PUT') {
448             curl_setopt($ch, CURLOPT_POST, 1);
449             curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
450             curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); //避免data数据过长
451         }
452         $result = curl_exec($ch);
453         $error_no = curl_errno($ch);
454         if (!$error_no) {
455             $result = trim($result);
456         } else {
457             $result = $error_no;
458         }
459 
460         curl_close($ch);
461         return $result;
462     }
463 
464     /**
465      * htmlspecialchars 函数包装
466      *
467      * @param string $str
468      * @param int $quote_style
469      * @return string
470      */
471     static function escape($str, $quote_style = ENT_COMPAT)
472     {
473         return htmlspecialchars($str, $quote_style);
474     }
475 
476     /**
477      * 求概率 返回key
478      * <pre>
479      * array(
480      *  'a' => 60
481      *  'b' => 30
482      *  'c' => 10
483      * );
484      * </pre>
485      *
486      * @param array $array
487      * @return int|bool
488      */
489     static function arrayRandomRate(array $array)
490     {
491         asort($array);
492         $max = array_sum($array);
493         foreach ($array as $a_key => $a_value) {
494             $rand = mt_rand(0, $max);
495 
496             if ($rand <= $a_value) {
497                 return $a_key;
498             } else {
499                 $max -= $a_value;
500             }
501         }
502 
503         return false;
504     }
505 
506     /**
507      * 判断是否是中文字符串
508      *
509      * @param string $string
510      * @return bool
511      */
512     static function isChinese($string)
513     {
514         if (preg_match("/^[\\x{4e00}-\\x{9fa5}]+$/u", $string)) {
515             return true;
516         }
517 
518         return false;
519     }
520 
521     /**
522      * 验证是否是一个正确的手机号
523      *
524      * @param int $mobile
525      * @return bool
526      */
527     static function isMobile($mobile)
528     {
529         if (preg_match("/^1[3456789]\\d{9}$/", $mobile)) {
530             return true;
531         }
532 
533         return false;
534     }
535 
536     /**
537      * 校验身份证号码
538      *
539      * @param string $id_card
540      * @param bool|true $just_check_length 是否只校验长度
541      * @return bool
542      */
543     static function checkIDCard($id_card, $just_check_length = true)
544     {
545         //长度校验
546         $length_validate = preg_match('/^([\d]{17}[xX\d]|[\d]{15})$/', $id_card) === 1;
547         if ($just_check_length) {
548             return $length_validate;
549         }
550 
551         if (!$length_validate) {
552             return false;
553         }
554 
555         $city_code = array(
556             11 => true, 12 => true, 13 => true, 14 => true, 15 => true,
557             21 => true, 22 => true, 23 => true,
558             31 => true, 32 => true, 33 => true, 34 => true, 35 => true, 36 => true, 37 => true,
559             41 => true, 42 => true, 43 => true, 44 => true, 45 => true, 46 => true,
560             50 => true, 51 => true, 52 => true, 53 => true, 54 => true,
561             61 => true, 62 => true, 63 => true, 64 => true, 65 => true,
562             71 => true,
563             81 => true, 82 => true,
564             91 => true,
565         );
566 
567         //地区校验
568         if (!isset($city_code[$id_card[0] . $id_card[1]])) {
569             return false;
570         }
571 
572         //生成校验码
573         $make_verify_bit = function ($id_card) {
574             if (strlen($id_card) != 17) {
575                 return null;
576             }
577 
578             $factor = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
579             //校验码对应值
580             $verify_number_list = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
581             $checksum = 0;
582             for ($i = 0; $i < 17; $i++) {
583                 $checksum += $id_card[$i] * $factor[$i];
584             }
585 
586             $mod = $checksum % 11;
587             $verify_number = $verify_number_list[$mod];
588             return $verify_number;
589         };
590 
591         $id_card_length = strlen($id_card);
592         if ($id_card_length == 15) {
593             //超出百岁特殊编码
594             if (array_search(substr($id_card, 12, 3), array('996', '997', '998', '999')) !== false) {
595                 $id_card = substr($id_card, 0, 6) . '18' . substr($id_card, 6, 9);
596             } else {
597                 $id_card = substr($id_card, 0, 6) . '19' . substr($id_card, 6, 9);
598             }
599 
600             $id_card .= $make_verify_bit($id_card);
601         } else {
602             //校验最后一位
603             if (strcasecmp($id_card[17], $make_verify_bit(substr($id_card, 0, 17))) != 0) {
604                 return false;
605             }
606         }
607 
608         //校验出生日期
609         $birth_day = substr($id_card, 6, 8);
610         $d = new \DateTime($birth_day);
611         if ($d->format('Y') > date('Y') || $d->format('m') > 12 || $d->format('d') > 31) {
612             return false;
613         }
614 
615         return true;
616     }
617 
618     /**
619      * 加解密
620      *
621      * @param string $data
622      * @param string $op
623      * @param string $key
624      * @param string $method
625      * @return mixed|string
626      */
627     static function encrypt($data, $op = 'DECODE', $key = '!@#%c*r&o*s^s%p$h~p&', $method = 'AES-256-CBC')
628     {
629         $encrypt_key = md5($key);
630         if ($op == 'ENCODE') {
631             $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($method));
632             $encrypted = openssl_encrypt($data, $method, $encrypt_key, 0, $iv);
633             $result = str_replace(array('=', '/', '+'), array('', '-', '_'), base64_encode($encrypted . '::' . $iv));
634         } else {
635             $data = base64_decode(str_replace(array('-', '_'), array('/', '+'), $data));
636             list($encrypted, $iv) = explode('::', $data);
637             $result = openssl_decrypt($encrypted, $method, $encrypt_key, 0, $iv);
638         }
639 
640         return $result;
641     }
642 
643     /**
644      * 取得用户真实ip
645      *
646      * @return string
647      */
648     static function getIp()
649     {
650         return Request::getInstance()->getClientIPAddress();
651     }
652 
653     /**
654      * 返回IP的整数形式
655      *
656      * @param string $ip
657      * @return string
658      */
659     static function getLongIp($ip = '')
660     {
661         if ($ip == '') {
662             $ip = self::getIp();
663         }
664 
665         return sprintf("%u", ip2long($ip));
666     }
667 
668     /**
669      * 显示友好时间格式
670      *
671      * @param int $time 时间戳
672      * @param string $format
673      * @param int $start_time
674      * @param string $suffix
675      * @return string
676      */
677     static function ftime($time, $format = 'Y-m-d H:i:s', $start_time = 0, $suffix = '前')
678     {
679         if ($start_time == 0) {
680             $start_time = time();
681         }
682 
683         $t = $start_time - $time;
684         if ($t < 63072000) {
685             $f = array(
686                 '31536000' => '年',
687                 '2592000' => '个月',
688                 '604800' => '星期',
689                 '86400' => '天',
690                 '3600' => '小时',
691                 '60' => '分钟',
692                 '1' => '秒'
693             );
694 
695             foreach ($f as $k => $v) {
696                 if (0 != $c = floor($t / (int)$k)) {
697                     return $c . $v . $suffix;
698                 }
699             }
700         }
701 
702         return date($format, $time);
703     }
704 
705     /**
706      * 格式化数据大小(单位byte)
707      *
708      * @param int $size
709      * @return string
710      */
711     static function convert($size)
712     {
713         $unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
714         $s = floor(log($size, 1024));
715         $i = (int)$s;
716 
717         if (isset($unit[$i])) {
718             return sprintf('%.2f ' . $unit[$i], $size / pow(1024, $s));
719         }
720 
721         return $size . ' ' . $unit[0];
722     }
723 }
724 
CrossPHP API documentation generated by ApiGen