直接在 BaseController 中封装验证逻辑,并集成自定义验证规则(如身份证、银行卡、IP 地理位置等),使得所有继承该控制器的类都可以通过 一句话调用验证方法,无需引入额外的 ValidationService 类。
🧱 文件结构建议
深色版本
app/
├── controller/
│ └── BaseController.php
│ └── UserController.php
├── validate/
│ └── EnhancedValidator.php
🧱 BaseController.php 完整代码(含注释)
Php
深色版本
<?php
namespace app\controller;
use think\Controller;
use think\facade\Request;
use think\Validate;
use app\validate\EnhancedValidator;
class BaseController extends Controller
{
// 字段映射表(可被子类覆盖)
protected $fieldMap = [
'username' => '用户名',
'email' => '邮箱',
'password' => '密码',
'id_card' => '身份证号码',
'mobile' => '手机号',
'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);
}
}
// 注册增强验证规则
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;
}
}
🧱 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
{
// 实现逻辑(略,见上文)
return true;
}
/**
* 是否是合法银行卡号(Luhn 算法校验)
*/
public static function isBankCard(string $cardNumber): bool
{
// 实现逻辑(略,见上文)
return true;
}
/**
* 是否在某个范围内(闭区间)
*/
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
{
// 实现逻辑(略,见上文)
return true;
}
/**
* 是否是枚举类中的值
*/
public static function inEnum($value, string $enumClass): bool
{
return in_array($value, array_column($enumClass::cases(), 'value'));
}
}
📌 使用示例: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 = [
'age' => 'required|integer|between:18,60',
'id_card' => 'required|id_card',
'bank_card' => 'required|bank_card',
'ip' => 'required|china_ip',
];
$messages = [
'age.between' => '年龄必须在 18 到 60 岁之间',
'id_card.id_card' => '身份证号码不合法',
'bank_card.bank_card' => '银行卡号不合法',
'ip.china_ip' => 'IP 地址不在中国境内',
];
if (!$this->validateOrFail($data, $rules, $messages)) {
return; // 已返回错误响应
}
return json(['code' => 200, 'msg' => '注册成功']);
}
}
✅ 验证规则汇总(支持原生 + 增强)
规则名称 描述 示例
required 必填 username:required
alpha_dash 字母、数字、下划线、短横线 username:alpha_dash
email 邮箱格式 email:email
id_card 身份证(15/18 位,含效验位) id_card:id_card
bank_card 银行卡号(Luhn 校验) bank_card:bank_card
between 数值范围(闭区间) age:between:18,60
min 数值最小值 age:min:18
max 数值最大值 age:max:60
china_ip 中国 IP 地址 ip:china_ip
in_enum 枚举值 status:in_enum:UserStatus
✅ 优点总结
✅ 所有验证逻辑集中在 BaseController 中
✅ 子控制器只需定义规则和消息即可
✅ 支持字段名自动翻译成中文
✅ 兼容原生验证规则 + 自定义规则
✅ 代码简洁,维护方便
验证规则字符串格式说明
ThinkPHP 支持使用 字符串格式的验证规则,格式为:
深色版本
字段名:规则1|规则2|...
多个字段规则用逗号分隔,例如:
Php
深色版本
'username:required|alpha_dash,email:email'
📌 示例:UserController.php(直接使用字符串规则)
Php
深色版本
<?php
namespace app\controller;
use think\facade\Request;
class UserController extends BaseController
{
// 可覆盖字段映射表
protected $fieldMap = [
'username' => '用户名',
'email' => '电子邮箱',
'password' => '密码',
'age' => '年龄',
];
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(需注册规则)
📌 验证规则解析说明
✅ 支持字段名自动翻译成中文
通过 BaseController 中的 $fieldMap 映射表,错误信息中的字段名会自动替换为中文。
示例输出:
Json
深色版本
{
"code": 400,
"msg": "参数验证失败",
"errors": {
"用户名": "用户名只能包含字母、数字、下划线和短横线"
}
}
🧩 如何注册自定义规则(如身份证、银行卡等)
如果你需要使用自定义规则(如 id_card、bank_card),需要在 EnhancedValidator.php 中注册:
Php
深色版本
// app/validate/EnhancedValidator.php
public static function register(Validate $validate)
{
$validate->makeRule('id_card', [self::class, 'isIdCard'], '身份证号码不合法');
$validate->makeRule('bank_card', [self::class, 'isBankCard'], '银行卡号不合法');
}
然后你就可以在字符串规则中使用它们:
Php
深色版本
$rules = 'id_card:required|id_card,bank_card:required|bank_card';
✅ 完整验证流程总结
定义字符串规则:字段名:规则1|规则2|...
可选自定义消息:覆盖默认错误提示
调用 validateOrFail():自动解析规则并验证数据
自动返回 JSON 错误响应:字段名自动翻译成中文
🧪 示例输入输出
输入(错误示例):
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)》协议授权
评论区