kode / tools
PHP8.1+通用工具包,包含消息体、数组处理、字符串处理、时间处理、加解密、IP、地理计算、Curl、二维码、全局辅助函数等
Package info
pkg:composer/kode/tools
Fund package maintenance!
v1.8.5
2026-07-29 04:14 UTC
Requires
- php: >=8.1
- ext-bcmath: *
- ext-gd: *
- ext-json: *
- ext-mbstring: *
- ext-openssl: *
- endroid/qr-code: ^6.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.20
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.0
README
简介
这是一个基于PHP8.1+特性开发的模块化通用工具包,提供了消息体、数组处理、字符串处理、时间处理、加解密、IP地址处理、地理计算、HTTP请求、二维码生成、安全工具、全局辅助方法等功能。支持对象和静态两种调用方式。
安装
composer require kode/tools
消息体模块
特性
- ✅ 灵活的链式调用(code/data/msg等方法可任意顺序调用)
- ✅ 默认200状态码,默认消息"成功"
- ✅ 支持动态添加任意字段(page/name/total等)
- ✅ 内置状态码映射(HTTP标准码+业务码)
- ✅ 支持自定义状态码映射
- ✅ XSS防护(可选)
- ✅ 危险方法名防护
快速开始
use Kode\Message\Message; // (new Message) 与 Message:: 完全等价 // 默认200,msg="成功" (new Message)->result(); Message::result(); // 结果: ['code' => 200, 'msg' => '成功'] // 指定状态码和消息 Message::code(20001)->msg('请求数据有误')->result(); // 结果: ['code' => 20001, 'msg' => '请求数据有误'] // 传入data数据(无data不显示data字段) Message::data(['id' => 1])->result(); // 结果: ['code' => 200, 'msg' => '成功', 'data' => ['id' => 1]] // 链式调用位置不约束 Message::data(['id' => 1])->code(20001)->msg('请求数据有误')->result(); // 结果: ['code' => 20001, 'msg' => '请求数据有误', 'data' => ['id' => 1]] // 动态添加任意字段 Message::data(['id' => 1])->page(1)->name('张三')->result(); // 结果: ['code' => 200, 'msg' => '成功', 'data' => ['id' => 1], 'page' => 1, 'name' => '张三'] // 动态字段支持委托 Str/Arr/Time/Math/Geo/Ip 等静态方法(多参数自动计算) Message::mbStrcut('张三你吃了吗', 0, 6)->result(); // 结果: ['code' => 200, 'msg' => '成功', 'mbStrcut' => '张三']
方法说明
| 方法 | 说明 | 示例 |
|---|---|---|
Message::result() |
返回结果数组,默认code=200, msg="成功" | Message::result() |
Message::code(int $code) |
设置状态码 | Message::code(400) |
Message::msg(string $msg) |
设置消息文本 | Message::msg('成功') |
Message::data(mixed $data) |
设置数据(可选,null时不输出) | Message::data(['id' => 1]) |
Message::toArray() |
result() 的别名 |
Message::toArray() |
Message::toJson(int $options) |
返回 JSON 字符串 | Message::toJson() |
Message::sanitize(bool $enabled) |
是否开启 XSS 过滤(默认true) | Message::sanitize(false) |
Message::page(int $page) |
设置页码(动态字段示例) | Message::page(1) |
Message::total(int $total) |
设置总数(动态字段示例) | Message::total(100) |
Message::loadCodes(string $path) |
从文件加载状态码 | Message::loadCodes('config/codes.php') |
Message::codes(array $codes) |
合并自定义状态码 | Message::codes([800000 => '自定义错误']) |
Message::getAllCodes() |
获取全部状态码映射 | Message::getAllCodes() |
Message::clearCodes() |
清空自定义状态码 | Message::clearCodes() |
内置状态码
// HTTP标准码 200 => 'OK', 400 => 'Bad Request', 401 => 'Unauthorized', 403 => 'Forbidden', 404 => 'Not Found', 500 => 'Internal Server Error' // 业务码 300000 => 'Token无效', 300001 => 'Token已过期', 400000 => '参数错误', 500000 => '数据库错误'
加解密模块
特性
- ✅ AES-256-GCM加密
- ✅ Sodium和OpenSSL双引擎自动切换
- ✅ MD5/SHA系列哈希(支持加盐)
- ✅ 密码哈希和验证
- ✅ HMAC签名
- ✅ UUID/Token/邀请码/验证码生成
快速开始
use Kode\Crypto\Crypto; // AES加密解密(密钥至少16字符) $crypto = new Crypto('mykey1234567890ab'); // 17字符密钥 $encrypted = $crypto->encrypt('敏感数据'); // 加密结果: JeB6LDA+LM9Yu87injOYd0ToSPfb4f/XBcEv7/qI6TWDczdBd3... $decrypted = $crypto->decrypt($encrypted); // 解密结果: 敏感数据 // 特殊字符/中文/emoji完全支持 $crypto->encrypt('你好世界 🌍'); // 加密结果: DKJaDjUoVt8mHZHlNba/XKk1pRY9dYV23kR2FTPkhnq69Er2OP... // MD5哈希(加盐) Crypto::md5('123456', 'salt'); // 结果: 2e4475e67a7d80f8c1e5c3f5e5c3a8f5 // 密码哈希 $hash = Crypto::passwordHash('123456'); // 结果: $2y$10$LQv3c1yqBwe...(随机哈希) Crypto::passwordVerify('123456', $hash); // 结果: true // UUID/Token生成 Crypto::uuid(); // 结果: 58d1b3c9-5ec4-4356-8007-e7ec469d1dae Crypto::token(32); // 结果: 89eb2398743a88f5fdcf33c727242a3d // HMAC签名 Crypto::hmac('数据', '密钥', 'sha256'); // 结果: 3d5f8e2b1a9c4d7e6f8a3b2c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f
特殊字符支持
加解密功能完美支持以下特殊字符:
| 类型 | 示例 | 支持状态 |
|---|---|---|
| 中文 | 你好世界 |
✅ 完全支持 |
| Emoji | 😀🎉🚀 |
✅ 完全支持 |
| 特殊符号 | !@#$%^&*()_+-=[]{} |
✅ 完全支持 |
| HTML标签 | <script>alert("xss")</script> |
✅ 完全支持 |
| JSON字符串 | {"key":"value"} |
✅ 完全支持 |
| 多行文本 | 第一行\n第二行\r\n |
✅ 完全支持 |
| 空字符 | 前端\0后端 |
✅ 完全支持 |
| SQL注入 | '; DROP TABLE users; -- |
✅ 完全支持 |
加密引擎
自动检测并选择最优加密引擎:
| 引擎 | 算法 | 说明 |
|---|---|---|
| Sodium (推荐) | AES-256-GCM | 优先使用(PHP8.5+) |
| Sodium Fallback | ChaCha20-Poly1305 | Sodium不支持AES-GCM时自动切换 |
| OpenSSL | AES-256-GCM | Sodium不可用时使用 |
输出模式
| 模式 | 说明 | 适用场景 |
|---|---|---|
MODE_STANDARD |
标准Base64 | 默认,数据存储 |
MODE_URL_SAFE |
URL安全Base64 | URL参数传输 |
MODE_COMPACT |
十六进制 | 日志记录、调试 |
URL传输加解密
URL传输时需要使用MODE_URL_SAFE模式,避免+/=等字符被URL编码:
use Kode\Crypto\Crypto; // 创建URL安全加密实例 $crypto = new Crypto('your_secret_key_16chars'); $crypto->mode(Crypto::MODE_URL_SAFE); // 加密数据 $original = '{"user_id":123,"token":"jwt..."}'; $encrypted = $crypto->encrypt($original); // 加密结果: r50Mzv6rf1t5q6AJvQt5Pc-Zqy5ykcrgX8jSEgGi... // 构建URL $url = 'https://api.example.com/user?' . http_build_query(['data' => $encrypted]); // 服务器端解密 $received = $_GET['data'] ?? $encrypted; $decrypted = $crypto->decrypt($received); // 解密结果: {"user_id":123,"token":"jwt..."}
安全防护
XSS防护
使用Str::xssSafe()防护XSS攻击:
use Kode\String\Str; // XSS攻击示例 $attacks = [ '<script>alert("XSS")</script>', 'javascript:alert("XSS")', '<img src=x onerror=alert("XSS")>', ]; // 防护处理 foreach ($attacks as $input) { $safe = Str::xssSafe($input); echo $safe; // 输出: <script>alert("XSS")</script> }
SQL注入防护
使用Str::sqlSafe()防护SQL注入:
use Kode\String\Str; $userInput = "'; DROP TABLE users; --"; $safe = Str::sqlSafe($userInput); // 输出: \'\'; DROP TABLE users; -- // 严格模式(去除所有非字母数字字符) $strict = Str::sqlSafe($userInput, true); // 输出: DROPTABLEUSERS
HTML转义
使用Str::htmlEscape()转义HTML特殊字符:
use Kode\String\Str; $html = '<div class="test">Hello & "World"</div>'; $escaped = Str::htmlEscape($html); // 输出: <div class="test">Hello & "World"</div>
方法说明
| 方法 | 说明 | 示例 |
|---|---|---|
Crypto::md5(string $str, string $salt) |
MD5哈希(可选加盐) | Crypto::md5('123', 'salt') |
Crypto::sha1(string $str, string $salt) |
SHA1哈希(可选加盐) | Crypto::sha1('123', 'salt') |
Crypto::sha256(string $str, string $salt) |
SHA256哈希(可选加盐) | Crypto::sha256('123', 'salt') |
Crypto::hash(string $data, string $algo) |
通用哈希 | Crypto::hash('data', 'sha512') |
Crypto::passwordHash(string $str) |
密码哈希 | Crypto::passwordHash('123') |
Crypto::passwordVerify(string $str, string $hash) |
密码验证 | Crypto::passwordVerify('123', $hash) |
Crypto::hmac(string $data, string $key, string $algo) |
HMAC签名 | Crypto::hmac('data', 'key') |
Crypto::hashEquals(string $known, string $user) |
恒时比较 | Crypto::hashEquals($a, $b) |
Crypto::token(int $length) |
生成随机Token | Crypto::token(32) |
Crypto::uuid() |
生成UUID | Crypto::uuid() |
Crypto::randomString(int $length) |
随机字符串 | Crypto::randomString(16) |
Crypto::orderId(string $prefix) |
订单号 | Crypto::orderId('ORD') |
Crypto::inviteCode(int $length) |
邀请码 | Crypto::inviteCode(6) |
Crypto::verifyCode(int $length) |
验证码 | Crypto::verifyCode(4) |
(new Crypto($key))->encrypt(string $data) |
AES加密 | $c->encrypt('data') |
(new Crypto($key))->decrypt(string $data) |
AES解密 | $c->decrypt($encrypted) |
HTTP请求模块
特性
- ✅ GET/POST/PUT/PATCH/DELETE/HEAD/OPTIONS
- ✅ 链式调用
- ✅ JSON/表单/文件上传
- ✅ SSL验证和代理支持
- ✅ 重试机制
- ✅ 中间件支持
- ✅ Promise风格then/catch
快速开始
use Kode\Curl\Curl; // GET请求 $response = Curl::get('https://api.example.com/users', ['page' => 1]) ->timeout(30) ->headers(['Authorization' => 'Bearer xxx']) ->send(); // 响应: Response对象,可调用 $response->json() 获取数据 // POST请求 $response = Curl::post('https://api.example.com/users', ['name' => '张三']) ->withJson(['name' => '张三']) ->send(); // 响应: Response对象 // 链式调用 $response = Curl::create('https://api.example.com/users') ->method('POST') ->withJson(['name' => '张三']) ->authorization('Bearer xxx') ->send(); // 响应: Response对象 // Promise风格 $result = Curl::get('https://api.example.com/users') ->then(fn($response) => $response->json()) ->catch(fn($response) => $response->getErrorMessage()); // 成功: 返回JSON数据 // 失败: 返回错误消息
方法说明
| 方法 | 说明 | 示例 |
|---|---|---|
Curl::get(string $url, array $query) |
GET请求 | Curl::get('/users', ['page' => 1]) |
Curl::post(string $url, mixed $data) |
POST请求 | Curl::post('/users', ['name' => 'x']) |
Curl::put(string $url, mixed $data) |
PUT请求 | Curl::put('/users/1', $data) |
Curl::delete(string $url) |
DELETE请求 | Curl::delete('/users/1') |
Curl::create(string $url) |
创建实例 | Curl::create('/users') |
->send() |
发送请求 | $curl->send() |
->timeout(int $seconds) |
超时时间 | ->timeout(30) |
->headers(array $headers) |
设置请求头 | ->headers(['Auth' => 'xxx']) |
->withJson(mixed $data) |
JSON数据 | ->withJson(['id' => 1]) |
->withForm(array $data) |
表单数据 | ->withForm(['name' => 'x']) |
->authorization(string $token) |
Bearer认证 | ->authorization('xxx') |
->proxy(string $host, int $port) |
代理设置 | ->proxy('127.0.0.1', 8080) |
->retry(int $times, int $delay) |
重试机制 | ->retry(3, 1000) |
->then(callable $onFulfilled) |
成功回调 | ->then(fn($r) => $r->json()) |
->catch(callable $onRejected) |
错误回调 | ->catch(fn($r) => $r->error) |
Response方法
| 方法 | 说明 | 示例 |
|---|---|---|
->isSuccess() |
是否成功(2xx) | $res->isSuccess() |
->isRedirect() |
是否重定向(3xx) | $res->isRedirect() |
->isClientError() |
客户端错误(4xx) | $res->isClientError() |
->isServerError() |
服务端错误(5xx) | $res->isServerError() |
->isJson() |
是否JSON | $res->isJson() |
->json() |
获取JSON数据 | $res->json() |
->getContent() |
获取内容 | $res->getContent() |
->getStatusCode() |
状态码 | $res->getStatusCode() |
数组处理模块
特性
- ✅ 树形结构转换
- ✅ first/last/find 数组操作
- ✅ 深度合并
- ✅ 统计计算
快速开始
use Kode\Array\Arr; // 数组转树形 $tree = Arr::tree([ ['id' => 1, 'parent_id' => 0, 'name' => 'A'], ['id' => 2, 'parent_id' => 1, 'name' => 'B'], ['id' => 3, 'parent_id' => 1, 'name' => 'C'], ], 'id', 'parent_id'); // 结果: [['id' => 1, 'parent_id' => 0, 'name' => 'A', 'children' => [...]]] // 获取首尾元素 Arr::first([1, 2, 3]); // 结果: 1 Arr::last([1, 2, 3]); // 结果: 3 // 查找元素 Arr::find([1, 2, 3], fn($n) => $n > 1); // 结果: 2 // 深度合并 Arr::deepMerge(['a' => 1], ['a' => 2, 'b' => 3]); // 结果: ['a' => 2, 'b' => 3]
方法说明
| 方法 | 说明 | 示例 |
|---|---|---|
Arr::tree(array $list, string $idField, string $parentIdField) |
数组转树形 | Arr::tree($list, 'id', 'pid') |
Arr::list(array $tree, string $childrenField) |
树形转数组 | Arr::list($tree, 'children') |
Arr::level(array $list, string $idField, string $parentIdField) |
计算层级 | Arr::level($list, 'id', 'pid') |
Arr::path(array $list, string $idField, string $parentIdField, string $nameField) |
获取路径 | Arr::path($list, 'id', 'pid', 'name') |
Arr::first(array $array) |
获取第一个元素 | Arr::first([1,2,3]) |
Arr::last(array $array) |
获取最后一个元素 | Arr::last([1,2,3]) |
Arr::find(array $array, callable $callback) |
查找满足条件的元素 | Arr::find($arr, fn($v)=>$v>1) |
Arr::filter(array $array, callable $callback) |
过滤数组 | Arr::filter($arr, fn($v)=>$v>0) |
Arr::map(array $array, callable $callback) |
遍历修改 | Arr::map($arr, fn($v)=>$v*2) |
Arr::reduce(array $array, callable $callback, mixed $initial) |
合并为单一值 | Arr::reduce($arr, fn($c,$v)=>$c+$v, 0) |
Arr::deepMerge(array $array1, array $array2) |
深度合并 | Arr::deepMerge($a1, $a2) |
Arr::group(array $array, string $key) |
分组 | Arr::group($arr, 'category') |
Arr::sort(array $array, string $key, string $order) |
排序 | Arr::sort($arr, 'id', 'asc') |
Arr::unique(array $array) |
去重 | Arr::unique($arr) |
Arr::chunk(array $array, int $size) |
分块 | Arr::chunk($arr, 10) |
Arr::flatten(array $array) |
扁平化 | Arr::flatten($tree) |
Arr::paginate(array $array, int $page, int $size) |
分页 | Arr::paginate($arr, 1, 10) |
Arr::sum(array $array, string $key) |
求和 | Arr::sum($arr, 'price') |
Arr::avg(array $array, string $key) |
平均值 | Arr::avg($arr, 'score') |
Arr::max(array $array, string $key) |
最大值 | Arr::max($arr, 'price') |
Arr::min(array $array, string $key) |
最小值 | Arr::min($arr, 'price') |
Arr::random(array $array) |
随机取一个 | Arr::random($arr) |
Arr::randomMany(array $array, int $num) |
随机取多个 | Arr::randomMany($arr, 3) |
Arr::column(array $array, string $columnKey) |
提取列 | Arr::column($arr, 'name') |
Arr::pluck(array $array, string $key) |
提取值列表 | Arr::pluck($arr, 'id') |
字符串处理模块
特性
- ✅ 手机号/邮箱/身份证脱敏
- ✅ 驼峰/蛇形命名转换
- ✅ Base64编码解码
- ✅ UUID生成
- ✅ 字符串验证
- ✅ 格式转换
快速开始
use Kode\String\Str; // 脱敏(支持自定义保留范围) Str::maskPhone('13800138000'); // 结果: 138****8000 Str::maskPhone('13800138000', 2, 2); // 结果: 13*******00(保留前2后2) Str::maskEmail('user@example.com'); // 结果: us**@example.com Str::maskEmail('user@example.com', 2, 0); // 结果: us**@example.com(自定义保留位数) // Unicode 感知脱敏(支持中文) Str::maskKeep('张三你吃了吗', 1, 1); // 结果: 张****吗(保留首尾各1个字符) // 自定义范围脱敏(支持负数索引) Str::mask('13800138000', 2, -1); // 结果: 13*********(从第2位替换到末尾) // 命名转换 Str::camel('hello_world'); // 结果: helloWorld Str::snake('helloWorld'); // 结果: hello_world Str::studly('hello_world'); // 结果: HelloWorld // Base64 Str::toBase64('hello'); // 结果: aGVsbG8= Str::fromBase64('aGVsbG8='); // 结果: hello // UUID / 唯一码(支持自定义格式、批量、时间排序) Str::uuid(); // 结果: a24e88d8-b560-4196-a34b-63626c1e489d Str::uuid('XXXX-9999-AA'); // 结果: 3A7F-4821-KL(按格式生成) Str::code('999999'); // 结果: 385104(6位数字验证码) Str::orderedUuid(); // 结果: 018f3b5c4d3e12f4(基于微时间戳,适合批量) Str::uuidBatch(5, '9999'); // 结果: ['1234', '5678', ...](5个不重复的4位码) // 验证 Str::validatePhone('13800138000'); // 结果: true Str::validateEmail('test@example.com'); // 结果: true Str::validateIdCard('110101199001011234'); // 结果: true // 车牌验证(支持油车/新能源/军用/使馆/白名单等) use Kode\String\Str; Str::validatePlate('京A12345'); // 结果: true(普通燃油车) Str::validatePlate('沪AD12345', Str::PLATE_NEW_ENERGY); // 结果: true(新能源) Str::validatePlate('使12345', Str::PLATE_EMBASSY); // 结果: true(使馆车) // 白名单优先命中(可用于数据库中的特种车辆) Str::validatePlate('UNKNOWN', Str::PLATE_ALL, ['UNKNOWN', '京V00001']); // 结果: true // 识别车牌类型 Str::plateType('沪AF12345'); // 结果: new_energy
方法说明
| 方法 | 说明 | 示例 |
|---|---|---|
| 脱敏方法 | ||
Str::maskPhone(string $phone, int $keepStart, int $keepEnd, string $mask) |
手机号脱敏 | Str::maskPhone('13800138000', 2, 2) |
Str::maskEmail(string $email, int $keepStart, int $keepEnd, string $mask) |
邮箱脱敏 | Str::maskEmail('a@b.com', 2, 0) |
Str::maskIdCard(string $idCard, int $keepStart, int $keepEnd, string $mask) |
身份证脱敏 | Str::maskIdCard('110101199001011234') |
Str::maskBankCard(string $bankCard, int $keepStart, int $keepEnd) |
银行卡脱敏 | Str::maskBankCard('6222021234567890') |
Str::mask(string $str, int $start, int $length, string $mask) |
自定义脱敏(支持负数) | Str::mask('abc', 1, -1) |
Str::maskKeep(string $str, int $head, int $tail, string $mask) |
Unicode 感知保留脱敏 | Str::maskKeep('张三', 1, 1) |
| 命名转换 | ||
Str::camel(string $str) |
转驼峰 | Str::camel('hello_world') |
Str::snake(string $str) |
转蛇形 | Str::snake('helloWorld') |
Str::studly(string $str) |
转大驼峰 | Str::studly('hello_world') |
| 编码转换 | ||
Str::toBase64(string $str) |
字符串转Base64 | Str::toBase64('hello') |
Str::fromBase64(string $base64) |
Base64转字符串 | Str::fromBase64('aGVsbG8=') |
Str::toJson(mixed $data) |
转JSON | Str::toJson(['a' => 1]) |
Str::fromJson(string $json) |
JSON转数据 | Str::fromJson('{"a":1}') |
Str::toXml(array $data) |
转XML | Str::toXml(['a' => 1]) |
Str::fromXml(string $xml) |
XML转数组 | Str::fromXml('<root><a>1</a></root>') |
Str::toArray(string $str, string $delimiter) |
字符串转数组 | Str::toArray('a,b,c') |
Str::fromArray(array $array, string $delimiter) |
数组转字符串 | Str::fromArray(['a','b']) |
| 字符串判断 | ||
Str::contains(string $str, string $needle) |
是否包含 | Str::contains('hello', 'll') |
Str::startsWith(string $str, string $prefix) |
是否开头 | Str::startsWith('hello', 'he') |
Str::endsWith(string $str, string $suffix) |
是否结尾 | Str::endsWith('hello', 'lo') |
| 字符串截取 | ||
Str::substr(string $str, int $start, ?int $length) |
截取字符串 | Str::substr('hello', 0, 3) |
Str::mbSubstr(string $str, int $start, ?int $length) |
中文截取 | Str::mbSubstr('你好', 0, 1) |
Str::truncate(string $str, int $length, string $suffix) |
按长度截断 | Str::truncate('abc', 2) |
Str::limit(string $str, int $limit, string $end) |
按显示宽度截断 | Str::limit('你好世界', 5) |
Str::length(string $str) |
获取长度 | Str::length('hello') |
Str::mbLength(string $str) |
中文长度 | Str::mbLength('你好') |
| 字符串修改 | ||
Str::replace(string $str, string $search, string $replace) |
替换 | Str::replace('a', 'b', 'a') |
Str::remove(string $str, string $search) |
删除 | Str::remove('ab', 'b') |
Str::reverse(string $str) |
反转 | Str::reverse('abc') |
Str::shuffle(string $str) |
随机打乱 | Str::shuffle('abc') |
Str::repeat(string $str, int $times) |
重复 | Str::repeat('a', 3) |
Str::pad(string $str, int $length, string $pad, int $type) |
填充 | Str::pad('a', 5, '0', STR_PAD_LEFT) |
Str::trim(string $str) |
去空格 | Str::trim(' abc ') |
Str::ucfirst(string $str) |
首字母大写 | Str::ucfirst('hello') |
Str::lcfirst(string $str) |
首字母小写 | Str::lcfirst('Hello') |
Str::title(string $str) |
首字母大写词 | Str::title('hello world') |
| 验证方法 | ||
Str::validatePhone(string $phone, string $region) |
验证手机号 | Str::validatePhone('13800138000') |
Str::validateEmail(string $email) |
验证邮箱 | Str::validateEmail('a@b.com') |
Str::validateIdCard(string $idCard) |
验证身份证 | Str::validateIdCard('110101199001011234') |
Str::validateCarPlate(string $plate) |
验证车牌(兼容旧方法) | Str::validateCarPlate('京A12345') |
Str::validatePlate(string $plate, string $type, array $whitelist) |
多类型车牌验证 | Str::validatePlate('京A12345', Str::PLATE_OIL) |
Str::plateType(string $plate) |
识别车牌类型 | Str::plateType('沪AF12345') |
Str::isPlateInWhitelist(string $plate, array $whitelist) |
白名单匹配 | Str::isPlateInWhitelist('X', ['X']) |
| 安全方法 | ||
Str::sqlSafe(string $str, bool $strict) |
SQL安全 | Str::sqlSafe('abc') |
Str::xssSafe(string $str, bool $strict) |
XSS安全 | Str::xssSafe('<script>') |
Str::htmlEscape(string $str) |
HTML转义 | Str::htmlEscape('<') |
Str::htmlUnescape(string $str) |
HTML反转义 | Str::htmlUnescape('<') |
| 其他方法 | ||
Str::uuid(?string $format) |
生成UUID(支持自定义格式) | Str::uuid() |
Str::code(string $format) |
按格式生成随机码 | Str::code('XXXX-9999') |
Str::orderedUuid(?string $format) |
时间排序唯一ID | Str::orderedUuid() |
Str::uuidBatch(int $count, ?string $format) |
批量生成唯一码 | Str::uuidBatch(100, '9999') |
Str::random(int $length, string $mode) |
随机字符串 | Str::random(16) |
Str::clean(string $str, array $options) |
清理字符串 | Str::clean(' abc ') |
Str::similarity(string $str1, string $str2) |
相似度 | Str::similarity('abc', 'abd') |
Str::split(string $str, string|array $delimiters) |
分割字符串 | Str::split('a,b', ',') |
Str::toBool(string $str) |
转布尔 | Str::toBool('true') |
Str::toInt(string $str) |
转整数 | Str::toInt('123') |
Str::toFloat(string $str) |
转浮点数 | Str::toFloat('1.23') |
Str::compress(string $str, int $level) |
压缩 | Str::compress('很长字符串') |
Str::decompress(string $str) |
解压 | Str::decompress($compressed) |
时间处理模块
特性
- ✅ 时间格式化
- ✅ 人性化显示(3分钟前)
- ✅ 日期范围计算
- ✅ 时间加减计算
快速开始
use Kode\Time\Time; // 获取当前时间 Time::now(); // 结果: 2026-04-01 12:00:00 Time::today(); // 结果: 2026-04-01 Time::yesterday(); // 结果: 2026-03-31 Time::tomorrow(); // 结果: 2026-04-02 // 人性化显示 Time::diffForHumans('2024-01-01'); // 结果: 2年前 // 日期范围 Time::weekStart(); // 结果: 2026-03-30 Time::weekEnd(); // 结果: 2026-04-05 Time::monthStart(); // 结果: 2026-04-01 Time::monthEnd(); // 结果: 2026-04-30 // 时间戳操作 Time::add(time(), 86400); // 结果: 明天的时间戳 Time::sub(time(), 3600); // 结果: 一小时前的时间戳
方法说明
| 方法 | 说明 | 示例 |
|---|---|---|
Time::now(string $format) |
当前时间 | Time::now() |
Time::today(string $format) |
今天日期 | Time::today() |
Time::yesterday(string $format) |
昨天 | Time::yesterday() |
Time::tomorrow(string $format) |
明天 | Time::tomorrow() |
Time::format(?int $timestamp, string $format) |
格式化时间 | Time::format(time(), 'Y-m-d') |
Time::diffForHumans(int|string $timestamp) |
人性化显示 | Time::diffForHumans('2024-01-01') |
Time::add(int $timestamp, int $interval) |
时间加秒 | Time::add(time(), 86400) |
Time::sub(int $timestamp, int $interval) |
时间减秒 | Time::sub(time(), 3600) |
Time::diff(int $start, int $end) |
差值(秒) | Time::diff($t1, $t2) |
Time::weekStart(?int $timestamp) |
本周开始 | Time::weekStart() |
Time::weekEnd(?int $timestamp) |
本周结束 | Time::weekEnd() |
Time::monthStart(?int $timestamp) |
本月开始 | Time::monthStart() |
Time::monthEnd(?int $timestamp) |
本月结束 | Time::monthEnd() |
Time::yearStart(?int $timestamp) |
今年开始 | Time::yearStart() |
Time::yearEnd(?int $timestamp) |
今年结束 | Time::yearEnd() |
Time::lastWeekStart(?int $timestamp) |
上周开始 | Time::lastWeekStart() |
Time::lastWeekEnd(?int $timestamp) |
上周结束 | Time::lastWeekEnd() |
Time::lastMonthStart(?int $timestamp) |
上月开始 | Time::lastMonthStart() |
Time::lastMonthEnd(?int $timestamp) |
上月结束 | Time::lastMonthEnd() |
Time::between(int $timestamp, int $start, int $end) |
是否在范围内 | Time::between(time(), $s, $e) |
Time::isToday(int $timestamp) |
是否今天 | Time::isToday($ts) |
Time::isYesterday(int $timestamp) |
是否昨天 | Time::isYesterday($ts) |
Time::isTomorrow(int $timestamp) |
是否明天 | Time::isTomorrow($ts) |
Time::isThisWeek(int $timestamp) |
是否本周 | Time::isThisWeek($ts) |
Time::isThisMonth(int $timestamp) |
是否本月 | Time::isThisMonth($ts) |
Time::isThisYear(int $timestamp) |
是否今年 | Time::isThisYear($ts) |
Time::dayOfWeek(int $timestamp) |
星期几(0-6) | Time::dayOfWeek(time()) |
Time::dayOfWeekName(int $timestamp) |
星期几名称 | Time::dayOfWeekName(time()) |
Time::dayOfYear(int $timestamp) |
第几天 | Time::dayOfYear(time()) |
Time::weekOfYear(int $timestamp) |
第几周 | Time::weekOfYear(time()) |
Time::daysInMonth(int $month, int $year) |
月天数 | Time::daysInMonth(2, 2024) |
Time::age(string $birthday) |
年龄 | Time::age('1990-01-01') |
Time::toTimestamp(string $timeStr) |
转时间戳 | Time::toTimestamp('2024-01-01') |
Time::toMillisecond(?int $timestamp) |
毫秒时间戳 | Time::toMillisecond() |
Time::fromMillisecond(int $millisecond) |
毫秒转时间戳 | Time::fromMillisecond($ms) |
Time::millisecond() |
当前毫秒 | Time::millisecond() |
Time::microsecond() |
当前微秒 | Time::microsecond() |
Time::microtime() |
当前微秒时间 | Time::microtime() |
Time::setTimezone(string $timezone) |
设置时区 | Time::setTimezone('Asia/Shanghai') |
数学计算模块
特性
- ✅ 高精度计算(bcmath)
- ✅ 全局默认精度 + 单次精度控制
- ✅ 折扣/税费计算
- ✅ 平均数/中位数/标准差
快速开始
use Kode\Math\Math; // 高精度计算(默认保留 10 位小数) Math::add('1.1', '2.2'); // 结果: 3.3000000000 Math::sub('5.5', '3.3'); // 结果: 2.2000000000 Math::mul('1.5', '2.5'); // 结果: 3.7500000000 Math::div('10', '3'); // 结果: 3.3333333333 // 单次指定精度 Math::add('1.1', '2.2', 2); // 结果: 3.30 Math::div('10', '3', 4); // 结果: 3.3333 // 全局默认精度 Math::setDefaultScale(4); Math::getDefaultScale(); // 结果: 4 Math::add('1.1', '2.2'); // 结果: 3.3000 // 折扣计算 Math::discount('100', '0.8'); // 结果: 80.00 // 税费计算 Math::tax('100', '0.13'); // 结果: 13.00 // 统计 Math::average([1, 2, 3, 4, 5]); // 结果: 3.0000000000 Math::median([1, 2, 3, 4, 5]); // 结果: 3.0000000000 Math::mode([1, 2, 2, 3]); // 结果: 2 Math::standardDeviation([1, 2, 3, 4, 5]); // 结果: 1.4142135624
方法说明
| 方法 | 说明 | 示例 |
|---|---|---|
| 精度控制 | ||
Math::setDefaultScale(int $scale) |
设置全局默认精度 | Math::setDefaultScale(4) |
Math::getDefaultScale() |
获取全局默认精度 | Math::getDefaultScale() |
| 基础运算 | ||
Math::add(float|int|string $num1, float|int|string $num2, ?int $scale) |
加法 | Math::add('1.1', '2.2') |
Math::sub(float|int|string $num1, float|int|string $num2, ?int $scale) |
减法 | Math::sub('5.5', '3.3') |
Math::mul(float|int|string $num1, float|int|string $num2, ?int $scale) |
乘法 | Math::mul('1.5', '2.5') |
Math::div(float|int|string $num1, float|int|string $num2, ?int $scale) |
除法 | Math::div('10', '3') |
Math::mod(float|int|string $num1, float|int|string $num2) |
取模 | Math::mod('10', '3') |
Math::pow(float|int|string $num, int $exponent, int $scale) |
幂运算 | Math::pow('2', 10) |
Math::sqrt(float|int|string $num, int $scale) |
平方根 | Math::sqrt('2') |
Math::abs(float|int|string $num) |
绝对值 | Math::abs('-5') |
Math::round(float|int|string $num, int $precision) |
四舍五入 | Math::round('3.5') |
Math::ceil(float|int|string $num, int $precision) |
向上取整 | Math::ceil('3.1') |
Math::floor(float|int|string $num, int $precision) |
向下取整 | Math::floor('3.9') |
Math::compare(float|int|string $num1, float|int|string $num2) |
比较(-1/0/1) | Math::compare('1', '2') |
Math::equal(float|int|string $num1, float|int|string $num2, int $scale) |
是否相等 | Math::equal('1.0', '1') |
Math::format(float|int|string $num, int $precision, bool $thousandsSeparator) |
格式化数字 | Math::format('1000', 2) |
| 金融计算 | ||
Math::discount(float|int|string $price, float|int|string $discount, int $scale) |
折扣价 | Math::discount('100', '0.8') |
Math::tax(float|int|string $amount, float|int|string $rate, int $scale) |
税额 | Math::tax('100', '0.13') |
Math::taxIncluded(float|int|string $amount, float|int|string $rate, int $scale) |
含税价 | Math::taxIncluded('100', '0.13') |
Math::taxExcluded(float|int|string $amount, float|int|string $rate, int $scale) |
不含税价 | Math::taxExcluded('113', '0.13') |
Math::percentage(float|int|string $part, float|int|string $total, int $scale) |
百分比 | Math::percentage('25', '100') |
Math::simpleInterest(float|int|string $principal, float|int|string $rate, int $years) |
单利 | Math::simpleInterest('1000', '0.05', 2) |
Math::compoundInterest(float|int|string $principal, float|int|string $rate, int $years) |
复利 | Math::compoundInterest('1000', '0.05', 2) |
| 三角函数 | ||
Math::sin(float|int|string $num, int $scale) |
正弦 | Math::sin('0') |
Math::cos(float|int|string $num, int $scale) |
余弦 | Math::cos('0') |
Math::tan(float|int|string $num, int $scale) |
正切 | Math::tan('1') |
Math::asin(float|int|string $num, int $scale) |
反正弦 | Math::asin('0.5') |
Math::acos(float|int|string $num, int $scale) |
反余弦 | Math::acos('0.5') |
Math::atan(float|int|string $num, int $scale) |
反正切 | Math::atan('1') |
| 对数函数 | ||
Math::ln(float|int|string $num, int $scale) |
自然对数 | Math::ln('2.718') |
Math::log10(float|int|string $num, int $scale) |
常用对数 | Math::log10('100') |
Math::log(float|int|string $num, float|int|string $base, int $scale) |
对数 | Math::log('8', '2') |
Math::rad2deg(float|int|string $num, int $scale) |
弧度转角度 | Math::rad2deg('3.14') |
Math::deg2rad(float|int|string $num, int $scale) |
角度转弧度 | Math::deg2rad('180') |
| 数论函数 | ||
Math::factorial(int $num) |
阶乘 | Math::factorial(5) |
Math::gcd(int $num1, int $num2) |
最大公约数 | Math::gcd('12', '18') |
Math::lcm(int $num1, int $num2) |
最小公倍数 | Math::lcm('4', '6') |
Math::isPrime(int $num) |
是否质数 | Math::isPrime(7) |
Math::isEven(int $num) |
是否偶数 | Math::isEven(4) |
Math::isOdd(int $num) |
是否奇数 | Math::isOdd(3) |
| 判断函数 | ||
Math::isPositive(float|int|string $num) |
是否正数 | Math::isPositive('1') |
Math::isNegative(float|int|string $num) |
是否负数 | Math::isNegative('-1') |
Math::isZero(float|int|string $num, int $scale) |
是否零 | Math::isZero('0') |
Math::isValid(mixed $num) |
是否有效数字 | Math::isValid('123') |
Math::inRange(float|int|string $num, float|int|string $min, float|int|string $max) |
是否在范围内 | Math::inRange('5', '1', '10') |
Math::clamp(float|int|string $num, float|int|string $min, float|int|string $max) |
限制范围 | Math::clamp('15', '1', '10') |
| 插值与随机 | ||
Math::lerp(float|int|string $start, float|int|string $end, float|int|string $t, int $scale) |
线性插值 | Math::lerp('0', '100', '0.5') |
Math::random(float|int|string $min, float|int|string $max, int $scale) |
随机数 | Math::random('1', '100') |
| 统计函数 | ||
Math::average(array $numbers, int $scale) |
平均值 | Math::average([1,2,3]) |
Math::median(array $numbers, int $scale) |
中位数 | Math::median([1,2,3,4,5]) |
Math::mode(array $numbers) |
众数 | Math::mode([1,2,2,3]) |
Math::standardDeviation(array $numbers, int $scale) |
标准差 | Math::standardDeviation([1,2,3]) |
Math::variance(array $numbers, int $scale) |
方差 | Math::variance([1,2,3]) |
地理位置模块
特性
- ✅ 两点距离计算(Haversine)
- ✅ 坐标验证
- ✅ 方位角计算
快速开始
use Kode\Geo\Geo; // 两点距离(默认公里) $distance = Geo::distance(39.9042, 116.4074, 31.2304, 121.4737); // 结果: 1068.51 // 两点距离(米) $distanceM = Geo::distance(39.9042, 116.4074, 31.2304, 121.4737, 'm'); // 结果: 1068506.82 // 坐标验证 Geo::isValid(39.9042, 116.4074); // 结果: true // 方位角 Geo::bearing(39.9042, 116.4074, 31.2304, 121.4737); // 结果: -141.67
方法说明
| 方法 | 说明 | 示例 |
|---|---|---|
Geo::distance(float $lat1, float $lon1, float $lat2, float $lon2, string $unit) |
两点距离 | Geo::distance($lat1, $lon1, $lat2, $lon2) |
Geo::isValid(float $lat, float $lon) |
坐标验证 | Geo::isValid(39.9042, 116.4074) |
Geo::toRadians(float $degrees) |
度转弧度 | Geo::toRadians(180) |
Geo::toDegrees(float $radians) |
弧度转度 | Geo::toDegrees(3.14) |
Geo::midpoint(float $lat1, float $lon1, float $lat2, float $lon2) |
中点坐标 | Geo::midpoint($lat1, $lon1, $lat2, $lon2) |
Geo::bearing(float $lat1, float $lon1, float $lat2, float $lon2) |
方位角(度) | Geo::bearing($lat1, $lon1, $lat2, $lon2) |
Geo::toDMS(float $decimal, bool $isLatitude) |
十进制转度分秒 | Geo::toDMS(39.9042, true) |
Geo::toDecimal(int $degrees, int $minutes, float $seconds, string $direction) |
度分秒转十进制 | Geo::toDecimal(39, 54, 15.12, 'N') |
IP地址模块
特性
- ✅ IP验证
- ✅ 私有/公网IP判断
- ✅ IP类型检测
快速开始
use Kode\Ip\Ip; // IP验证 Ip::isValid('192.168.1.1'); // 结果: true // 私有IP判断 Ip::isPrivate('192.168.1.1'); // 结果: true Ip::isPublic('8.8.8.8'); // 结果: true // 获取客户端IP Ip::get(); // 结果: 127.0.0.1 Ip::getRealIp(); // 结果: 真实IP // IP类型 Ip::getType('192.168.1.1'); // 结果: private Ip::getType('8.8.8.8'); // 结果: public // CIDR 检查 Ip::inCidr('192.168.1.100', '192.168.1.0/24'); // 结果: true // IP 范围检查 Ip::inRange('192.168.1.100', '192.168.1.1-192.168.1.200'); // 结果: true // IP转长整数 Ip::toLong('192.168.1.1'); // 结果: 3232235777 Ip::fromLong(3232235777); // 结果: 192.168.1.1
方法说明
| 方法 | 说明 | 示例 |
|---|---|---|
Ip::get(bool $checkProxy) |
获取客户端IP | Ip::get() |
Ip::getRealIp() |
获取真实IP | Ip::getRealIp() |
Ip::isValid(string $ip) |
IP验证 | Ip::isValid('192.168.1.1') |
Ip::isPrivate(string $ip) |
是否私有IP | Ip::isPrivate('192.168.1.1') |
Ip::isPublic(string $ip) |
是否公网IP | Ip::isPublic('8.8.8.8') |
Ip::inCidr(string $ip, string $cidr) |
是否属于 CIDR | Ip::inCidr('192.168.1.1', '192.168.1.0/24') |
Ip::inRange(string $ip, string $range) |
是否在 IP 范围 | Ip::inRange('1.1.1.1', '1.1.1.0-1.1.1.255') |
Ip::getVersion(string $ip) |
IP版本(4/6) | Ip::getVersion('192.168.1.1') |
Ip::getType(string $ip) |
IP类型 | Ip::getType('192.168.1.1') |
Ip::toLong(string $ip) |
IP转整数 | Ip::toLong('192.168.1.1') |
Ip::fromLong(int $long) |
整数转IP | Ip::fromLong(3232235777) |
Ip::getLocation(string $ip, ?string $apiKey) |
IP归属地 | Ip::getLocation('8.8.8.8') |
Ip::isFromCountry(string $ip, string $countryCode) |
是否某国IP | Ip::isFromCountry('8.8.8.8', 'US') |
安全模块
特性
- ✅ 滑动窗口限速(文件锁实现,并发安全)
- ✅ CSRF Token 生成与验证
- ✅ HMAC-SHA256 请求签名与验签
- ✅ CIDR/IP 范围检查
- ✅ 安全输入过滤与 XSS/SQL 基础清理
快速开始
use Kode\Security\Security; // 限速:每 60 秒最多 5 次 $allow = Security::rateLimit('user_123', 5, 60); // 结果: true(前 5 次)/ false(触发限速) // CSRF Token $token = Security::csrfToken(); $valid = Security::csrfVerify($token); // 结果: true // 一次性 CSRF Token $once = Security::csrfTokenOnce(); Security::csrfVerifyOnce($once); // 验证后自动失效 // 请求签名 $secret = 'your_secret_key_at_least_16chars'; $payload = Security::signPayload(['user_id' => 123], $secret); // 结果: ['user_id' => 123, '_time' => 171..., '_sign' => '...'] $ok = Security::signVerify($payload, $secret); // 结果: true // 安全获取输入 $age = Security::input('age', 0, 'int', 'get'); $email = Security::input('email', '', 'email', 'post'); // XSS 清理 $safe = Security::xssClean('<script>alert(1)</script>'); // 结果: 清理后的安全字符串 // 请求指纹 + Nonce 防重放 $fingerprint = Security::requestFingerprint(); $nonce = Security::nonce('api', 300); $valid = Security::verifyNonce($nonce, 'api', 300); // 结果: true(第二次验证为 false) // 切换限速存储后端为 APCu(单机多 worker) use Kode\Security\Storage\ApcuStorage; Security::setRateLimiterStorage(new ApcuStorage());
方法说明
| 方法 | 说明 | 示例 |
|---|---|---|
Security::rateLimit(string $key, int $max, int $window) |
检查是否触发限速 | Security::rateLimit('ip', 60, 60) |
Security::rateLimitRemaining(string $key, int $max, int $window) |
获取剩余次数(同时记录本次) | Security::rateLimitRemaining('ip', 60, 60) |
Security::rateLimitAvailable(string $key, int $max, int $window) |
仅查询剩余次数 | Security::rateLimitAvailable('ip', 60, 60) |
Security::rateLimitReset(string $key) |
重置限速记录 | Security::rateLimitReset('ip') |
Security::setRateLimiterStorage(RateLimiterStorageInterface $storage) |
切换限速存储后端 | Security::setRateLimiterStorage(new RedisStorage($redis)) |
Security::requestFingerprint(array $extra) |
请求指纹 | Security::requestFingerprint() |
Security::nonce(string $namespace, int $ttl) |
生成一次性 Nonce | Security::nonce('api', 300) |
Security::verifyNonce(string $token, string $namespace, int $ttl) |
验证并消耗 Nonce | Security::verifyNonce($token, 'api', 300) |
Security::csrfToken(?string $key) |
生成 CSRF Token | Security::csrfToken() |
Security::csrfVerify(string $token, ?string $key, bool $clear) |
验证 CSRF Token | Security::csrfVerify($token) |
Security::csrfTokenOnce(?string $key) |
生成一次性 Token | Security::csrfTokenOnce() |
Security::csrfVerifyOnce(string $token, ?string $key) |
验证一次性 Token | Security::csrfVerifyOnce($token) |
Security::sign(array $data, string $secret, ?int $timestamp) |
生成签名 | Security::sign($data, $secret) |
Security::signVerify(array $data, string $secret, int $expire) |
验证签名 | Security::signVerify($data, $secret) |
Security::signPayload(array $data, string $secret) |
生成带签名的数据 | Security::signPayload($data, $secret) |
Security::inCidr(string $ip, string $cidr) |
CIDR 检查 | Security::inCidr('1.1.1.1', '1.1.1.0/24') |
Security::inRange(string $ip, string $range) |
IP 范围检查 | Security::inRange('1.1.1.1', '1.1.1.0-1.1.1.255') |
Security::input(string $key, mixed $default, string $type, string $source) |
安全输入过滤 | Security::input('id', 0, 'int', 'get') |
Security::inputs(array $rules) |
批量安全输入过滤 | Security::inputs([['id','int',0,'get']]) |
Security::cast(mixed $value, string $type) |
类型转换过滤 | Security::cast('123', 'int') |
Security::xssClean(string $str) |
XSS 清理 | Security::xssClean('<script>') |
Security::sqlSafe(string $str) |
SQL 基础过滤 | Security::sqlSafe("' OR 1=1") |
Security::randomToken(int $length) |
生成随机 Token | Security::randomToken(32) |
Security::randomInt(int $min, int $max) |
安全随机整数 | Security::randomInt(1, 100) |
限速存储后端
默认使用 FileStorage(文件锁),适合大多数多进程环境。根据部署形态可切换为更高性能的存储:
use Kode\Security\Security; use Kode\Security\Storage\MemoryStorage; use Kode\Security\Storage\ApcuStorage; use Kode\Security\Storage\RedisStorage; // 内存存储(仅当前进程,适合测试) Security::setRateLimiterStorage(new MemoryStorage()); // APCu 存储(单机多 worker 共享) if ((new ApcuStorage())->available()) { Security::setRateLimiterStorage(new ApcuStorage()); } // Redis 存储(分布式多机共享) $redis = new Redis(); $redis->connect('127.0.0.1', 6379); Security::setRateLimiterStorage(new RedisStorage($redis));
| 存储后端 | 适用场景 | 依赖 |
|---|---|---|
FileStorage |
默认,多进程 FPM/Swoole | 无 |
MemoryStorage |
单进程 / 单元测试 | 无 |
ApcuStorage |
单机多 worker 高性能 | ext-apcu |
RedisStorage |
分布式部署 | ext-redis |
二维码模块
特性
- ✅ 生成二维码
- ✅ 支持Logo
- ✅ 多种编码模式
快速开始
use Kode\Qrcode\Qr; // 生成二维码图片 $qr = Qr::text('https://example.com') ->size(300) ->margin(10) ->generate(); // 保存到文件 Qr::text('https://example.com') ->save('qrcode.png'); // 生成Base64 $base64 = Qr::text('https://example.com') ->base64();
方法说明
| 方法 | 说明 | 示例 |
|---|---|---|
Qr::text(string $content) |
设置内容 | Qr::text('hello') |
Qr::size(int $size) |
二维码尺寸 | Qr::size(300) |
Qr::margin(int $margin) |
边距 | Qr::margin(10) |
Qr::foregroundColor(string $color) |
前景色 | Qr::foregroundColor('#000000') |
Qr::backgroundColor(string $color) |
背景色 | Qr::backgroundColor('#ffffff') |
Qr::logo(string $path) |
Logo路径 | Qr::logo('logo.png') |
Qr::generate() |
生成图片 | $qr->generate() |
Qr::save(string $path) |
保存文件 | $qr->save('qr.png') |
Qr::base64() |
返回Base64 | $qr->base64() |
全局辅助函数
使用composer require后,全局函数自动加载:
// 数组函数 arr_first([1, 2, 3]); // 结果: 1 arr_last([1, 2, 3]); // 结果: 3 arr_find([1, 2, 3], fn($n) => $n > 1); // 结果: 2 arr_random([1, 2, 3]); // 结果: 随机一个元素 arr_deep_merge(['a' => 1], ['b' => 2]); // 结果: ['a' => 1, 'b' => 2] arr_pluck($array, 'name'); // 结果: 提取的列值数组 arr_to_tree($list, 'id', 'parent_id', 'children'); // 结果: 树形结构 arr_from_tree($tree, 'children'); // 结果: 扁平数组 arr_multi_sort($array, ['created_at'], ['desc']); // 结果: 排序后的数组 // 字符串函数 str_mask_phone('13800138000'); // 结果: 138****8000 str_mask_phone('13800138000', 2, 2); // 结果: 13*******00 str_mask_email('user@example.com'); // 结果: us**@example.com str_mask_id_card('110101199001011234'); // 结果: 110101********1234 str_mask_keep('张三你吃了吗', 1, 1); // 结果: 张****吗 str_to_base64('hello'); // 结果: aGVsbG8= str_from_base64('aGVsbG8='); // 结果: hello str_truncate('abcdefghijk', 5); // 结果: abcde... str_limit_length('你好世界', 3); // 结果: 你好... str_mb_strcut('张三你吃了吗', 0, 6); // 结果: 张三 str_camel('hello_world'); // 结果: helloWorld str_snake('helloWorld'); // 结果: hello_world str_starts_with('hello', 'he'); // 结果: true str_ends_with('hello', 'lo'); // 结果: true str_contains('hello world', 'world'); // 结果: true str_uuid(); // 结果: 50f53907-b0e9-4c5c-9b67-8ec6aa888c5e str_uuid_batch(5, '9999'); // 结果: ['1234', '5678', ...] str_ordered_uuid(); // 结果: 018f3b5c4d3e12f4 str_code('XXXX-9999'); // 结果: 3A7F-4821 str_validate_plate('京A12345'); // 结果: true // 时间函数 time_now(); // 结果: 2026-04-01 08:40:15 time_today(); // 结果: 2026-04-01 time_yesterday(); // 结果: 2026-03-31 time_tomorrow(); // 结果: 2026-04-02 time_diff_for_humans('2024-01-01'); // 结果: 2年前 // 数学函数 math_set_default_scale(4); math_get_default_scale(); // 结果: 4 math_add('1.1', '2.2'); // 结果: 3.3000 math_add('1.1', '2.2', 2); // 结果: 3.30 math_sub('5.5', '3.3'); // 结果: 2.2000 math_mul('1.5', '2.5'); // 结果: 3.7500 math_div('10', '3'); // 结果: 3.3333 math_discount('100', '0.8'); // 结果: 80.00 math_tax('100', '0.13'); // 结果: 13.00 math_average([1, 2, 3, 4, 5]); // 结果: 3.0000 math_median([1, 2, 3, 4, 5]); // 结果: 3.0000 // 地理位置函数 geo_distance(39.9042, 116.4074, 31.2304, 121.4737); // 结果: 1068.5058062575(北京到上海距离,单位:公里) geo_distance(39.9042, 116.4074, 31.2304, 121.4737, 'm'); // 结果: 1068505.8062575(单位:米) geo_is_valid(39.9042, 116.4074); // 结果: true // IP函数 ip_get(); // 结果: 127.0.0.1(客户端IP) ip_get_real(); // 结果: 真实客户端IP(支持代理) ip_is_valid('192.168.1.1'); // 结果: true ip_is_private('192.168.1.1'); // 结果: true ip_is_public('8.8.8.8'); // 结果: true ip_in_cidr('192.168.1.1', '192.168.1.0/24'); // 结果: true ip_in_range('192.168.1.100', '192.168.1.1-192.168.1.200'); // 结果: true // 安全函数 security_rate_limit('api:user_123', 5, 60); // 结果: true / false security_rate_limit_available('api:user_123', 5, 60); // 结果: 剩余次数 security_rate_limit_storage(new \Kode\Security\Storage\MemoryStorage()); // 结果: 切换限速存储后端 security_csrf_token(); // 结果: 32位随机Token security_sign(['user_id' => 1], 'your_secret_key_16chars'); // 结果: HMAC签名 security_input('age', 0, 'int', 'get'); // 结果: 过滤后的整数 security_xss_clean('<script>alert(1)</script>'); // 结果: 清理后的字符串 security_fingerprint(); // 结果: 64位十六进制请求指纹 $nonce = security_nonce('api', 300); security_verify_nonce($nonce, 'api', 300); // 结果: true(首次)/ false(重复) // HTTP请求函数 curl_get('https://api.example.com/users', ['page' => 1]); // 结果: Response对象 curl_post('https://api.example.com/users', ['name' => '张三']); // 结果: Response对象 // 二维码函数 qr_text('https://example.com')->save('qrcode.png'); // 结果: 保存二维码图片 qr_wifi('MyWiFi', 'password123')->base64(); // 结果: Base64编码的二维码 // 辅助函数 uuid(); // 结果: 06c32c05-c0e8-4e9e-b80f-3919404f923c random_string(16); // 结果: xK7d9f2mAb3cL5nP
高并发使用建议
本项目已针对 FPM、Swoole、FrankenPHP、Workerman 等运行环境做以下并发安全处理:
Message无状态化:Message::静态链式调用每次都会创建新的实例,不共享实例状态,避免长生命周期服务中的请求间状态泄漏。- 限速存储可切换:默认
FileStorage使用flock文件锁实现滑动窗口计数,可直接用于多进程/多 worker 环境;单机高并发建议切换为ApcuStorage,分布式部署建议切换为RedisStorage。 - Crypto 实例复用:
(new Crypto($key))实例可安全复用,但密钥不应在请求间共享不同业务密钥。 - 建议组合:
use Kode\Message\Message; use Kode\Security\Security; // 在控制器入口统一限速 if (!Security::rateLimit('api:' . Ip::get(), 100, 60)) { return Message::code(429)->msg('请求过于频繁')->result(); } // 业务响应 return Message::data(['id' => 1])->page(1)->total(100)->result();
许可证
MIT License