本記事はまだ書きなぐり段階のものです。
あとで清書する…予定。
php artisan migrate
が失敗する
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `children_table` add constraint `children_parent_id_foreign` foreign
key (`parent_id`) references `parent_table` (`id`) on delete cascade)
概要:
エラー内容でいろいろと調べたがどうにもよくわからない。
タイプミスをしているわけではないし、外部キー制約は順番が重要だということだったのできちんと親テーブル(parent_table)が生成されたあとで実行しているのに何故だろうか?と考えて煮詰まってしまいお手上げだ〜!ということで質問を投げてみたところ、
とある方が「型情報などを完全にあわせないとエラーになる」と教えてもらった。
原因:
元々、型情報がBigIntegerで定義したいところがintegerになっていたのであとでまとめて修正しようと思っていたのだがこれが原因だったようだ。
migrationファイルを本来想定している型情報に合致するよう修正を実装。
今回はcreate_children_table.php
内ではparent_idをBigIntegerで定義していたが実際のcreate_parent_table.php
ではIntegerだったのでIntegerになるようchildrenテーブルの型情報を変更。
これだけだとまだ情報が抜け落ちていてincrements()
は自動でUNSIGNED
を付与するのでそれを追加する。
この状態でphp artisan migrate:rollback
を実行し、先程失敗したmigrateをロールバックしmigrate成功時点の状態まで巻き戻す。
なおこの際にchildrenテーブルは生成自体には成功している(外部キー制約だけが付与されていない状態で作成されている)ためDROP TABLEで削除しておかないと「すでに作成済みだ」と怒られる。
(個人的には外部キー制約でエラー出たならテーブルの作成も失敗してほしい、何故テーブルだけ作成されるのだろう?)
あとはphp artisan migrate
を実行すれば成功する。
よっしゃ!完了だ!!!
と思ったがロールバックがきちんと出来ているか?が確認出来ていなかったため実行したところ↓のようなエラーが出た。
[Illuminate\Database\QueryException]
SQLSTATE[23000]: Integrity constraint violation: 1217 Cannot delete or update a parent row: a foreign key constraint fails (SQL: drop table if exists `parent_tables`)
エラー内容みればわかるが外部キー制約があるから更新も削除もできないよ!とある。
はてな?何故だろうと思ってmigrationファイルを確認したところdown()
の実装に問題がああった。
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('parent_table');
Schema::dropIfExists('children_table');
}
先に親テーブルを削除しようとしているために子テーブルの外部キー制約に引っかかっている状態だなとわかったので「子テーブル削除→親テーブル削除」の順番になるよう修正。
これでロールバックが可能になった。
php artisan refresh
を実行したところ問題なく再生成された。
今度こそ完了した!という結末になる。
まとめ
しかしLaravelのmigrateはエラー内容がわかりにくいなあという印象だ。
5.4ではこのあたりのエラー情報は改善されているんだろうか?
もしくはもっと別の方法で具体的にコードのココが間違っている!と教えてくれると助かるのになあ。
ログみろって話なんだろうけどもスキーマビルダーのコードに問題があるんだからそこを表示してほしいな。