Laravel 参数校验实战:用 FormRequest 把验证逻辑收拢到一处

test12026-09-160 次阅读

把校验从控制器里搬出来

新手常把校验写在控制器里,用 $request->validate([...]) 堆十几条规则。控制器越来越胖,而且同一个接口在后台和开放 API 复用时要重复写一遍规则。Laravel 的表单请求(FormRequest)正好解决这个:把规则、中文提示、授权判断封装成一个类,控制器只管业务。

生成并编写一个表单请求

// php artisan make:request StoreOrderRequest

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreOrderRequest extends FormRequest
{
    // 简单场景:登录用户才能下单
    public function authorize(): bool
    {
        return (bool) $this->user();
    }

    public function rules(): array
    {
        return [
            "product_id" => ["required", "integer", "exists:products,id"],
            "quantity"   => ["required", "integer", "min:1", "max:99"],
            "coupon"     => ["nullable", "string", "size:8"],
            "remark"     => ["nullable", "string", "max:200"],
        ];
    }

    // 自定义中文报错,避免前端拿到默认英文
    public function messages(): array
    {
        return [
            "product_id.exists" => "商品不存在或已下架",
            "quantity.max"      => "单次最多购买 99 件",
        ];
    }

    // 给校验后的字段起更友好的名字
    public function attributes(): array
    {
        return [
            "product_id" => "商品",
            "quantity"   => "购买数量",
        ];
    }
}

控制器里直接用

把类型提示换成这个 Request,校验失败会自动返回 422 且带上 messages() 的内容,控制器里完全不用写一句 validate。

use App\Http\Requests\StoreOrderRequest;

public function store(StoreOrderRequest $request)
{
    $data = $request->validated(); // 只返回通过校验的字段,自动过滤多余参数
    $order = Order::create($data);
    return response()->json(["code" => 0, "data" => $order]);
}

进阶:带条件与自定义规则

  • sometimes 规则:字段存在时才校验,适合 PATCH 部分更新。
  • Rule::unique 配合 ignore:编辑时排除自己,避免「邮箱已存在」误报。
  • 复杂逻辑用自定义规则类 php artisan make:rule PhoneCn,把正则与业务校验内聚。
"email" => ["required", "email", Rule::unique("users")->ignore($this->route("id"))],
"mobile" => ["sometimes", "string", new PhoneCn()],

为什么值得用

表单请求让「参数怎么才算合法」成为显式契约,前端联调、接口文档、开放平台都能直接参考 rules();控制器保持单薄,授权与校验失败时框架统一返回,不用在每个方法里重复 try/catch。项目越大,这个收益越明显。

T

test1

文章作者

把校验从控制器里搬出来 新手常把校验写在控制器里,用 $request->validate([...]) 堆十几条规则...

分类
技术
发布时间
2026-09-16
字数
约 1965 字
阅读
0 次