174 lines
4.7 KiB
Markdown
174 lines
4.7 KiB
Markdown
# 3.4 验证器开发
|
|
|
|
:::tip 概述
|
|
验证器用于校验请求参数的合法性,继承 ThinkPHP 的 Validate 类。通过在 Logic 层配置 `$validateClass` 属性,`add`/`update` 时自动触发校验,无需手动调用。
|
|
:::
|
|
|
|
## 验证器文件位置
|
|
|
|
```text
|
|
app/validate/ExampleValidate.php
|
|
```
|
|
|
|
## 完整代码(来自项目实际代码)
|
|
|
|
```php
|
|
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace app\validate;
|
|
|
|
use think\Validate;
|
|
|
|
/**
|
|
* 案例演示验证器
|
|
*
|
|
* 负责案例演示模块的入参校验,继承 ThinkPHP 的 Validate。
|
|
*
|
|
* 结构说明:
|
|
* - $rule:字段校验规则,由必填字段自动推导;
|
|
* - $message:自定义错误提示,按"字段.规则"生成中文提示;
|
|
* - $scene:场景化校验,add 与 update 使用相同的字段集。
|
|
*
|
|
* 说明:唯一性校验未写入本验证器,
|
|
* 由 ExampleLogic 的 uniqueFields 在逻辑层完成。
|
|
*/
|
|
class ExampleValidate extends Validate
|
|
{
|
|
/**
|
|
* 校验规则
|
|
*
|
|
* 由生成器按字段的必填属性自动推导,
|
|
* 通常形如 '字段名' => 'require'。
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $rule = [
|
|
'name' => 'require',
|
|
];
|
|
|
|
/**
|
|
* 自定义错误提示
|
|
*
|
|
* 键为"字段名.规则名",值为中文提示语,
|
|
* 覆盖框架默认提示,提升用户可读性。
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $message = [
|
|
'name.require' => '请输入案例名称',
|
|
];
|
|
|
|
/**
|
|
* 校验场景
|
|
*
|
|
* add 与 update 使用相同的字段集,
|
|
* 与项目其它验证器的统一模式保持一致。
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $scene = [
|
|
'add' => ['name'], // 新增场景
|
|
'update' => ['name'], // 修改场景
|
|
];
|
|
}
|
|
```
|
|
|
|
## 在 Logic 中配置自动验证(推荐)
|
|
|
|
在 Logic 子类中配置 `$validateClass` 属性,`add`/`update` 时自动调用对应验证器:
|
|
|
|
```php
|
|
// app/logic/ExampleLogic.php
|
|
class ExampleLogic extends BaseLogic
|
|
{
|
|
/**
|
|
* 关联的模型类
|
|
*
|
|
* @var string
|
|
*/
|
|
protected string $modelClass = Example::class;
|
|
|
|
/**
|
|
* 参数验证器类
|
|
*
|
|
* 配置后,add/update 自动校验
|
|
*
|
|
* @var string
|
|
*/
|
|
protected string $validateClass = \app\validate\ExampleValidate::class;
|
|
|
|
// ... 其他属性
|
|
}
|
|
```
|
|
|
|
**工作原理:**
|
|
|
|
1. `add()` 流程:`beforeAdd` → `validateData($data, 'add')` → 后续入库
|
|
2. `update()` 流程:`beforeUpdate` → `validateData($data, 'update', $id)` → 后续入库
|
|
3. 验证器按场景(`add`/`update`)校验,场景不存在时使用默认规则
|
|
4. 校验失败抛出 `ValidateException`,由 `ExceptionHandle` 统一返回错误响应
|
|
|
|
**覆盖范围:** 无论是 Controller 通过 `_add`/`_edit` 调用,还是 `import` 等内部调用都会生效。
|
|
|
|
## 在 Controller 中手动调用(特殊场景)
|
|
|
|
对于不走 `BaseLogic.add()`/`update()` 的特殊接口(如登录),可在 Controller 中手动调用:
|
|
|
|
```php
|
|
// app/controller/LoginController.php
|
|
public function login(): Json
|
|
{
|
|
$params = $this->getParams();
|
|
try {
|
|
$this->validate($params, LoginValidate::class . '.login');
|
|
} catch (\Exception $e) {
|
|
return $this->fail($e->getMessage(), 422);
|
|
}
|
|
// ... 登录逻辑
|
|
}
|
|
```
|
|
|
|
## 常用验证规则
|
|
|
|
| 规则 | 说明 | 示例 |
|
|
|------|------|------|
|
|
| `require` | 必填 | `'name' => 'require'` |
|
|
| `max:n` | 最大长度 | `'title' => 'max:200'` |
|
|
| `min:n` | 最小长度 | `'password' => 'min:6'` |
|
|
| `number` | 数字 | `'sort' => 'number'` |
|
|
| `integer` | 整数 | `'age' => 'integer'` |
|
|
| `in:a,b,c` | 枚举值 | `'status' => 'in:0,1'` |
|
|
| `email` | 邮箱格式 | `'email' => 'email'` |
|
|
| `mobile` | 手机号格式 | `'mobile' => 'mobile'` |
|
|
| `unique:table` | 唯一性 | `'username' => 'unique:user'` |
|
|
|
|
## 场景(Scene)用法
|
|
|
|
场景允许在不同接口使用不同的验证规则。项目统一使用 `$scene` 属性定义:
|
|
|
|
```php
|
|
class UserValidate extends Validate
|
|
{
|
|
protected $rule = [
|
|
'username' => 'require|unique:user',
|
|
'realname' => 'require',
|
|
'mobile' => 'mobile',
|
|
'email' => 'email',
|
|
];
|
|
|
|
protected $message = [
|
|
'username.require' => '用户名不能为空',
|
|
'username.unique' => '用户名已存在',
|
|
'realname.require' => '姓名不能为空',
|
|
];
|
|
|
|
// 场景属性:指定每个场景校验哪些字段
|
|
protected $scene = [
|
|
'add' => ['username', 'realname', 'mobile', 'email'],
|
|
'update' => ['realname', 'mobile', 'email'], // 修改时不校验 username
|
|
];
|
|
}
|
|
```
|
|
|
|
**自动场景匹配:** Logic 配置了 `$validateClass` 后,`add()` 自动使用 `add` 场景,`update()` 自动使用 `update` 场景,无需手动指定。 |