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

可以直接用 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 App\Rules\UppercaseFirstLetter;
$request->validate([
'name' => ['required', new UppercaseFirstLetter],
]);
在 FormRequest 的 rules() 方法中同理:
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 抽数据。










