Laravel怎么使用Validator验证器_Laravel独立验证逻辑教程【分离】

7次阅读

laravel validator 可在 service、job 等任意位置通过 validator::make() 手动调用,无需绑定控制器;validate() 失败抛异常,validated() 仅在校验通过后返回安全数据;unique 规则需显式指定连接名(如 tenant.users)并处理软删除。

Laravel怎么使用Validator验证器_Laravel独立验证逻辑教程【分离】

不用专门“分离”验证逻辑,Laravel 的 Validator 本身就不绑定控制器 —— 直接在任何地方 new 或用 Validator::make() 就能用,所谓“独立验证”就是别写进 Controller 方法里硬编码。

怎么在 Service 或 Form Request 外手动调用 Validator

最常见需求:在 Service 类、Job、API 中间件或命令行里做数据校验,不走 FormRequest 流程。

  • Validator::make() 是最轻量方式,返回 Validator 实例,可链式调用 validate()(失败抛异常)或 fails()(手动判断)
  • 别直接 new Validator,它依赖容器注入的 TranslationFinderPresenceVerifier,手动 new 容易报错
  • 如果需要复用规则,把规则数组抽成 private Static 属性或 config 文件,别塞在方法里
// 在 app/Services/UserService.php 里 use IlluminateSupportFacadesValidator;  public function createFromRawData(array $data) {     $validator = Validator::make($data, [         'email' => 'required|email|unique:users',         'age'   => 'NULLable|integer|min:13',     ]);      if ($validator->fails()) {         throw new ValidationException($validator);     }      return User::create($validator->validated()); }

validate()validated() 的关键区别

这两个方法看起来像一对,但行为差异直接影响错误处理和数据安全。

  • validate():立即校验,失败时抛出 ValidationException(自动被 Laravel 异常处理器转成 422 响应),适合你不想自己处理失败逻辑的场景
  • validated():只在已校验通过的前提下返回过滤后的数据;如果还没调用 validate() 或校验失败就调,会返回空数组 —— 不报错,但数据丢了,这点容易被忽略
  • 如果你用 fails() + errors() 手动处理,记得最后一定要调 validate() 或确保校验已执行,否则 validated() 拿不到干净数据

自定义规则写在哪?别放 AppRules 就完事

自定义规则不是“扔进 Rules 目录就自动可用”,注册和使用有隐含依赖。

  • 类名必须符合 PSR-4,且实现 Rule 接口(或继承 AbstractRule),否则 Validator::extend() 会静默失败
  • 如果用 Validator::extend('foo', ...) 动态注册,务必在服务提供者(如 AppServiceProvider@boot)里执行,不能在模型或控制器里临时注册 —— 否则测试时可能漏掉、队列里不可用
  • 闭包形式的自定义规则无法序列化,放进 Job 或缓存后会报 Serialization of closure is not allowed

为什么有时候 unique 规则查不到数据库

这不是规则本身问题,而是 unique 依赖 Laravel 的 DatabasePresenceVerifier,而它默认只连接 default 数据库连接。

  • 如果你的用户表在 tenant 连接上,但没显式指定,unique:users,email 会去查 default 库,永远返回“可用”
  • 正确写法是 unique:tenant.users,email(注意中间是英文点号),或者用数组语法:['unique:users,email,NULL,id,tenant_id,' . $tenantId]
  • 软删除模型加 withTrashed() 时,unique 默认不包含 deleted_at 字段,得配合 whereNull('deleted_at') 手动加条件,否则已被软删的邮箱仍被判定为“已存在”

真正麻烦的从来不是写验证规则,而是验证上下文 —— 数据来源(http?队列?命令?)、数据库连接、软删除状态、多租户隔离,这些不显式对齐,Validator 再灵活也救不了。

text=ZqhQzanResources