如何在Laravel中创建自定义的Validation Rule? (验证规则对象)

11次阅读

推荐使用 php artisan make:rule 命令创建验证规则类,生成于 app/Rules 目录,需实例化后在验证规则数组中使用(如 new UppercaseFirstLetter),不可直接写类名字符串;passes() 返回布尔值,message() 支持 :attribute 占位符;跨字段校验应通过构造函数传参并谨慎访问 $this->validator?->getData(),优先考虑在 Form Request 的 withValidator() 中处理。

如何在Laravel中创建自定义的Validation Rule? (验证规则对象)

可以直接用 php artisan make:rule 命令生成验证规则类,这是 laravel 官方推荐且最干净的做法,比闭包或匿名函数更易复用、测试和维护。

用 Artisan 命令创建 Rule 类

Laravel 5.5+ 内置了 make:rule 命令,会自动生成符合约定的类文件到 app/Rules 目录(Laravel 9+ 默认在 app/Rules;旧版本可能需手动创建该目录)。

执行命令:

php artisan make:rule UppercaseFirstLetter

生成的类默认包含 passes()message() 两个方法,你只需填充逻辑即可。注意:passes() 必须返回布尔值,false 表示验证失败。

  • passes($Attribute, $value):第一个参数是字段名(如 name),第二个是实际提交的值
  • message() 返回字符串,支持占位符如 :attribute,会被自动替换为字段中文名(需在 resources/lang/xx/validation.php 中配置)
  • 若需访问整个请求数据,可在构造函数中接收 Request 或使用 $this->validator(需在 validateWithBag 等上下文中才可用,不推荐强依赖)

在 Form Request 或 validate() 中使用 Rule 实例

Rule 类不是自动注册的,必须实例化后传入验证规则数组。不能直接写类名字符串,也不能漏掉 new

错误写法:

['name' => 'required|UppercaseFirstLetter'] // ❌ 不识别自定义类名

正确写法(在控制器中):

use AppRulesUppercaseFirstLetter;  $request->validate([     'name' => ['required', new UppercaseFirstLetter], ]);

FormRequestrules() 方法中同理:

public function rules() {     return [         'title' => ['required', new UppercaseFirstLetter],     ]; }
  • 多个 Rule 可以链式组合,顺序即执行顺序
  • 如果 Rule 需要参数(比如最小长度),在 __construct() 中定义,并在 new UppercaseFirstLetter($min) 中传入
  • 不要在 message() 中硬编码字段名,始终用 :attribute

Rule 类中访问其他字段值(如确认密码、日期范围)

单纯靠 $attribute$value 无法获取其他字段。此时需借助 $this->validator —— 但这个属性只在 Rule 被 Validator 实例调用时才被注入,且文档未公开保证其稳定性。

更可靠的方式是:在 Rule 构造时传入依赖字段名,再通过 $this->validator?->getData() 获取全部输入(需判空):

class DateAfter implements Rule {     protected $dateField;      public function __construct(string $dateField)     {         $this->dateField = $dateField;     }      public function passes($attribute, $value): bool     {         $data = $this->validator?->getData() ?? [];         $otherDate = $data[$this->dateField] ?? null;          return $value > $otherDate;     }      public function message(): string     {         return ':attribute must be after :date_field.';     } }
  • 使用时:new DateAfter('start_date')
  • $this->validator 是可选的,上线前务必加 ?-> 或判空,否则在单元测试或非标准调用下可能报 Call to a member function getData() on NULL
  • 这种跨字段校验更适合放在 Form Request 的 withValidator() 中做,Rule 类尽量保持单字段职责

Rule 类看似简单,但容易忽略 $this->validator 的生命周期和空值风险;多人协作时,建议在构造函数里明确声明依赖,而不是隐式从 validator 抽数据。

text=ZqhQzanResources