PHP项目中实用的14个自建通用函数详解

Leo
Leo
发布时间:2026-10-14| 5人浏览过
原创

在PHP Web开发中,封装通用的工具函数能显著减少重复代码并提高安全性。本文精选了项目中常用的14个自建函数,涵盖从安全的HTTP请求、数据加解密到字符串安全过滤等多场景操作,为开发者提供即插即用的代码解决方案。

HTTP接口请求与安全传输

在进行微服务或第三方API对接时,通常需要对参数进行序列化、编码及简单的签名校验,以确保数据传输的安全性。以下两个函数实现了带URL编码参数的POST请求及通用的可逆加密机制。

第1步:实现安全的CURL POST请求

该函数用于向指定URL发送POST数据。为了防止数据篡改,参数会先通过authcode进行加密和URL编码,同时自动附加当前时间戳作为时效验证。返回结果会被解析为关联数组,方便后续逻辑处理。

function getCurlDate($url, $datas, $key) {
    // 添加时间戳防止重放攻击,增加300秒有效期
    $datas['time'] = $_SERVER['REQUEST_TIME'] + 300;
    
    // 序列化数据并使用自定义密钥加密后URLEncode
    $post_data['post'] = urlencode(authcode(serialize($datas), "ENCODE", $key));
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    
    $output = curl_exec($ch);
    curl_close($ch);
    
    return json_decode($output, true);
}

第2步:配置可逆的加密解密函数 (authcode)

authcode是一个经典的RC4流密码变种实现,常用于Cookie加密或Token生成。它支持加密(ENCODE)和解密(DECODE),并可选地设置过期时间。在解密时,会自动校验时间戳和校验和,若失效或篡改则返回空值。

function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
    $ckey_length = 4;
    // 使用MD5生成固定长度的密钥段
    $key = md5($key ? $key : '^www.itokit.com$');
    $keya = md5(substr($key, 0, 16));
    $keyb = md5(substr($key, 16, 16));
    
    // 解密时截取前4位验证码,加密时截取随机码最后4位
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
    
    $cryptkey = $keya . md5($keya . $keyc);
    $key_length = strlen($cryptkey);
    
    // 构造待处理字符串:含时间戳(10位)+校验位(16位)+原始内容
    $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);
    
    // 密钥混排算法 (KSA)
    $rndkey = array();
    for ($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }
    
    // PRGA伪随机流生成
    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 {
        // 去除base64中的等号以增强URL安全性
        return $keyc . str_replace('=', '', base64_encode($result));
    }
}

字符串安全过滤与转换

在处理用户输入和输出时,防止SQL注入和XSS攻击是核心任务。除了原生函数外,封装能够递归处理数组的深度过滤函数,能有效避免遗漏嵌套数据结构中的恶意字符。

第3步:深度处理反斜杠转义 (addslashes/stripslashes)

由于addslashes仅处理单层字符串,对于多维数组需递归调用。以下封装确保无论传入的是字符串还是数组,都能正确转义或还原特殊字符。

// 递归转义
function new_addslashes($string){
    if(!is_array($string)) return addslashes($string);
    foreach($string as $key => $val) $string[$key] = new_addslashes($val);
    return $string;
}

// 更简洁的替代方案
function addslashes_deep($string){
    return is_array($string) ? array_map('addslashes_deep', $string) : addslashes($string);
}

第4步:HTML特殊字符实体转换 (htmlspecialchars)

同样地,针对可能包含数组结构的数据,使用new_html_special_chars递归将尖括号等字符转换为HTML实体,防止XSS漏洞。

function new_html_special_chars($string) {
    if(!is_array($string)) return htmlspecialchars($string);
    foreach($string as $key => $val) $string[$key] = new_html_special_chars($val);
    return $string;
}

第5步:字符串与十六进制互转

在某些底层通信或二进制数据处理场景中,可能需要将文本转为Hex格式。这两个函数手动实现了字节级的位移运算,不依赖扩展库。

/**
 * 字符串转十六进制
 */
function str2hex($s) {
    $r = "";
    $hexes = array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
    for ($i=0; $i<strlen($s); $i++)
        $r .= ($hexes [(ord($s{$i}) >> 4)] . $hexes [(ord($s{$i}) & 0xf)]);
    return $r;
}

/**
 * 十六进制转字符串
 */
function hex2str($s) {
    $r = "";
    for ( $i = 0; $i<strlen($s); $i += 2) {
        $x1 = ord($s{$i});
        $x1 = ($x1>=48 && $x1<58) ? $x1-48 : $x1-97+10;
        $x2 = ord($s{$i+1});
        $x2 = ($x2>=48 && $x2<58) ? $x2-48 : $x2-97+10;
        $r .= chr((($x1 << 4) & 0xf0) | ($x2 & 0x0f));
    }
    return $r;
}

第6步:多维数组与字符串互相转换

string2array利用eval将Serialized格式的字符串还原为变量,而array2string则将数组转为安全的序列化字符串表示,注意这里使用了var_export配合addslashes以确保生成的字符串代码安全。

function string2array($data) {
    if($data == '') return array();
    eval("\$array = $data;");
    return $array;
}

function array2string($data, $isformdata = 1) {
    if($data == '') return '';
    if($isformdata) $data = new_stripslashes($data);
    return addslashes(var_export($data, TRUE));
}

文本处理与系统信息获取

除了安全相关操作,日常开发中还常涉及文件扩展名判断、IP地址识别、大字符串截断以及文件大小单位换算等功能。

第7步:精准获取客户端IP地址

考虑到CDN、代理服务器等情况,IP获取函数按优先级依次检查HTTP_CLIENT_IP、HTTP_X_FORWARDED_FOR和REMOTE_ADDR,并通过正则表达式提取合法的IPv4地址。

function ip() {
    if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
        $ip = getenv('HTTP_CLIENT_IP');
    } elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
        $ip = getenv('HTTP_X_FORWARDED_FOR');
    } elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
        $ip = getenv('REMOTE_ADDR');
    } elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    return preg_match ( '/[\d\.]{7,15}/', $ip, $matches ) ? $matches [0] : '';
}

第8步:支持UTF-8的多字节字符串截取

标准的substr在多字节编码(如UTF-8中文)下容易导致乱码。该函数通过遍历字节并根据ASCII值判断字符长度,准确截取指定宽度的字符串,并保留HTML实体不被破坏。

function str_cut($string, $length, $dot = '...') {
    $strlen = strlen($string);
    if($strlen <= $length) return $string;
    
    // 预处理HTML实体,防止被错误截断
    $string = str_replace(array(' ',' ','&','"',"'",''','"','—','<','>','·','…'), 
                          array('∵',' ','&','"',"'",'“','”','—','<','>','·','…'), $string);
    
    $strcut = '';
    if(strtolower(CHARSET) == 'utf-8') {
        $length = intval($length-strlen($dot)-$length/3);
        $n = $tn = $noc = 0;
        while($n < strlen($string)) {
            $t = ord($string[$n]);
            if($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) { $tn = 1; $n++; $noc++; }
            elseif(194 <= $t && $t <= 223) { $tn = 2; $n += 2; $noc += 2; }
            elseif(224 <= $t && $t <= 239) { $tn = 3; $n += 3; $noc += 2; }
            elseif(240 <= $t && $t <= 247) { $tn = 4; $n += 4; $noc += 2; }
            elseif(248 <= $t && $t <= 251) { $tn = 5; $n += 5; $noc += 2; }
            elseif($t == 252 || $t == 253) { $tn = 6; $n += 6; $noc += 2; }
            else { $n++; }
            if($noc >= $length) break;
        }
        if($noc > $length) $n -= $tn;
        $strcut = substr($string, 0, $n);
        // 还原HTML实体
        $strcut = str_replace(array('∵','&','"',"'",'“','”','—','<','>','·','…'), 
                              array(' ','&','"',"'",'“','”','—','<','>','·','…'), $strcut);
    } else {
        // GBK等双字节编码处理逻辑
        $dotlen = strlen($dot);
        $maxi = $length - $dotlen - 1;
        $current_str = '';
        $search_arr = array('&',' ','"',"'","'",'''','"','—','<','>','·','…','∵');
        $replace_arr = array('&',' ','"',"'","'",'''','"','—','<','>','·','…',' ');
        $search_flip = array_flip($search_arr);
        for ($i = 0; $i < $maxi; $i++) {
            $current_str = ord($string[$i]) > 127 ? $string[$i].$string[++$i] : $string[$i];
            if (in_array($current_str, $search_arr)) {
                $key = $search_flip[$current_str];
                $current_str = str_replace($search_arr[$key], $replace_arr[$key], $current_str);
            }
            $strcut .= $current_str;
        }
    }
    return $strcut.$dot;
}

第9步:文件扩展名提取与文件大小格式化

get_file_ext简单高效地提取文件后缀;sizecount则将字节大小自动转换为KB、MB或GB,并保留两位小数,便于前端展示。

function get_file_ext($pic) {
    return substr($pic, strrpos($pic, '.') + 1);
}

function sizecount($filesize) {
    if ($filesize >= 1073741824) {
        $filesize = round($filesize / 1073741824 * 100) / 100 .' GB';
    } elseif ($filesize >= 1048576) {
        $filesize = round($filesize / 1048576 * 100) / 100 .' MB';
    } elseif($filesize >= 1024) {
        $filesize = round($filesize / 1024 * 100) / 100 . ' KB';
    } else {
        $filesize = $filesize.' Bytes';
    }
    return $filesize;
}

第10步:生成随机字符串

用于生成验证码或临时令牌,默认仅包含数字,也可指定字符集。

function random($length, $chars = '0123456789') {
    $hash = '';
    $max = strlen($chars) - 1;
    for($i = 0; $i < $length; $i++) {
        $hash .= $chars[mt_rand(0, $max)];
    }
    return $hash;
}
以上就是PHP项目中常用通用自建函数的详细内容,更多关于PHP开发技巧与代码优化的资料请关注本站其它相关文章!
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。