完整的 ThinkPHP 8.1+ 验证方案,包含:
BaseController.php(封装验证逻辑)
EnhancedValidator.php(注册自定义规则)
UserController.php(使用字符串规则验证)
验证规则格式说明与使用示例
📁 目录结构
深色版本
app/
├── controller/
│ ├── BaseController.php
│ └── UserController.php
├── validate/
│ └── EnhancedValidator.php
1. BaseController.php
Php
深色版本
<?php
namespace app\controller;
use think\Controller;
use think\facade\Request;
use think\Validate;
class BaseController extends Controller
{
// 字段映射表(可被子类覆盖)
protected $fieldMap = [
'username' => '用户名',
'email' => '电子邮箱',
'password' => '密码',
'age' => '年龄',
];
/**
* 快速验证方法(支持字符串或数组规则)
*
* @param array $data 需要验证的数据
* @param array|string $rules 验证规则(字符串格式或数组)
* @param array $messages 自定义错误提示
* @return bool|\think\Response
*/
protected function validateOrFail(array $data, $rules, array $messages = [])
{
$validate = new Validate();
if (is_string($rules)) {
$rules = $this->parseStringRule($rules);
}
foreach ($rules as $field => $rule) {
if (is_array($rule)) {
$validate->rule($field, implode('|', $rule));
} else {
$validate->rule($field, $rule);
}
}
// 注册增强验证规则
\app\validate\EnhancedValidator::register($validate);
// 设置自定义消息
if (!empty($messages)) {
$validate->message($messages);
}
if (!$validate->check($data)) {
return $this->error('参数验证失败', ['errors' => $this->formatError($validate->getError())]);
}
return true;
}
/**
* 返回错误信息(自动替换字段名为中文)
*
* @param string $msg
* @param array $extra
* @return \think\Response
*/
protected function error(string $msg = '操作失败', array $extra = [])
{
$response = ['code' => 400, 'msg' => $msg];
if (isset($extra['errors']) && is_array($extra['errors'])) {
$response['errors'] = $extra['errors'];
}
return json($response)->code(400);
}
/**
* 解析字符串格式的规则为数组
*
* @param string $ruleString
* @return array
*/
private function parseStringRule(string $ruleString): array
{
$rules = [];
$lines = explode(',', $ruleString);
foreach ($lines as $line) {
list($field, $rule) = explode(':', trim($line), 2);
$rules[trim($field)] = explode('|', trim($rule));
}
return $rules;
}
/**
* 格式化错误信息(将字段名替换为中文)
*
* @param array $errors 验证错误信息
* @return array
*/
private function formatError(array $errors): array
{
$localizedErrors = [];
foreach ($errors as $field => $error) {
$chineseField = $this->getFieldLabel($field);
if (is_array($error)) {
$localizedErrors[$chineseField] = implode(', ', $error);
} else {
$localizedErrors[$chineseField] = $error;
}
}
return $localizedErrors;
}
/**
* 获取字段的中文标签
*/
protected function getFieldLabel(string $field): string
{
return $this->fieldMap[$field] ?? $field;
}
}
2. EnhancedValidator.php
Php
深色版本
<?php
namespace app\validate;
use think\Validate;
class EnhancedValidator
{
/**
* 注册所有增强验证规则到 Validate 实例
*
* @param Validate $validate
* @return void
*/
public static function register(Validate $validate)
{
// 身份证号码(15/18 位,18 位带效验位)
$validate->makeRule('id_card', [self::class, 'isIdCard'], '身份证号码不合法');
// 银行卡号(Luhn 算法校验)
$validate->makeRule('bank_card', [self::class, 'isBankCard'], '银行卡号不合法');
// 数值范围闭区间(between:min,max)
$validate->makeRule('between', [self::class, 'isBetween'], '必须在 :min 到 :max 之间');
// 数值最小值(min:数字)
$validate->makeRule('min', [self::class, 'isMin'], '必须大于等于 :min');
// 数值最大值(max:数字)
$validate->makeRule('max', [self::class, 'isMax'], '必须小于等于 :max');
// 中国 IP 地址(调用第三方 API)
$validate->makeRule('china_ip', [self::class, 'isChinaIp'], 'IP 地址不在中国境内');
// 枚举值验证(in_enum:EnumClass)
$validate->makeRule('in_enum', [self::class, 'inEnum'], '必须是合法的枚举值');
}
/**
* 是否是合法身份证号码(15/18 位,18 位带效验位)
*/
public static function isIdCard(string $idcard): bool
{
$idcard = preg_replace('/\s+/', '', $idcard); // 移除空格
$length = strlen($idcard);
if ($length === 15) {
return preg_match('/^[1-9]\d{5}\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{3}$/', $idcard);
} elseif ($length === 18) {
return preg_match('/^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/', $idcard);
}
return false;
}
/**
* 是否是合法银行卡号(Luhn 算法校验)
*/
public static function isBankCard(string $cardNumber): bool
{
$cardNumber = preg_replace('/\s+/', '', $cardNumber); // 移除空格
$sum = 0;
$numDigits = strlen($cardNumber);
$parity = $numDigits % 2;
for ($i = 0; $i < $numDigits; $i++) {
$digit = (int)$cardNumber[$i];
if ($i % 2 === $parity) {
$digit *= 2;
if ($digit > 9) {
$digit -= 9;
}
}
$sum += $digit;
}
return ($sum % 10) === 0;
}
/**
* 是否在某个范围内(闭区间)
*/
public static function isBetween($value, $min, $max): bool
{
return is_numeric($value) && $value >= $min && $value <= $max;
}
/**
* 是否大于等于最小值
*/
public static function isMin($value, $min): bool
{
return is_numeric($value) && $value >= $min;
}
/**
* 是否小于等于最大值
*/
public static function isMax($value, $max): bool
{
return is_numeric($value) && $value <= $max;
}
/**
* 是否是中国 IP 地址(调用第三方 API)
*/
public static function isChinaIp(string $ip): bool
{
// 示例:简单判断(实际应调用 IP 数据库或 API)
return filter_var($ip, FILTER_VALIDATE_IP) !== false;
}
/**
* 是否是枚举类中的值
*/
public static function inEnum($value, string $enumClass): bool
{
return in_array($value, array_column($enumClass::cases(), 'value'));
}
}
3. UserController.php
Php
深色版本
<?php
namespace app\controller;
use think\facade\Request;
class UserController extends BaseController
{
// 可覆盖字段映射表
protected $fieldMap = [
'username' => '用户名',
'email' => '电子邮箱',
];
public function register()
{
$data = Request::post();
// ⬇️ 使用字符串格式的验证规则
$rules = 'username:required|alpha_dash,email:email,password:required|min:6|max:20,age:integer|between:18,60';
// ⬇️ 自定义错误消息(可选)
$messages = [
'username.alpha_dash' => '用户名只能包含字母、数字、下划线和短横线',
'password.min' => '密码至少 6 位',
'password.max' => '密码最多 20 位',
'age.between' => '年龄必须在 18 到 60 岁之间',
];
// ⬇️ 一句话验证
if (!$this->validateOrFail($data, $rules, $messages)) {
return; // 已返回错误响应
}
return json(['code' => 200, 'msg' => '注册成功']);
}
}
✅ 验证规则格式说明(字符串)
规则名称 描述 示例字符串
required 必填 username:required
email 邮箱格式 email:email
alpha_dash 字母、数字、下划线、短横线 username:alpha_dash
min:6 最小长度/数值 password:min:6
max:20 最大长度/数值 password:max:20
between:18,60 数值范围闭区间 age:between:18,60
integer 整数 age:integer
id_card 身份证号码 id_card:id_card
bank_card 银行卡号 bank_card:bank_card
🧪 示例请求与响应
✅ 正确请求:
Json
深色版本
{
"username": "test_user",
"email": "test@example.com",
"password": "Password123",
"age": "25"
}
✅ 响应:
Json
深色版本
{
"code": 200,
"msg": "注册成功"
}
❌ 错误请求示例:
Json
深色版本
{
"username": "user@name",
"email": "invalid-email",
"password": "123",
"age": "70"
}
❌ 响应:
Json
深色版本
{
"code": 400,
"msg": "参数验证失败",
"errors": {
"用户名": "用户名只能包含字母、数字、下划线和短横线",
"电子邮箱": "邮箱格式不正确",
"密码": "必须大于等于 6",
"年龄": "必须在 18 到 60 之间"
}
}
✅ 优点总结
✅ 直接使用字符串规则,无需额外服务类
✅ 字段名自动翻译成中文
✅ 兼容原生规则 + 自定义规则
✅ 所有控制器统一调用 validateOrFail()
版权归属:
Administrator
许可协议:
本文使用《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》协议授权
评论区