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

基于双值的自定义规则:Region模型Tag唯一性验证规则创建

搞定Region模型Tag唯一性验证的方案

嘿,我明白你的需求了——Tag是由name和countries_id拼接成的小写字符串,得保证它唯一,而且是动态生成的,不能让用户传。咱们一步步来解决这个问题:

核心思路

因为Tag不是请求里直接传的参数,是咱们自己拼的,所以验证的关键是:先拿请求里的name和countries_id生成Tag,再去数据库里查这个Tag是不是已经存在。而且还要考虑更新场景,不能把当前编辑的记录当成重复项。

方案1:完善你已经在用的自定义验证规则

你已经写了RegionUniqueRule,那咱们直接改造这个规则类就行,让它自动处理Tag的生成和唯一性检查:

改造后的自定义规则类

use Illuminate\Contracts\Validation\Rule;
use App\Models\Region;

class RegionUniqueRule implements Rule
{
    public function passes($attribute, $value)
    {
        // 先从请求里拿到countries_id
        $countriesId = request()->input('countries_id');
        // 按照要求生成小写的Tag
        $tag = strtolower($value) . '-' . $countriesId;
        
        // 开始查数据库,看看有没有重复的Tag
        $query = Region::where('tag', $tag);
        
        // 如果是更新操作(比如传了id),要排除当前这条记录
        if ($id = request()->input('id')) {
            $query->where('id', '!=', $id);
        }
        
        // 没找到重复的就返回true,验证通过
        return $query->count() === 0;
    }

    public function message()
    {
        // 给用户友好的提示
        return '这个地区名称和国家的组合已经存在啦(重复的Tag)!';
    }
}

调整你的验证规则数组

然后把验证规则补全,别忘了给countries_id加必填和合法性验证(比如检查这个id是不是真的在countries表里存在):

return [
    'name' => ['required', new RegionUniqueRule()],
    'countries_id' => ['required', 'exists:countries,id'],
];

方案2:用Laravel内置的Unique规则,不用写自定义类

要是不想搞自定义规则,直接用Laravel自带的Rule::unique也能搞定,用闭包动态生成查询条件就行:

use Illuminate\Validation\Rule;

return [
    'name' => ['required'],
    'countries_id' => ['required', 'exists:countries,id'],
    // 给name加唯一性验证,通过闭包指定Tag的查询条件
    'name' => [
        'required',
        Rule::unique('regions')->where(function ($query) {
            // 生成要检查的Tag
            $tag = strtolower(request()->input('name')) . '-' . request()->input('countries_id');
            return $query->where('tag', $tag);
        })->ignore(request()->input('id')) // 更新时跳过当前记录
    ],
];

额外的小建议

  1. 数据库层面加保险:为了防止并发情况下出现重复Tag(比如两个请求同时验证通过,然后都插入数据库),记得给regions表的tag字段加唯一索引,这样数据库本身会帮咱们拦住重复数据。
  2. 自动生成Tag:在保存Region记录的时候,自动生成Tag,不用手动写:
// 在Region模型里加这段代码
protected static function boot()
{
    parent::boot();
    
    // 创建记录时自动生成Tag
    static::creating(function ($region) {
        $region->tag = strtolower($region->name) . '-' . $region->countries_id;
    });
    
    // 如果允许更新名称或国家ID,更新时也同步更新Tag
    static::updating(function ($region) {
        $region->tag = strtolower($region->name) . '-' . $region->countries_id;
    });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:46:26