hyperf-plus/validate

hyperf-plus validate 基于 hyperf/validation 的路由验证适配器,支持注解式验证

Installs: 8 606

Dependents: 2

Suggesters: 2

Security: 0

Stars: 4

Watchers: 1

Forks: 2

Open Issues: 0

pkg:composer/hyperf-plus/validate

v4.0.1-beta 2025-12-05 06:24 UTC

README

基于 hyperf/validation 的路由验证适配器,支持注解式验证。

特性

  • 🚀 基于 Laravel Validation 规则,功能强大
  • 📝 注解式验证,代码简洁优雅
  • ⚡ 规则缓存,高性能
  • 🎯 专注路由验证,职责单一
  • 🔧 完全兼容 hyperf/validation 所有规则

安装

composer require hyperf-plus/validate

配置

1. 发布配置文件(可选)

php bin/hyperf.php vendor:publish hyperf-plus/validate

2. 安装语言包(必需)

composer require hyperf/translation
php bin/hyperf.php vendor:publish hyperf/translation

配置 config/autoload/translation.php

return [
    'locale' => 'zh_CN',
    'fallback_locale' => 'en',
    'path' => BASE_PATH . '/storage/languages',
];

使用方法

基础用法

<?php

namespace App\Controller;

use HPlus\Route\Annotation\PostApi;
use HPlus\Route\Annotation\ApiController;
use HPlus\Validate\Annotations\RequestValidation;

#[ApiController(prefix: '/api/users')]
class UserController
{
    #[PostApi(path: '')]
    #[RequestValidation(
        rules: [
            'name' => 'required|string|max:50',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|string|min:6|confirmed',
            'age' => 'nullable|integer|between:18,100',
        ],
        messages: [
            'name.required' => '用户名不能为空',
            'email.unique' => '该邮箱已被注册',
        ]
    )]
    public function create()
    {
        // 验证通过后的逻辑
        return ['message' => 'success'];
    }
}

验证模式

1. 验证请求体(rules)

验证 POST/PUT 请求体数据:

#[RequestValidation(
    rules: ['name' => 'required', 'email' => 'required|email']
)]

2. 验证查询参数(queryRules)

验证 URL 查询参数(GET 请求参数):

#[GetApi(path: '')]
#[RequestValidation(
    queryRules: [
        'page' => 'required|integer|min:1',
        'size' => 'required|integer|between:1,100',
        'keyword' => 'nullable|string|max:50',
    ]
)]
public function list()
{
    // ...
}

3. 同时验证 Query 和 Body

使用 queryRulesrules 分别验证:

#[PostApi(path: '/search')]
#[RequestValidation(
    queryRules: [
        'page' => 'required|integer|min:1',   // 验证 URL 查询参数
        'size' => 'required|integer|between:1,100',
    ],
    rules: [
        'filters' => 'nullable|array',        // 验证请求体
        'sort' => 'nullable|array',
    ]
)]
public function search()
{
    // ...
}

4. 请求体数据格式(mode)

mode 参数控制请求体数据的解析方式:

#[RequestValidation(
    rules: ['name' => 'required'],
    mode: 'json'  // 默认值,可选:json | form | xml
)]

自定义错误消息

#[RequestValidation(
    rules: [
        'email' => 'required|email',
        'password' => 'required|min:6',
    ],
    messages: [
        'email.required' => '邮箱地址不能为空',
        'email.email' => '邮箱格式不正确',
        'password.min' => '密码至少需要6个字符',
    ]
)]

自定义字段名称

#[RequestValidation(
    rules: [
        'user_email' => 'required|email',
    ],
    attributes: [
        'user_email' => '用户邮箱',
    ]
)]
// 错误消息将显示:"用户邮箱格式不正确",而不是"user_email格式不正确"

停止首个失败

默认验证所有字段,返回所有错误。如果只想返回第一个错误:

#[RequestValidation(
    rules: ['email' => 'required|email'],
    stopOnFirstFailure: true
)]

支持的验证规则

完全支持 Laravel Validation 所有规则,包括但不限于:

基础规则

  • required - 必填
  • nullable - 可为空
  • string - 字符串
  • integer - 整数
  • numeric - 数字
  • boolean - 布尔值
  • array - 数组
  • json - JSON 字符串

字符串规则

  • email - 邮箱格式
  • url - URL 格式
  • ip - IP 地址
  • uuid - UUID 格式
  • alpha - 纯字母
  • alpha_num - 字母和数字
  • alpha_dash - 字母、数字、破折号、下划线
  • regex:pattern - 正则表达式

数值规则

  • min:value - 最小值
  • max:value - 最大值
  • between:min,max - 范围
  • size:value - 大小
  • gt:field - 大于某字段
  • gte:field - 大于等于某字段
  • lt:field - 小于某字段
  • lte:field - 小于等于某字段

日期规则

  • date - 日期格式
  • date_format:format - 指定日期格式
  • before:date - 早于某日期
  • after:date - 晚于某日期
  • before_or_equal:date - 早于或等于
  • after_or_equal:date - 晚于或等于

数组规则

  • in:foo,bar,... - 在指定值中
  • not_in:foo,bar,... - 不在指定值中
  • array - 数组类型
  • distinct - 数组不重复

数据库规则

  • unique:table,column,except,idColumn - 唯一性
  • exists:table,column - 存在性

文件规则

  • file - 文件
  • image - 图片
  • mimes:jpg,png,... - 文件类型
  • max:value - 文件大小(KB)

关系规则

  • confirmed - 确认字段(需要 field_confirmation
  • same:field - 与某字段相同
  • different:field - 与某字段不同
  • required_if:field,value - 条件必填
  • required_with:field - 当某字段存在时必填
  • required_without:field - 当某字段不存在时必填

更多规则请参考:https://laravel.com/docs/validation#available-validation-rules

高级用法

自定义验证规则

config/autoload/dependencies.php 中扩展验证器:

use Hyperf\Validation\Contract\ValidatorFactoryInterface;
use Hyperf\Validation\ValidatorFactory;

return [
    ValidatorFactoryInterface::class => function ($container) {
        $factory = $container->get(ValidatorFactory::class);
        
        // 注册自定义规则
        $factory->extend('phone', function ($attribute, $value, $parameters, $validator) {
            return preg_match('/^1[3-9]\d{9}$/', $value);
        });
        
        // 自定义错误消息
        $factory->replacer('phone', function ($message, $attribute, $rule, $parameters) {
            return str_replace(':attribute', $attribute, ':attribute 必须是有效的手机号');
        });
        
        return $factory;
    },
];

使用自定义规则:

#[RequestValidation(
    rules: ['mobile' => 'required|phone']
)]

嵌套数组验证

#[RequestValidation(
    rules: [
        'users' => 'required|array',
        'users.*.name' => 'required|string',
        'users.*.email' => 'required|email',
        'users.*.age' => 'nullable|integer|min:18',
    ]
)]

条件验证

#[RequestValidation(
    rules: [
        'type' => 'required|in:person,company',
        'id_card' => 'required_if:type,person|size:18',
        'business_license' => 'required_if:type,company',
    ]
)]

性能优化

规则缓存

验证规则会在首次请求时解析并缓存在内存中,后续请求直接使用缓存,无需重复解析注解。

查看缓存统计

use HPlus\Validate\Aspect\ValidationAspect;

$stats = ValidationAspect::getCacheStats();
// [
//     'rule_hits' => 1000,
//     'rule_misses' => 10,
//     'total_requests' => 1010,
//     'rule_hit_rate' => '99.01%',
//     'rule_cache_size' => 10,
// ]

清空缓存

ValidationAspect::clearCache();

错误处理

验证失败会抛出 HPlus\Validate\Exception\ValidateException 异常,状态码为 422。

建议在全局异常处理器中统一处理:

<?php

namespace App\Exception\Handler;

use HPlus\Validate\Exception\ValidateException;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Psr\Http\Message\ResponseInterface;
use Throwable;

class ValidationExceptionHandler extends ExceptionHandler
{
    public function handle(Throwable $throwable, ResponseInterface $response)
    {
        if ($throwable instanceof ValidateException) {
            return $response
                ->withStatus(422)
                ->withHeader('Content-Type', 'application/json')
                ->withBody(new SwooleStream(json_encode([
                    'code' => 422,
                    'message' => $throwable->getMessage(),
                ], JSON_UNESCAPED_UNICODE)));
        }
        
        return $response;
    }

    public function isValid(Throwable $throwable): bool
    {
        return $throwable instanceof ValidateException;
    }
}

RuleParser(供 Swagger 使用)

RuleParser 类用于将验证规则转换为 JSON Schema,主要供 hyperf-plus/swagger 插件使用:

use HPlus\Validate\RuleParser;

// 单个规则转换
$schema = RuleParser::ruleToJsonSchema('required|string|max:50|email');
// ['type' => 'string', 'maxLength' => 50, 'format' => 'email']

// 批量规则转换
$schema = RuleParser::rulesToJsonSchema([
    'name|姓名' => 'required|string|max:50',
    'age|年龄' => 'nullable|integer|between:18,100',
]);
// 返回完整的 JSON Schema

与旧版本的区别

旧版(已弃用)

#[RequestValidation(
    rules: ['email' => 'required|email'],
    validate: UserValidator::class,  // ❌ 不再需要
    scene: 'create',                 // ❌ 不再需要
    filter: true,                    // ✅ 保留
    security: true,                  // ✅ 保留
    batch: true,                     // ✅ 改为 stopOnFirstFailure
    dateType: 'json'                 // ✅ 改为 mode
)]

新版(推荐)

#[RequestValidation(
    rules: ['email' => 'required|email'],  // ✅ 请求体验证规则
    queryRules: ['page' => 'integer'],     // ✅ 查询参数验证规则
    messages: [],                          // ✅ 自定义消息
    attributes: [],                        // ✅ 字段别名
    mode: 'json',                          // ✅ 请求体解析模式
    filter: false,                         // ✅ 过滤多余字段
    security: false,                       // ✅ 安全模式
    stopOnFirstFailure: false              // ✅ 停止策略
)]

参数说明

参数 类型 默认值 说明
rules array [] 请求体验证规则 (Laravel validation 规则)
queryRules array [] 查询参数验证规则
messages array [] 自定义错误消息
attributes array [] 字段别名(用于错误消息)
mode string 'json' 请求体数据解析模式:json / form / xml
filter bool false 是否过滤多余字段(只保留规则中定义的字段)
security bool false 安全模式(请求中有未定义字段时抛出异常)
stopOnFirstFailure bool false 是否在第一个失败时停止验证

迁移指南

如果你正在从旧版本迁移:

  1. ✅ 保留 rules 参数
  2. ❌ 移除 validatescene 参数(改用内联规则)
  3. ✅ 保留 filtersecurity 参数
  4. ✅ 将 dateType 改为 mode
  5. ✅ 将 batch: false 改为 stopOnFirstFailure: true

常见问题

1. 验证不生效?

检查是否正确安装了 hyperf/validationhyperf/translation

2. 错误消息是英文?

确保配置了中文语言包,参考"配置"部分。

3. 如何验证 GET 请求参数?

使用 queryRules 参数。

4. 如何同时验证 query 和 body?

同时使用 queryRules(验证查询参数)和 rules(验证请求体)。

License

Apache-2.0