使用 utf8mb4 (Laravel) 的不区分大小写的 SQL 查询
Case insensitive SQL queries with utf8mb4 (Laravel)
我正在尝试创建一个只允许创建唯一用户名的帐户系统。 SQL 查询过去不区分大小写,但在将字符集更改为 utf8mb4 后,它区分大小写,这意味着人们可以使用重复的用户名。 (我更改为 utf8mb4 以允许用户 BIOS 中的表情符号和其他符号,因此无法恢复到旧字符集)
我试过更改连接排序规则,但是我尝试的所有操作都给我错误 500。我需要一些不需要我在每个查询中添加 "strtolower($username)" 的东西。
示例查询:
if(DB::table('users')->where('username', $username)->count() > 0){
return response()->json(['status'=>'error','message'=>'Username is taken']);
}
SQL配置:
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
当用户尝试使用重复的用户名时,服务器应该 return:
{'status': 'error, 'message': 'Username is taken'}
但用户实际上能够创建一个帐户。
您可以在模型中定义 mutator。每次要存储数据时都会调用此方法:
class User extends Model
{
/**
* Set the user's username in lowercase.
*
* @param string $value
* @return void
*/
public function setUsernameAttribute($value)
{
$this->attributes['username'] = strtolower($value);
}
}
现在,如果您在迁移中将该列声明为 unique
(如下所示):
Schema::create('users', function (Blueprint $table) {
// ...
$table->string('username')->unique();
});
然后它会抛出异常错误,因为它会检测到系统正在尝试创建重复的记录。所以只要处理这个异常就可以return对用户的正确响应。
use Illuminate\Database\QueryException;
// ...
try
{
$user = User::create($data);
}
catch (QueryException $e)
{
$errorCode = $e->errorInfo[1];
if ($errorCode == 1062)
{
return response()->json(['status'=>'error', 'message'=>'Username is taken']);
}
}
但是,你需要在任何地方添加它.. 所以只需将它添加到 your exception handler 然后你就可以开始了。
注意:我使用 来详细说明我的答案。
已通过将所有 table 归类更改为 utf8mb4_unicode_ci
来修复。
ALTER TABLE <table> CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
我正在尝试创建一个只允许创建唯一用户名的帐户系统。 SQL 查询过去不区分大小写,但在将字符集更改为 utf8mb4 后,它区分大小写,这意味着人们可以使用重复的用户名。 (我更改为 utf8mb4 以允许用户 BIOS 中的表情符号和其他符号,因此无法恢复到旧字符集)
我试过更改连接排序规则,但是我尝试的所有操作都给我错误 500。我需要一些不需要我在每个查询中添加 "strtolower($username)" 的东西。
示例查询:
if(DB::table('users')->where('username', $username)->count() > 0){
return response()->json(['status'=>'error','message'=>'Username is taken']);
}
SQL配置:
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
当用户尝试使用重复的用户名时,服务器应该 return:
{'status': 'error, 'message': 'Username is taken'}
但用户实际上能够创建一个帐户。
您可以在模型中定义 mutator。每次要存储数据时都会调用此方法:
class User extends Model
{
/**
* Set the user's username in lowercase.
*
* @param string $value
* @return void
*/
public function setUsernameAttribute($value)
{
$this->attributes['username'] = strtolower($value);
}
}
现在,如果您在迁移中将该列声明为 unique
(如下所示):
Schema::create('users', function (Blueprint $table) {
// ...
$table->string('username')->unique();
});
然后它会抛出异常错误,因为它会检测到系统正在尝试创建重复的记录。所以只要处理这个异常就可以return对用户的正确响应。
use Illuminate\Database\QueryException;
// ...
try
{
$user = User::create($data);
}
catch (QueryException $e)
{
$errorCode = $e->errorInfo[1];
if ($errorCode == 1062)
{
return response()->json(['status'=>'error', 'message'=>'Username is taken']);
}
}
但是,你需要在任何地方添加它.. 所以只需将它添加到 your exception handler 然后你就可以开始了。
注意:我使用
已通过将所有 table 归类更改为 utf8mb4_unicode_ci
来修复。
ALTER TABLE <table> CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;