Files
rxthinkcmf-wiki/RXThinkCMF_Laravel13_EleVue/zh/guide/validator.md
T
2026-10-08 17:50:29 +08:00

5.7 KiB
Raw Blame History

3.4 FormRequest 验证器

:::tip 概述 参数格式验证由 FormRequest 完成(Laravel 标准机制):控制器方法类型注入请求类,未通过校验时框架自动返回统一 JSON 错误响应。所有请求类继承本项目的 BaseRequest,子类只需声明 rules() 与 messages()。 :::

请求类文件位置

app/Http/Requests/ExampleRequest.php

完整代码(来自项目实际代码)

<?php

namespace App\Http\Requests;

/**
 * 案例表单请求
 *
 * 负责案例演示新增/修改接口的参数校验。
 *
 * 说明:
 * - 继承 BaseRequest,基础校验能力(失败响应统一处理)由基类提供。
 * - 本类只声明案例特有的字段规则与自定义错误消息。
 * - 新增与修改共用本请求类,修改时由基类或控制器负责校验 id。
 * - 前端传参使用 camelCase,数据库字段为 snake_case;
 * - type 类型:1=类型1,2=类型2,3=类型3,4=类型4,
 *   与 Example 模型的约定一致。
 * - status 状态:1=在用,2=停用。
 */
class ExampleRequest extends BaseRequest
{
    /**
     * 校验规则
     *
     * @return array<string, string> 字段规则
     */
    public function rules(): array
    {
        return [
            'name' => 'required|string|max:255',       // 案例名称:必填,最长 255
            'avatar' => 'nullable|string|max:255',     // 头像/图片地址:可空,最长 255
            'type' => 'nullable|integer|in:1,2,3,4',   // 类型:1=类型1,2=类型2,3=类型3,4=类型4
            'status' => 'nullable|integer|in:1,2',     // 状态:1=在用,2=停用
            'sort' => 'nullable|integer',              // 排序值:可空,整数
        ];
    }

    /**
     * 自定义错误消息
     *
     * 为需要友好提示的规则提供中文消息,覆盖框架默认英文提示。
     *
     * @return array<string, string> 字段规则 => 错误消息
     */
    public function messages(): array
    {
        return [
            'name.required' => '案例名称不能为空',
            'name.max' => '案例名称不能超过 255 个字符',
            'avatar.max' => '图片地址不能超过 255 个字符',
            'type.in' => '案例类型不合法,允许:1-类型1 2-类型2 3-类型3 4-类型4',
            'status.in' => '状态值不合法,允许:1-在用 2-停用',
            'sort.integer' => '排序值格式不正确',
        ];
    }
}

控制器中的使用

// 类型注入:请求到达方法前自动完成校验
public function add(ExampleRequest $request): JsonResponse
{
    // validated() → 已校验数据,键名转换由 Service 写入入口统一完成
    return $this->_add($this->exampleService, $request->validated());
}

:::tip validated() 是白名单 validated() 只返回 rules() 中声明过的键,未声明的字段在进入控制器前即被丢弃。业务需要传递给 Service 的字段(如修改接口的 id、用户表单的 city / roles)都应在规则中声明,否则即使前端传了也到不了 Service。 :::

BaseRequest 基类提供的能力

app/Http/Requests/BaseRequest.php:

能力 说明
authorize() 统一返回 true 鉴权由路由中间件与 #[Permission] 注解负责,请求类不参与授权
failedValidation() 统一处理 校验失败返回固定 JSON:{"code":1,"ok":false,"msg":"参数验证失败","data":{字段=>错误数组}}(code=1 与 Controller::fail() 约定一致)

:::warning 两条校验失败路径

  • FormRequest 注入(本章方式)→ 失败响应 code=1;
  • 代码内手动 Validator::validate() 抛出的 ValidationException → 由全局 Handler 渲染为 code=422。

前端两种都应兼容(以 code !== 0 判失败)。详见 5.16 统一响应与异常抛出。 :::

常用验证规则

规则 说明 示例
required 必填 'name' => 'required'
string 字符串 'name' => 'string'
max:n 最大长度 'title' => 'max:200'
min:n 最小长度 'password' => 'min:6'
integer 整数 'sort' => 'integer'
in:a,b,c 枚举值 'status' => 'in:1,2'
nullable 可空(不传则跳过其余规则) 'avatar' => 'nullable|string'
email 邮箱格式 'email' => 'email'
date 日期格式 'start_time' => 'date'
regex:/.../ 正则 'code' => 'regex:/^[A-Za-z]+$/'

分层职责:格式 vs 业务

层 职责 示例
FormRequest(本章) 参数格式:必填、类型、长度、枚举 name 必填、type 只能 1-4
Service 层 参数业务规则:唯一性、状态依赖、权限 name 不能与已有记录重复

:::tip 唯一性为什么不放 FormRequest? uniqueFields 校验在 Service 层完成(HasUniqueCheck Trait),因为软删除场景下数据库唯一索引会误伤(is_delete=1 的旧记录仍占索引),且需要排除自身(update 场景)。见 3.5 Service 层开发。 :::

场景拆分(新增 vs 修改字段差异大时)

FormRequest 可按方法区分规则:

class UserRequest extends BaseRequest
{
    public function rules(): array
    {
        // 通过 $this->isMethod('post') 或自定义场景标识区分
        $rules = [
            'realname' => 'required|string|max:50',
            'mobile' => 'nullable|max:20',
        ];

        if ($this->isMethod('post')) {
            // 新增时才要求用户名
            $rules['username'] = 'required|string|min:3|max:50';
        }

        return $rules;
    }
}