Search code examples
phpsqllaravelcharacter-encodingutf8mb4

Case insensitive SQL queries with utf8mb4 (Laravel)


I'm trying to make a account system that only allows unique usernames to be created. SQL queries used to be case insensitive, but after changing the charset to utf8mb4 it's case sensitive meaning people can use duplicate usernames. (I changed to utf8mb4 to allow emojis and other symbols in user bios, so reverting back to the old charset isn't an option)

I've tried changing the connection collation, however everything I try gives me error 500. I need something that won't require me to add "strtolower($username)" in every query.

Example query:

if(DB::table('users')->where('username', $username)->count() > 0){
    return response()->json(['status'=>'error','message'=>'Username is taken']);
}

SQL configuration:

'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,
],

When a user tries to use a duplicate username the server should return:

{'status': 'error, 'message': 'Username is taken'}

but the user is actually able to create an account.


Solution

  • Fixed by changing all table collations to utf8mb4_unicode_ci.

    ALTER TABLE <table> CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;