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

Laravel validation unique规则如何实现忽略大小写的唯一性校验

问题原因

你当前代码的核心问题是\Str::lower('name')仅对字符串'name'本身做小写转换,没有作用到数据库name字段的实际存储值,所以大小写比对逻辑完全没有生效。

修正方案

方案1:调整现有查询逻辑

需要用数据库原生方法对字段值做小写转换,引入DB门面处理即可:
首先在文件顶部引入依赖:

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

调整查询代码:

// 不需要多余的orderBy,只要判断是否存在即可
$exists = Category::where(DB::raw('LOWER(name)'), '=', Str::lower(request('name')))->first();
if ($exists) {
    return redirect()->route('categories.index')->with('error', 'Nama kategori sudah ada');
} else {
    Category::create(request()->all());
}

方案2:使用Laravel验证规则实现(更符合框架最佳实践)

可以直接在请求验证阶段就完成大小写不敏感的唯一性校验,不需要手动写存在判断:

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

// 验证逻辑放在控制器最前面
$request->validate([
    'name' => [
        'required',
        'string',
        'max:255',
        Rule::unique('categories')->where(function ($query) use ($request) {
            return $query->where(DB::raw('LOWER(name)'), Str::lower($request->input('name')));
        })
    ]
], [
    'name.unique' => 'Nama kategori sudah ada'
]);

// 验证通过后直接创建即可
Category::create(request()->all());
return redirect()->route('categories.index')->with('success', 'Kategori berhasil ditambahkan');

额外优化建议(可选)

如果你的分类表数据量较大,上述查询会因为用到LOWER(name)函数无法命中普通索引,查询效率较低。可以在数据库层面新增小写生成列加唯一索引,同时实现性能优化和数据库级别的强校验:

-- MySQL 示例
ALTER TABLE categories 
ADD COLUMN name_lower VARCHAR(255) GENERATED ALWAYS AS (LOWER(name)) STORED,
ADD UNIQUE INDEX uk_name_lower (name_lower);

加了这个索引之后,查询可以直接改成:

$exists = Category::where('name_lower', '=', Str::lower(request('name')))->first();

就算代码层面遗漏校验,数据库也会直接抛出唯一冲突错误,避免脏数据写入。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:48:04