【Laravel】usersテーブルのidをULIDに変更する方法とログイン出来なくなる問題の解決方法
こんにちは、saitogoです。
今回はusersテーブルのidをULIDに変更する方法について記事にまとめました。
ゴール
usersテーブルでidの代わりにULIDを使用する。
開発環境
- Windows11
- WSL2
- Docker
- Laravel 11.9
- VScode
前提
- Laravelの開発環境は既に構築済み
- Authファザードを使ったログイン処理が実装済み
結論
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
protected $keyType = "string"; // primary key type
public $incrementing = false; // auto incrament
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
// $table->id();
$table->ulid("id")->primary();
// $table->string('name');
$table->string('email')->unique();
// $table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignUlid('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
Schema::dropIfExists('password_reset_tokens');
Schema::dropIfExists('sessions');
}
};
やったこと
usersテーブルのSchemaをidからulidに変更。
※nameとemail_verified_atは使用しないのでコメントアウトしてます。
Schema::create('users', function (Blueprint $table) {
// $table->id();
$table->ulid("id")->primary();
// $table->string('name');
$table->string('email')->unique();
// $table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Auth::attemptはtrue
を返すが、ログイン状態が保持されていなかった。
そのためリダイレクト後にログイン画面に戻されてしまう。
原因
sessionsテーブルの外部キー制約の型が不一致のため、sessionsのuser_idカラムがNULLになってしまい、ログイン情報が参照出来なかった。
詳細
sessionsテーブルの外部キー制約のデフォルトはidの型を使ってる。
つまり、user_idの型はbigint(20)
になっている。
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
しかし、ULID(usersテーブルのidカラム)の型はchar(26)
です。
そのためbigint(20)
とchar(26)
で型が不一致となり、sessionsテーブルのuser_idカラムの値はNULLになってしまう。
usersテーブルの構造 | sessionsテーブルの構造 |
---|---|
解決方法
sessionsテーブルのSchemaのforeignId
をforeignUlid
に変更する。
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
- $table->foreignId('user_id')->nullable()->index();
+ $table->foreignUlid('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
補足
UUIDを使いたい場合は上記のULIDをUUIDに変更するだけで使える。
Schema::create('users', function (Blueprint $table) {
// $table->id();
- $table->ulid("id")->primary();
+ $table->uuid("id")->primary();
// $table->string('name');
$table->string('email')->unique();
// $table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
- $table->foreignUlid('user_id')->nullable()->index();
+ $table->foreignUuid('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
おわりに
usersテーブルの主キーをULIDに変更する記事はたくさんありますが、どの記事もusersテーブルのSchemaを変更することしか書いてなかったので、ログイン出来ずにハマってしまいました。
デフォルトのIDだと連番なので、ユーザー数やユーザーIDが推測出来てしまうため、今回IDをULIDに変更する記事を書きました。
今回Zennで記事を投稿するのが初めてなので、至らないところがあれば指摘していただけると幸いです。
Discussion