Laravel中如何将输入转小写并实现分类名唯一校验
我来帮你搞定这两个问题,分步骤给你说清楚:
一、实现字段自动转小写存储
你之前尝试strtolower($kategori->nama_kategori)无效,核心原因是顺序搞反了——你得先把请求参数转成小写,再赋值给模型属性,而不是先赋值再转(那样操作的是模型里的旧值,没重新赋值回去当然不会生效)。推荐两种方案:
1. 手动处理赋值(快速直接)
直接在赋值环节对请求参数做小写转换:
$kategori = new Kategori; $kategori->nama_kategori = strtolower($request->nama_kategori); // 先转小写再赋值给模型 $kategori->save();
2. 使用模型修改器(优雅持久)
如果希望每次给nama_kategori赋值时都自动转小写,不用重复写转换代码,可以在Kategori模型里添加修改器(Mutator),一劳永逸:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Kategori extends Model { // ... 其他模型代码 public function setNamaKategoriAttribute($value) { // 每次给该属性赋值时,自动将值转为小写后存入数据库 $this->attributes['nama_kategori'] = strtolower($value); } }
之后不管是通过请求赋值,还是直接给模型属性赋值,都会自动完成小写转换,不用再手动处理。
二、实现不区分大小写的唯一约束
要做到已有"Hello"时存储"hello"触发错误,需要同时在验证层和数据库层做处理,避免出现绕过验证直接操作数据库的漏洞:
1. 验证层添加不区分大小写的唯一规则
在你的请求验证逻辑里(比如表单请求类,或者控制器的validate方法),给nama_kategori添加带大小写忽略的唯一校验规则:
use Illuminate\Validation\Rule; $request->validate([ 'nama_kategori' => [ 'required', 'string', // 验证时将数据库字段和输入值都转成小写比对 Rule::unique('kategori')->where(fn ($query) => $query->whereRaw('LOWER(nama_kategori) = ?', [strtolower($request->nama_kategori)])) ] ]);
或者用更简洁的语法:
'nama_kategori' => 'required|string|unique:kategori,nama_kategori,NULL,id,LOWER(nama_kategori),LOWER(:value)'
2. 数据库层添加不区分大小写的唯一索引
验证层只是业务逻辑校验,为了绝对保证数据唯一性,需要在数据库层面做约束,有两种方式可选:
方式一:修改字段排序规则(Collation)
把nama_kategori字段的排序规则改成不区分大小写的(比如MySQL的utf8mb4_unicode_ci,默认的utf8mb4_bin是区分大小写的)。可以通过迁移修改:
use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; Schema::table('kategori', function (Blueprint $table) { $table->string('nama_kategori') ->collate('utf8mb4_unicode_ci') // 不区分大小写的排序规则 ->unique() ->change(); });
执行迁移后,数据库会自动忽略大小写检查唯一性。
方式二:添加基于小写转换的函数索引
如果不想修改整个字段的排序规则,可以添加一个基于LOWER(nama_kategori)的唯一索引:
use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\DB; Schema::table('kategori', function (Blueprint $table) { $table->unique(DB::raw('LOWER(nama_kategori)'), 'nama_kategori_lower_unique'); });
这样数据库会基于字段的小写值检查唯一性,同样能达到需求效果。
内容的提问来源于stack exchange,提问作者Muhammad Zainul Mutaqin

