一个PHP公共的工具类Tools.php


一个压箱底的,都是一些比较常用的静态函数,封到了一个类里面。

如果是thinkphp框架,建议放在/app/common/Tools.php下。

不断更新,最后更新时间见类的函数包最后面一行。

<?php
declare (strict_types=1);

namespace app\common;


class Tools
{


    /**
     * 私有拒绝构造
     */
    private function __construct()
    {
    }

    /**
     * 私有拒绝克隆
     */
    private function __clone()
    {
    }


    /**
     * 正则判断手机号码
     * @param unknown $str
     * @return boolean
     */
    public static function isMobile($str)
    {
        // 手机号码 '/^(\+86|86)?1[35678][0-9]{9}/';
        // IP '/^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})){3}$/';
        // 400电话 '/^(400)[016789][0-9]{6}/';
        // 中国座机 '/^(\+86|86|0)((\d{2}-\d{8})|(\d{3}-\d{7})|(\d{10}))/';
        // qq号 '/^\d{5,16}/';
        // HTML备注 '/<!--.*-->/U';
        return (preg_match('/^(\+86|86)?1[3456789][0-9]{9}$/', $str)) ? TRUE : FALSE;
    }


    /**
     * 是否电话号码
     * @param unknown $str
     * @return boolean
     */
    public static function isTelephone($str)
    {
        return (preg_match('/^(\+86|86|0)((\d{2}-\d{8})|(\d{3}-\d{7})|(\d{10}))$/', $str)) ? TRUE : FALSE;
    }


    /**
     * 是否ip判断
     * @param unknown $str
     * @return boolean
     */
    public static function isIp($str)
    {
        $regular = '/^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})){3}$/';
        return (preg_match($regular, $str)) ? TRUE : FALSE;
    }


    /**
     * 是否email判断
     * @param unknown $str
     * @return boolean
     */
    public static function isEmail($str)
    {
        return (preg_match("/^([0-9A-Za-z\\-_\\.]+)@([0-9a-z]+\\.[a-z]{2,3}(\\.[a-z]{2})?)$/i", $str)) ? TRUE : FALSE;
    }


    /**
     * 是否登录帐号
     * @return boolean
     */
    public static function isAccount($str)
    {
        return (preg_match("/^[a-zA-Z][0-9a-zA-Z_\s]+$/", $str)) ? TRUE : FALSE;
    }


    /**
     * 获取客户端ip
     * @param unknown $str
     * @return string
     */
    public static function ip()
    {
        //建议使用Request::$client_ip
        $ip = '';
        if (getenv("HTTP_CLIENT_IP"))
            $ip = getenv("HTTP_CLIENT_IP");
        else if (getenv("HTTP_X_FORWARDED_FOR"))
            $ip = getenv("HTTP_X_FORWARDED_FOR");
        else if (getenv("REMOTE_ADDR"))
            $ip = getenv("REMOTE_ADDR");
        return $ip;
    }


    /**
     * 获取客户端浏览器代理agent
     * @param string $str useless
     * @return unknown
     */
    public static function ua($type = 'normal')
    {
        //建议使用:Request::$user_agent 或Request::user_agent(['platform','mobile'])
        //name-version
        if (empty($_SERVER['HTTP_USER_AGENT'])) {
            return 'UserAgentNull';//当浏览器没有发送访问者的信息的时候
        }
        $agent = $_SERVER['HTTP_USER_AGENT'];
        $name = $vers = '';
        if (preg_match('/MSIE\s(\d+)\..*/i', $agent, $regs)) {
            $name = 'IE';
            $vers = isset($regs[1]) ? $regs[1] : '';
        } elseif (preg_match('/FireFox\/(\d+)\..*/i', $agent, $regs)) {
            $name = 'FireFox';
            $vers = isset($regs[1]) ? $regs[1] : '';
        } elseif (preg_match('/Opera[\s|\/](\d+)\..*/i', $agent, $regs)) {
            $name = 'Opera';
            $vers = isset($regs[1]) ? $regs[1] : '';
        } elseif (preg_match('/Chrome\/(\d+)\..*/i', $agent, $regs)) {
            $name = 'Chrome';
            $vers = isset($regs[1]) ? $regs[1] : '';
        } elseif ((strpos($agent, 'Chrome') == false) && preg_match('/Safari\/(\d+)\..*$/i', $agent, $regs)) {
            $name = 'Safari';
            $vers = isset($regs[1]) ? $regs[1] : '';
        }
        $name = $name === '' ? 'x' : $name;
        $vers = $vers === '' ? '0' : $vers;

        if ($name === 'x') {
            $bot = false;//if agent is spider
            $ua = addslashes(strtolower($_SERVER['HTTP_USER_AGENT']));
            if (strpos($ua, 'googlebot') !== false) {
                $bot = 'Google';
            } elseif (strpos($ua, 'mediapartners-google') !== false) {
                $bot = 'Google Adsense';
            } elseif (strpos($ua, 'baiduspider') !== false) {
                $bot = 'Baidu';
            } elseif (strpos($ua, 'sogou spider') !== false) {
                $bot = 'Sogou';
            } elseif (strpos($ua, 'sogou web') !== false) {
                $bot = 'Sogou web';
            } elseif (strpos($ua, 'sosospider') !== false) {
                $bot = 'SOSO';
            } elseif (strpos($ua, '360spider') !== false) {
                $bot = '360Spider';
            } elseif (strpos($ua, 'yahoo') !== false) {
                $bot = 'Yahoo';
            } elseif (strpos($ua, 'msn') !== false) {
                $bot = 'MSN';
            } elseif (strpos($ua, 'msnbot') !== false) {
                $bot = 'msnbot';
            } elseif (strpos($ua, 'sohu') !== false) {
                $bot = 'Sohu';
            } elseif (strpos($ua, 'yodaoBot') !== false) {
                $bot = 'Yodao';
            } elseif (strpos($ua, 'twiceler') !== false) {
                $bot = 'Twiceler';
            } elseif (strpos($ua, 'ia_archiver') !== false) {
                $bot = 'Alexa_';
            } elseif (strpos($ua, 'iaarchiver') !== false) {
                $bot = 'Alexa';
            } elseif (strpos($ua, 'yisouspider') !== false) {
                $bot = 'Yisou';
            } elseif (strpos($ua, 'jikespider') !== false) {
                $bot = 'Jike';
            } elseif (strpos($ua, 'bingbot') !== false) {
                $bot = 'Bingbot';
            } elseif (strpos($ua, 'slurp') !== false) {
                $bot = 'Yahoo slurp';
            } elseif (strpos($ua, 'bot') !== false) {
                $bot = 'otRobot';
            } elseif (strpos($ua, 'spider') !== false) {
                $bot = 'otSpider';
            }
            if ($bot !== false) {
                return 'Spider:' . $bot;
            }
        }

        return $name . ' ' . $vers;
    }


    /**
     * 获取设备类型
     * web/wap/weixin/alipay etc...
     * @return string
     */
    public static function device()
    {
        //建议组合使用:Request::user_agent(['mobile'])
        $agent = Arr::get($_SERVER, 'HTTP_USER_AGENT');
        if (preg_match('/Mobile/i', $agent) and preg_match('/MicroMessenger/i', $agent)) {
            return 'weixin';
        }
        if (preg_match('/AlipayClient/i', $agent)) {
            return "alipay";
        }
        if (preg_match('/Mobile/i', $agent)) {
            return 'wap';
        }
        return 'web';
    }


    /**
     * 对象转数组,使用get_object_vars返回对象属性组成的数组
     */
    public static function objectToArray($data)
    {
        if (is_object($data)) {
            $res = array();
            foreach ($data as $k => $v) {
                $res[$k] = self::objectToArray($v);
            }
            return count($res) > 0 ? $res : $data;
        }
        return $data;
        /*
        $arr = is_object($obj) ? get_object_vars($obj) : $obj;
        if(is_array($arr)){
            return array_map(__FUNCTION__, $arr);
        }
        return $arr;
         */
    }

    /**
     * 数组转对象
     * @param unknown $arr
     * @return StdClass|unknown
     */
    public static function arrayToObject($data)
    {
        if (is_array($data)) {
            $res = new stdClass();
            foreach ($data as $k => $v) {
                $res->$k = self::arrayToObject($v);
            }
            return $res;
        }
        return $data;

        /*
        if(is_array($arr)){
            return (object)array_map(__FUNCTION__, $arr);
        }
        return $arr;
         */
    }

    /**
     * 递归转换json为数组
     */
    public static function jsonToArray($data)
    {
        if (is_string($data) and is_array(json_decode($data, true))) {
            $data = json_decode($data, true);
            foreach ($data as $k => $v) {
                $data[$k] = self::jsonToArray($v);
            }
        }
        return $data;
    }


    /**
     * 字符串二进制base64编码转数组或对象,失败就FALSE
     * @param base64 $str base64编码的串
     * @param boolean $fa 需要对象此项为空需要数组为TRUE
     * @return mixed|boolean
     */
    public static function base64Decode($str, $fa = FALSE)
    {
        if ($str == base64_encode(base64_decode($str))) {
            $str = base64_decode($str);
            $res = $fa ? json_decode($str, TRUE) : json_decode($str);
            if (json_last_error() == JSON_ERROR_NONE) {
                return $res;
            }
        }
        return FALSE;
    }

    /**
     * 字符串或数组变成base64编码,失败就FALSE
     * @param base64 $data 数组或字符串
     * @return mixed|boolean
     */
    public static function base64Encode($data)
    {
        try {
            if (is_array($data)) {
                $data = json_encode($data);
            }
            $str = base64_encode($data);
            if (self::base64Decode($str) !== FALSE) {
                return $str;
            }
        } catch (\Exception $e) {
            //
        }
        return FALSE;
    }

    /**
     * 判断是否异步请求
     * @return boolean
     */
    public static function isAjax()
    {
        //Request::initial()->is_ajax()
        if (isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && strtolower($_SERVER["HTTP_X_REQUESTED_WITH"]) == "xmlhttprequest") {
            return TRUE;
        }
        return FALSE;
    }


    /**格式为可视化时间
     * @param null $time 时间戳或datetime
     * @param int $type
     * @param string $default
     * @return false|string
     */
    public static function seeTime($time = null, $type = null, $default = '-')
    {
        if (empty($time)) {
            //return $time === null ? date('Y-m-d H:i:s') : $default;从未登录的情况是null
            return $default;
        }
        if (!is_numeric($time)) {
            $time = strtotime($time);
        }
        $timestamp = intval($time);
        if ($timestamp <= 0) {
            return $default;
        }

        //$result = '';
        switch ($type) {
            case 1 :
                //默认的,例如:2013-11-02 17:34:32
                $result = date('Y-m-d H:i:s', $timestamp);
                break;
            case 2 :
                //
                $result = date('Y年m月d日 H时i分s秒', $timestamp);
                break;
            case 3 ://
                $result = date('Y年m月d日 H时i分', $timestamp);
                break;
            case 4 ://
                $result = date('Y年m月d日', $timestamp);
                break;
            case 5 ://
                $result = date('Y年m月', $timestamp);
                break;
            case 6 ://
                $result = date('Y年', $timestamp);
                break;
            case 7 ://
                $result = date('Y-m-d', $timestamp);
                break;
            case 8 ://
                $result = date('Y-m', $timestamp);
                break;
            default :
                //最经典的,较旧的时间:只时分,无秒,例如:2013-11-02 17:34
                $today = date('G') * 3600 + date('i') * 60 + date('s'); //今天过了多少秒
                $nowTime = time();
                $residue = $nowTime % $timestamp;
                if ($residue < 60) {
                    $result = ($residue == 0) ? '刚刚' : $residue . '秒前';
                } elseif ($residue < 3600) {
                    $result = floor($residue / 60) . '分钟前';
                } elseif ($residue <= $today) {
                    $result = '今天' . date('H:i', $timestamp);
                } elseif ($residue > $today && $residue < $today + 86400) {
                    $result = '昨天' . date('H:i', $timestamp);
                } elseif (date('Y', $timestamp) == date('Y')) {
                    $result = date('m-d H:i', $timestamp);
                } else {
                    $result = date('Y-m-d H:i', $timestamp);
                }
                break;
        }
        return $result;
    }

    /**
     * 可逆加密解密算法
     * @param unknown $string 加密的串
     * @param string $operation ENCODE|DECODE
     * @param string $key 混肴值
     * @param number $expiry 失效秒数
     * @return string
     */
    public static function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0)
    {
        $ckey_length = 4;
        $keyp = defined('AUTHKEYP') ?? Cookie::$salt;
        $key = md5($key ? $key : $keyp);
        $keya = md5(substr($key, 0, 16));
        $keyb = md5(substr($key, 16, 16));
        $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
        $cryptkey = $keya . md5($keya . $keyc);
        $key_length = strlen($cryptkey);
        $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
        $string_length = strlen($string);
        $result = '';
        $box = range(0, 255);
        $rndkey = array();
        for ($i = 0; $i <= 255; $i++) {
            $rndkey[$i] = ord($cryptkey[$i % $key_length]);
        }
        for ($j = $i = 0; $i < 256; $i++) {
            $j = ($j + $box[$i] + $rndkey[$i]) % 256;
            $tmp = $box[$i];
            $box[$i] = $box[$j];
            $box[$j] = $tmp;
        }
        for ($a = $j = $i = 0; $i < $string_length; $i++) {
            $a = ($a + 1) % 256;
            $j = ($j + $box[$a]) % 256;
            $tmp = $box[$a];
            $box[$a] = $box[$j];
            $box[$j] = $tmp;
            $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
        }
        if ($operation == 'DECODE') {
            if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
                return substr($result, 26);
            } else {
                return '';
            }
        } else {
            return $keyc . str_replace('=', '', base64_encode($result));
        }
        return '';
    }

    /**
     * bsykc-获取在一定空间和时间内的唯一序列号
     * HELP::seriesNumber(16,'input');
     * @param number $len 长度
     * @param string $type 类型
     * @param string $prefix 前缀
     * @return string
     * @since 20170608
     */
    public static function seriesNumber($length = 32, $type = '', $prefix = '')
    {
        $sn = '';/* 选择一个随机的方案 */
        switch ($type) {
            case 'input'://被输入的全大写,不允许有I1O0
                //62个字符0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
                $str = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';//32种子
                $prelen = strlen($prefix);
                if ($prelen > 0) {
                    $sn = $prefix;
                    $length -= $prelen;
                }
                for ($i = 0; $i < $length; $i++) {
                    $sn .= substr($str, rand(0, 31), 1);
                }
                break;

            case 'share':
                $sn = rand(100, 999);
                break;

            case 'token':
                $sn = md5(uniqid());
                break;

            default://32位以时间为主轴的(充值或订单)序列号
                list($usec, $sec) = explode(" ", microtime());
                //$sn .= date($length < 32 ? 'ymdHis' : 'YmdHis');
                $sn .= date('YmdHis');
                $sn .= ceil(($usec + rand(1, 9)) * 1000000);
                $sn .= mt_rand(1000000, 9999999);
                $sn .= rand(1000, 9999);
                for ($i = strlen($sn); $i < $length; $i++) {
                    $sn .= substr(rand(1000, 9999), 0, 1);
                }
                $sn = substr($sn, 0, $length);
                break;
        }
        return $sn;
    }

    /**
     * 根据类型获取时间戳范围
     * 1:今日/2:昨日/3:本周/4:上周/5:本月/6:上月/7:本年度/8:上年度
     * 缺省:今日
     * @param int $type
     * @return array 0=starttime,1=endtime
     */
    public static function timeRange($type)
    {
        $starttime = 0;
        $endtime = 1;
        switch ($type) {
            case 2:
                $starttime = strtotime(date('Y-m-d 00:00:00', strtotime('-1 day')));
                $endtime = strtotime(date('Y-m-d 23:59:59', strtotime('-1 day')));
                break;
            case 3:
                $starttime = mktime(0, 0, 0, date("m"), date("d") - date("w") + 1, date("Y"));;
                $endtime = time();
                break;
            case 4:
                $starttime = strtotime(date('Y-m-d 00:00:00', strtotime('last Sunday')));
                $endtime = strtotime(date('Y-m-d H:i:s', strtotime('last Sunday') + 7 * 24 * 3600 - 1));
                break;
            case 5:
                $starttime = strtotime(date('Y-m-01 00:00:00', time()));
                $endtime = time();
                break;
            case 6:
                $starttime = strtotime(date('Y-m-01 00:00:00', strtotime('-1 month')));
                $endtime = strtotime(date('Y-m-31 23:59:00', strtotime('-1 month')));
                break;
            case 7:
                $starttime = strtotime(date("Y") . "-1" . "-1");
                $endtime = strtotime(date("Y") . "-12" . "-31");
                break;
            case 8:
                $starttime = mktime(0, 0, 0, 1, 1, date('Y', strtotime('-1 year', time())));
                $endtime = mktime(0, 0, 0, 12, 31, date('Y', strtotime('-1 year', time())));
                break;
            default:
                $starttime = strtotime(date('Y-m-d 00:00:00'));
                $endtime = strtotime(date('Y-m-d 23:59:59'));
                break;
        }
        return array($starttime, $endtime);
    }


    /**
     * 按星期获取起止日期时间戳
     * 1:周一/2:周二/3:周三/4:周四/5:周五/6:周六/7:周日
     * 缺省:无
     * @param unknown $day
     * @return multitype:number
     */
    public static function weekRange($day)
    {
        $starttime = 0;
        $endtime = 1;
        switch ($day) {
            case 1:
                $starttime = mktime(0, 0, 0, date("m"), date("d") - date("w") + 1, date("Y"));
                $endtime = mktime(23, 59, 59, date("m"), date("d") - date("w") + 1, date("Y"));
                break;
            case 2:
                $starttime = mktime(0, 0, 0, date("m"), date("d") - date("w") + 2, date("Y"));
                $endtime = mktime(23, 59, 59, date("m"), date("d") - date("w") + 2, date("Y"));
                break;
            case 3:
                $starttime = mktime(0, 0, 0, date("m"), date("d") - date("w") + 3, date("Y"));
                $endtime = mktime(23, 59, 59, date("m"), date("d") - date("w") + 3, date("Y"));
                break;
            case 4:
                $starttime = mktime(0, 0, 0, date("m"), date("d") - date("w") + 4, date("Y"));
                $endtime = mktime(23, 59, 59, date("m"), date("d") - date("w") + 4, date("Y"));
                break;
            case 5:
                $starttime = mktime(0, 0, 0, date("m"), date("d") - date("w") + 5, date("Y"));
                $endtime = mktime(23, 59, 59, date("m"), date("d") - date("w") + 5, date("Y"));
                break;
            case 6:
                $starttime = mktime(0, 0, 0, date("m"), date("d") - date("w") + 6, date("Y"));
                $endtime = mktime(23, 59, 59, date("m"), date("d") - date("w") + 6, date("Y"));
                break;
            case 7:
                $starttime = mktime(0, 0, 0, date("m"), date("d") - date("w") + 7, date("Y"));
                $endtime = mktime(23, 59, 59, date("m"), date("d") - date("w") + 7, date("Y"));
                break;
        }
        return array($starttime, $endtime);
    }

    /**
     * 获取大数值的缩写
     * @param float $num 数值
     * @since 20170823
     */
    public static function seeNum($num)
    {
        if (!is_numeric($num)) {
            return $num;
        }

        if ($num > 1000 and $num < 100000) {
            //大于0.1万小于100万
            return round($num / 10000, 2) . '万';
        } elseif ($num >= 100000 and $num < 10000000) {
            //大于10万小于100万
            return round($num / 10000, 1) . '万';
        } elseif ($num >= 10000000 and $num < 100000000) {
            //大于10万小于100万
            return round($num / 10000) . '万';
        } elseif ($num >= 100000000) {
            //大于1亿
            return round($num / 100000000, 2) . '亿';
        }
        return $num;
    }

    /**
     * 递归创建文件夹(慎用)
     * @param string $directory
     * @param number $chmod
     * @return boolean
     */
    public static function mkdir($directory, $chmod = 0644)
    {
        return (is_dir($directory) AND is_writable($directory))
            OR (
                self::mkdir(dirname($directory), $chmod)
                AND (
                    mkdir($directory, 0777) OR chmod($directory, $chmod)
                )
            );
    }

    /**
     * 传入文件字节数返回可视化大小
     * @param unknown $size
     */
    public static function seeSize($size)
    {

        if (!is_numeric($size)) {
            return '-';
        }

        if ($size < 10) {
            return $size . 'B';
        } elseif ($size < 10000) {
            return round($size / 1000, 2) . 'KB';
        } elseif ($size < 1000000000) {
            return round($size / 1000000, 2) . 'MB';
        } else {
            return round($size / 1000000000, 2) . 'GB';
        }
    }

    /**
     * 清除html格式为有换行的纯文本
     * @param unknown $str
     */
    public static function clearHtml($str)
    {
        $str = trim(html_entity_decode(strip_tags($str, '<div><p><br>')));
        $str = preg_replace('/\<\/?(p|br|div)[^\>]*\>/i', "\n", $str);
        $str = trim(preg_replace('/[\n]{2,}/', "\n", $str), "\n");
        return $str;
    }


    /**
     * 判断字符串是否可转化为json
     * @param $str
     * @return bool
     */
    public static function isJson($str)
    {
        $data = json_decode($str);
        if (($data and is_object($data)) or (is_array($data) and !empty($data))) {
            //if ($data and is_object($data)) {
            return true;
        }
        return false;
    }


    /**
     * 获取绝对数字,哪怕传入的是字符串
     * @param $pk 数字或字符串
     * @param $salt 附加值
     * @return mixed 返回一个关联integer
     */
    public static function fixedNumber($pk, string $salt = ''): int
    {
        if (is_int($pk)) {
            return $pk;//若是整型直接返回
        }
        $m1 = md5(strval($pk));
        $m2 = md5($m1 . strval($pk) . $salt);
        preg_match_all('/\d+/', $m1 . $m2, $match);//dump(array_sum(current($match)));
        return (int)array_sum(current($match));
    }


    /**
     * 传入版本字符串返回百进制版本整数
     * @param $name
     * @return float|int
     */
    public static function appInteger($name)
    {
        $va = explode('.', $name);//dump($va);
        if (count($va) != 3) {
            return 10000;
        }
        $newer = intval($va[0]) * 10000;
        $newer += intval($va[1]) * 100;
        $newer += intval($va[2]);
        return $newer;
    }


    /**
     * 产生一个token令牌
     * @param string $salt
     * @return string
     */
    public static function token($salt = '')
    {
        return md5($salt . uniqid() . time());
    }


    /**
     * 从md5数据里面提取数字,来作为验证码,默认生成4位数字
     * @param int $length
     * @param string $keyword
     * @return string
     */
    public static function timecode($length = 4, $keyword = '')
    {
        $str = md5($keyword . time());
        $leng = 32;
        $code = '';
        $count = 0;

        for ($i = 3; $i < $leng; $i++) {
            $c = substr($str, $i, 1);
            if ($c >= '0' && $c <= '9') {
                $code = $code . $c;
                $count++;
                if ($count >= $length) {
                    break;
                }
            }
        }
        return $code;
    }


    /**
     * 发起一个http请求
     */
    public static function curl($url, $method = 'GET', array $data = [], $options = [])
    {
        $ch = curl_init();//句柄
        if ($method == 'POST') {
            curl_setopt($ch, CURLOPT_POST, 1);//post提交方式
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data, JSON_UNESCAPED_UNICODE));
        } else {
            $url .= '?' . http_build_query($data);
        }

        //配置是json的payload提交形式
        if (isset($options['json']) and $options['json'] === true) {
            $header = [
                'Content-Type: application/json; charset=utf-8',
                'Content-Length:' . strlen(json_encode($data, JSON_UNESCAPED_UNICODE))
            ];
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        } else {
            curl_setopt($ch, CURLOPT_HTTPHEADER, ["x-sdk-client" => "php/2.0.0"]);
        }

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        if (substr($url, 0, 5) == 'https') {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }

        $rtn = curl_exec($ch);

        if ($rtn === false) {
            // 大多由设置等原因引起,一般无法保障后续逻辑正常执行,
            // 所以这里触发的是E_USER_ERROR,会终止脚本执行,无法被try...catch捕获,需要用户排查环境、网络等故障
            trigger_error("[CURL_" . curl_errno($ch) . "]: " . curl_error($ch), E_USER_ERROR);
        }
        curl_close($ch);
        return $rtn;//纯洁的返回
    }


    /**
     * 传入类对象返回点号隔开的命名空间
     * @param $class
     * @param string $suffix1 可选后缀
     * @param string $suffix2 可选二次唯一
     * @return mixed|string
     */
    public static function ns()
    {
        $args = func_get_args();
        $ns = '';
        foreach ($args as $item) {
            $ns .= str_replace('\\', '.', strval($item));
            $ns .= '.';
        }
        return $ns ?: 'app.common.Tools.ns.null.';
    }


    /**
     * 获取不重复字符串
     */
    public static function uuid()
    {
        return strrev(strtoupper(uniqid()));//?且没有0OIl之类?
    }

    /**
     * 清除所有中英文符号(pure为真则连空格都不要)
     */
    public static function clearSymbol($str, $pure = false)
    {
        $chars = "。、!?:;﹑•"…‘’“”〝〞∕¦‖— 〈〉﹞﹝「」‹›〖〗】【»«』『〕〔》《﹐¸﹕︰﹔!¡?¿﹖﹌﹏﹋";
        $chars .= "'´ˊˋ―﹫︳︴¯_ ̄﹢﹦﹤‐­˜﹟﹩﹠﹪﹡﹨﹍﹉﹎﹊ˇ︵︶︷︸︹︿﹀︺︽︾ˉ﹁﹂﹃﹄︻︼()";//中文标点
        $pattern = array("/[[:punct:]]/i", '/[' . $chars . ']/u', '/[ ]{2,}/');//英文标点符号,中文标点符号
        if ($pure) {
            return preg_replace($pattern, '', $str);
        }
        return preg_replace($pattern, ' ', $str);
    }


}//last.20201203

原文链接:https://blog.yongit.com/note/763090.html