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

Laravel 7.x自定义数组验证:验证设备归属所选设备厂商

解决Laravel中设备与所属公司的动态验证问题

嘿,我来帮你搞定这个验证问题!你遇到的核心问题是Laravel默认的exists规则没法动态引用请求数组里同层级的其他字段,所以咱们得用自定义逻辑来确保每个device_id确实属于对应的device_company_id,防止恶意篡改。

方法一:使用闭包结合默认exists规则(更简洁)

不需要单独创建规则类,直接在验证规则里用闭包动态添加查询条件:

use Illuminate\Validation\Rule;

// 你的原有规则合并逻辑
$rules = array_merge($rules, [
    'devices' => [
        'required',
        'array'
    ],
    'devices.*.device_company_id' => [
        'required',
        'integer',
        'exists:device_companies,id,company_id,' . auth()->user()->id
    ],
    'devices.*.device_id' => [
        'required',
        'integer',
        Rule::exists('devices', 'id')->where(function ($query) use ($attribute) {
            // 从字段名中提取数组索引,比如从"devices.0.device_id"拿到索引0
            $index = explode('.', $attribute)[1];
            // 获取当前设备对应的device_company_id
            $deviceCompanyId = request()->input("devices.{$index}.device_company_id");
            // 添加查询条件:设备必须属于指定的device_company_id
            $query->where('device_company_id', $deviceCompanyId);
        })
    ],
]);

方法二:创建自定义验证规则类(更易复用)

如果这个验证逻辑在多个地方用到,推荐单独创建规则类:

1. 生成规则类

运行Artisan命令:

php artisan make:rule DeviceBelongsToCompany

2. 编写规则逻辑

修改app/Rules/DeviceBelongsToCompany.php:

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\DB;

class DeviceBelongsToCompany implements Rule
{
    protected $deviceCompanyId;

    // 构造函数接收对应的device_company_id
    public function __construct($deviceCompanyId)
    {
        $this->deviceCompanyId = $deviceCompanyId;
    }

    // 验证逻辑:检查设备是否属于指定公司
    public function passes($attribute, $value)
    {
        return DB::table('devices')
            ->where('id', $value)
            ->where('device_company_id', $this->deviceCompanyId)
            ->exists();
    }

    // 自定义错误提示信息
    public function message()
    {
        return '所选设备不属于指定的设备公司,请检查输入。';
    }
}

3. 在验证规则中使用自定义规则

// 你的原有规则合并逻辑
$rules = array_merge($rules, [
    'devices' => [
        'required',
        'array'
    ],
    'devices.*.device_company_id' => [
        'required',
        'integer',
        'exists:device_companies,id,company_id,' . auth()->user()->id
    ],
    'devices.*.device_id' => [
        'required',
        'integer',
        function ($attribute, $value, $fail) {
            // 提取数组索引
            $index = explode('.', $attribute)[1];
            $deviceCompanyId = request()->input("devices.{$index}.device_company_id");
            
            // 实例化自定义规则并验证
            $rule = new \App\Rules\DeviceBelongsToCompany($deviceCompanyId);
            if (!$rule->passes($attribute, $value)) {
                $fail($rule->message());
            }
        }
    ],
]);

为什么原有写法不行?

Laravel默认的exists规则参数是静态值,无法动态引用请求中同层级的其他字段(比如devices.*.device_company_id),所以必须通过闭包或自定义规则来实现这种动态关联验证,确保请求数据的合法性。

内容的提问来源于stack exchange,提问作者Mr.Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 09:57:51