You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Laravel FormRequest验证中获取其他字段的值

仓库物料出库验证中获取对应物料ID的方法

问题背景

我有仓库物料出库的输入数据如下:

[
    "movement_date" => "2022-09-08",
    "type" => "1",
    "transaction_number" => "OUTBOUND-001",
    "remarks" => "Moved to another warehouse",
    "items" => [
        0 => [
            "material_id" => "47",
            "uom" => "Kilogram",
            "qty" => "1000",
        ],
        1 => [
            "material_id" => "16",
            "uom" => "Kilogram",
            "qty" => "500",
        ],
    ],
]

我尝试在FormRequest中检查每个物料的剩余库存,代码如下:

return [
    'type' => 'required',
    'movement_date' => ['required','date', function ($attribute, $value, $fail) {
        if ($value > Carbon::now()->format('Y-m-d')) $fail('Invalid date '.Carbon::now()->format('Y-m-d'));
    }],
    'items' => 'required|array',
    'items.*.material_id' => 'required',
    'items.*.qty' => ['required', function ($attribute, $value, $fail) {
        $stock = \App\Models\MaterialStock::where('material_id', 'I need material id from material_id field here')->first();

        $stock === null ? $balance = 0 : $balance = $stock->qty;
        
        if ($balance < $value) $fail('Insufficient stock');
    }],
];

我的问题是:在验证qty字段时,如何获取对应的material_id值?


解决方案

方法一:通过验证闭包的$validator参数获取

验证闭包支持第四个参数$validator,它包含所有请求数据。你可以从字段名中提取索引,再通过索引获取对应item的material_id:

'items.*.qty' => ['required', function ($attribute, $value, $fail, $validator) {
    // 拆分字段名,比如从"items.0.qty"中提取索引0
    $parts = explode('.', $attribute);
    $index = $parts[1];
    
    // 获取当前item的material_id
    $materialId = $validator->getData()['items'][$index]['material_id'];
    
    $stock = \App\Models\MaterialStock::where('material_id', $materialId)->first();
    $balance = $stock ? $stock->qty : 0;
    
    if ($balance < $value) {
        $fail("物料ID {$materialId} 的库存不足,当前剩余 {$balance},请求出库 {$value}");
    }
}],

方法二:使用自定义验证规则(复用性更强)

创建一个自定义验证规则类,专门处理库存校验:

  1. 生成规则类:
php artisan make:rule StockAvailable
  1. 编写规则逻辑:
namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use App\Models\MaterialStock;

class StockAvailable implements ValidationRule
{
    protected $materialId;

    public function __construct($materialId)
    {
        $this->materialId = $materialId;
    }

    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        $stock = MaterialStock::where('material_id', $this->materialId)->first();
        $balance = $stock ? $stock->qty : 0;

        if ($balance < $value) {
            $fail("物料ID {$this->materialId} 的库存不足,当前剩余 {$balance},请求出库 {$value}");
        }
    }
}
  1. 在FormRequest中使用:
use App\Rules\StockAvailable;

// ...

return [
    // 其他验证规则...
    'items' => 'required|array',
    'items.*.material_id' => 'required',
    'items.*.qty' => ['required', function ($attribute, $value, $fail, $validator) {
        $parts = explode('.', $attribute);
        $index = $parts[1];
        $materialId = $validator->getData()['items'][$index]['material_id'];
        
        // 应用自定义规则
        (new StockAvailable($materialId))->validate($attribute, $value, $fail);
    }],
];

方法三:使用withValidator批量验证(性能更优)

通过FormRequest的withValidator方法,在验证完成后批量处理库存校验,还能减少数据库查询次数:

protected function withValidator($validator)
{
    $validator->after(function ($validator) {
        $items = $validator->getData()['items'] ?? [];
        if (empty($items)) return;
        
        // 收集所有物料ID,批量查询库存
        $materialIds = array_column($items, 'material_id');
        $stockMap = \App\Models\MaterialStock::whereIn('material_id', $materialIds)
            ->pluck('qty', 'material_id')
            ->toArray();
            
        foreach ($items as $index => $item) {
            $materialId = $item['material_id'];
            $qty = $item['qty'];
            $balance = $stockMap[$materialId] ?? 0;
            
            if ($balance < $qty) {
                $validator->errors()->add("items.{$index}.qty", "物料ID {$materialId} 的库存不足,当前剩余 {$balance},请求出库 {$qty}");
            }
        }
    });
}

这种方法只需要一次数据库查询,比逐个查询效率更高,适合批量出库场景。


内容的提问来源于stack exchange,提问作者owf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 15:50:27