まだリリースはできていないのですが、個人開発をしています。
その個人開発で行き詰まってしまったものがあったので共有したいと思います。
マイグレーションでDBのデータ不整合によりマイグレーションがコケる
エラーメッセージの記録を取り忘れてしまったので、こちらでは割愛になってしまうのですが、
USERSテーブルとそのUSERテーブルを外部キーとして参照しているBroadcastsテーブルがあります。今回Broadcastsテーブルに変更を加えたので、DBの中にデータが入っている状態でマイグレーションをしました。
この際、USERSテーブルとBroadcastsテーブルの間のデータの不整合のせいで、外部キーの参照がデータ上取れておらずマイグレーションができませんでした。
今回の解決法は極めて限定された条件での解決法なので、 皆様注意して扱うようにしてください。
データベースのデータをすべてDROPする
DBのデータが悪いことで外部キーの参照が外れずマイグレーションができなかったため、
php artisan db:wipe
で、DBの中のデータをすべて削除しました。これは個人開発で最悪DB内のデータがどうなってもいいという場合のものなので、絶対に真似しないでください。セッション情報をDB内に保持していたり、マスタデータなどを保持している場合はそのデータ丸ごと消えるものなので、必要なテーブルを選択して通常は実行するようにしてください。
まじで真似しないほうがいいです。確実に迷惑をかけることは確実なので。
まぁ僕の場合は個人開発なのでどうでもいいかなと思っていたのですが。
テーブル数も7テーブルしかないので比較的マシなので。
外部キー参照の際に指定したカラム名が間違っていたためマイグレーションがコケた。
これはまだ前半に比べて役に立つと思います。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('broadcasting_rooms', function (Blueprint $table) {
$table->id()->unique();
// users テーブルの外部キー関連付け
$table->unsignedBigInteger('user_id')->NotNull();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->string('room_names', 140)->NotNull();
$table->string('room_explain', 140)->nullable();
$table->integer('broadcasting_flag')->NotNull();
$table->string('container_id', 140)->nullable()->unique();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// broadcasting_rooms の外部キー制約を解除してテーブルを削除
if (Schema::hasTable('broadcasting_rooms')) {
Log::debug("broadcasting_roomsが存在する");
Schema::table('broadcasting_rooms', function (Blueprint $table) {
$table->dropForeign(['user_id']); // 外部キーを削除
});
Schema::dropIfExists('broadcasting_rooms'); // テーブルを削除
}
// 最後に users テーブルを削除
if (Schema::hasTable('users')) {
Schema::dropIfExists('users');
}
}
};
ここで、container_idカラムの値を外部キーとして別のテーブルに保持されるようにしようとしていました。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('container_logs', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id')->nullable(false);
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->string('container_id')->nullable(false);
$table->foreign('container_id')->references('id')->on('broadcasting_rooms')->onDelete('cascade');
$table->string('container_log')->NotNull();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('container_logs');
}
};
もうお気づきの方はいるでしょう。
container_logsテーブルでcontainer_idを参照しようとしている際にBroadcasting_roomsのcontainer_idカラムを指定しなければならないところでidカラムを間違えて指定してしまっています。
なので、マイグレーションを行おうとした際に
SQLSTATE[HY000]: General error: 3780 Referencing column 'container_id' and referenced column 'id' in foreign key constraint 'container_logs_container_id_foreign' are incompatible. (Connection: mysql, SQL: alter table `container_logs` add constraint `container_logs_container_id_foreign` foreign key (`container_id`) references `broadcasting_rooms` (`id`) on delete cascade)
idを指定しているけどそんなものないぞ。
互換性ありません。
とエラー文が出てきてしまいマイグレーションがコケてしまったというわけです。
いやータイポには気をつけないといけないですね。全然気が付きませんでした。