必须引入自定义验证规则,方法包括:一、make:rule 创建可复用规则类;二、validator::extend() 注册全局字符串规则;三、验证数组嵌入匿名闭包;四、实现dataawarerule访问全部请求数据;五、formrequest中withvalidator()动态添加逻辑。

如果您在 Laravel 项目中需要对表单字段执行内置规则无法覆盖的业务校验逻辑,则必须引入自定义验证规则。以下是实现该目标的多种方法:
一、使用 php artisan make:rule 创建独立规则类
此方式生成结构清晰、可测试、可复用的验证规则类,适用于中大型项目或需跨多个控制器/请求复用的场景。规则类位于 app/Rules 目录,严格遵循 Laravel 的 Rule 接口契约。
1、在终端执行命令生成规则类:php artisan make:rule ValidPhoneNumber
2、打开 app/Rules/ValidPhoneNumber.php,修改 passes() 方法,填入中国大陆手机号正则校验逻辑:return preg_match('/^1[3-9]\d{9}$/', $value) === 1;
3、在 message() 方法中返回中文提示:return '请输入有效的中国大陆手机号码';
4、在控制器验证逻辑中实例化使用:use App\Rules\ValidPhoneNumber; $request->validate(['phone' => ['required', new ValidPhoneNumber]]);
二、通过 Validator::extend() 注册全局规则
该方式将规则注册为字符串形式(如 'phone_zh'),可在任意验证数组中以管道符语法调用,适合轻量级、全站通用的正则类规则,但不支持动态参数注入和跨字段访问。
1、在 app/Providers/AppServiceProvider.php 的 boot() 方法内调用 Validator::extend()
2、传入规则名 'phone_zh'、闭包回调及默认错误消息:Validator::extend('phone_zh', function ($attribute, $value, $parameters, $validator) { return preg_match('/^1[3-9]\d{9}$/', $value) === 1; });
3、在 resources/lang/zh_CN/validation.php 的 custom 数组中添加提示:'phone_zh' => ':attribute 格式不正确'
4、在验证数组中直接使用字符串:['phone' => 'required|phone_zh']
三、在验证数组中嵌入匿名闭包
此方式无需额外文件,适合仅在单一位置使用的临时性逻辑,例如拦截特定域名邮箱或基于当前请求状态的条件校验,但不可复用且难以单元测试。
1、在控制器 validate() 或 Validator::make() 调用中,于规则数组内插入闭包
2、闭包必须接收三个参数:$attribute、$value、$fail
3、当校验失败时,必须显式调用 $fail() 并传入错误消息,例如:$fail('邮箱域名不能为 example.com')
4、示例规则项:'email' => ['required', 'email', function ($attribute, $value, $fail) { if (strpos($value, 'example.com') !== false) { $fail('邮箱地址不能使用 example.com 域名'); } }]
四、实现 DataAwareRule 接口以访问全部请求数据
当验证逻辑需依赖其他字段值(如确认密码、日期范围比对)或整个请求上下文时,标准 Rule 接口无法满足,必须实现 DataAwareRule 并在 passes() 中通过 $this->data 访问完整请求数据。
1、执行命令生成规则类:php artisan make:rule ConfirmedPassword
2、让类同时实现 Rule 和 DataAwareRule 接口
3、在 passes() 方法中获取当前请求全部字段:$data = $this->data;
4、比对 password 和 password_confirmation 字段值:return $data['password'] === $data['password_confirmation'];
5、确保在验证数组中仍以 new 实例化方式调用,不可使用字符串语法
五、在 FormRequest 的 withValidator() 中动态添加验证逻辑
该方式绕过规则类机制,直接操作验证器实例,适用于需合并多字段错误至同一 error bag、或执行数据库查询类校验(如唯一性联合约束)等复杂场景,但会削弱规则封装性。
1、在自定义 FormRequest 类中重写 withValidator() 方法
2、通过 $validator->getRules() 获取原始规则配置
3、调用 $validator->after() 注册后置钩子,在其中执行跨字段逻辑
4、校验失败时使用 $validator->errors()->add('field', '错误消息内容')
5、注意:此方法中禁止调用 Validator::make() 或 new Validator,否则将破坏 Laravel 的错误包管理机制











