Laravelで開発をするにあたって、 データベースを構築する際にマイグレーションを利用することがあると思います。
私は、このマイグレーションの実行にあたり「php artisan migrate」を叩くときに毎度のようにエラーが出ます・・・泣
ということで備忘録がてら、よくあるエラーパターンと、その対処法についてです。何かのヒントになれば幸いです。
先に結論。
だいたいコレのどれか。
まずコレ確認してみて。
● DBにそもそもベースとなるテーブル作ってない。
● .envファイルの DB設定おかしい or 変更が反映されていない
● 外部キー制約に「onDelete('cascade')」と「onUpdate('cascade')」が抜けてる
● テーブルの順番問題(外部キーで参照するためのテーブルがそもそも未完成)
● カラムの「型」が参照元と参照先で違う。
このどれかがあるだけでマイグレーションを実行しようとしたときにエラーになります。
それぞれについても軽く解説していきます。
① DBにそもそもベースとなるテーブル作ってない。
そりゃそうよね。って話ですが、意外とローカル環境で開発 → デプロイしたときなどにやっちゃいます。
SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = (プロジェクトの名前) and table_name = migrations and table_type = 'BASE TABLE')
多分、こんな感じのエラーが出てるはず。
ベースのテーブルが無いんだからアクセスできるわけがないですね。
DBの状態、特に今実行しようとしているマイグレーションのベースとなるテーブルがあるかは確認しておきましょう。
② .envファイルの DB設定おかしい or 変更が反映されていない
これも割とやりがち。というか忘れがち。
例えば、ローカル環境で、MySQLを用いている場合の「.env」は
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=プロジェクトの名前
DB_USERNAME=任意のユーザー名
DB_PASSWORD=任意のパスワード
DB_SOCKET=/Applications/MAMP/tmp/mysql/mysql.sock
のような形になると思います。
・デプロイしたときに、DB_SOCKET の部分を変更し忘れていたり
SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = (プロジェクトの名前) and table_name = migrations and table_type = 'BASE TABLE')
・DB_DATABASE の部分の名前がベーステーブル名と違ったり
SQLSTATE[HY000] [1049] Unknown database 「.envのDB_DATABASEの部分」 (SQL: select * from information_schema.tables where table_schema = 〇〇 and table_name = migrations and table_type = 'BASE TABLE')
するとアウトです。
.envの設定変更後はコンフィグのキャッシュをクリアするのを忘れずに。
コマンドは「php artisan config:cache」とかでいけるニャ
③ 外部キー制約に「onDelete('cascade')」と「onUpdate('cascade')」が抜けてる
これが抜けていると外部キー制約がかかっているカラムをイジるときにエラーが出ることがあります。
外部キー制約を付けつつも、そのカラムの変更(削除・更新)を許容する場合は以下のように、これを追記しておきましょう。
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
④ テーブルの順番問題(外部キーで参照するためのテーブルがそもそも未完成)
これが意外とハマっちゃう部分。
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `〇〇テーブル add constraint
□□_foreign` foreign key (`△△`) references `project_type` (`△の相手`) on delete cascade on update cascade)
のような当たり障りない感じのエラーが出る。
エラーの原因は「外部キーを使おうとしてるけど、そんなん(カラムなりテーブルなりが)無いんだけど・・・。」ってことらしい。
マイグレーションを実行すると古い順に読み込んでいるようなので、「マイグレーションファイルの順番を入れ替える」必要がある。
そんな場合があるのがこのパターンです。
├── database
│ ├── factories
│ │ └── UserFactory.php
│ ├── migrations
│ │ ├── 2014_10_12_000000_create_users_table.php
│ │ ├── 2014_10_12_100000_create_password_resets_table.php
│ │ ├── 2023_08_29_041302_create_category_table.php
│ │ ├── 2023_08_29_041513_create_purchase_table.php
│ │ ├── 2023_08_29_041727_create_goods_table.php
│ └── seeds
│ └── DatabaseSeeder.php
こんな感じの構成になっていると仮定して
「purchase(購入)」テーブルでは、「商品(goods)」を購入したユーザーのIDを外部キーを用いて紐づけようとしている。
そのような場合、先に商品(goods)テーブルが作られていないと、どこに外部キーをつける相手いるんですか?となりエラーが起こります。
もし、これに当てはまっている場合は、ファイル名の日時の部分だけ変更でOKです。
├── database
│ ├── factories
│ │ └── UserFactory.php
│ ├── migrations
│ │ ├── 2014_10_12_000000_create_users_table.php
│ │ ├── 2014_10_12_100000_create_password_resets_table.php
│ │ ├── 2023_08_29_041302_create_category_table.php
│ │ ├── 2023_08_29_041513_create_purchase_table.php
│ │ ├── 2023_08_29_041420_create_goods_table.php // ここの「2023_08_29」以降を、purchaseテーブルのより前に変更
│ └── seeds
│ └── DatabaseSeeder.php
ファイルの順番は(きっと)勝手に入れ替わり、マイグレーションを実行するときに読み込まれる順番が変わります。
⑤ カラムの「型」が参照元と参照先で違う。
SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = 〇〇 and table_name = migrations and table_type = 'BASE TABLE')
って感じのエラーが出るかと思います。
タイトルの通りですが、外部キーをつけようとしているカラム同士の「データ型」が違うとエラーになります。
先述の「purchase」と「goods」を例に考えたとき
・purchase には「goods_id」カラムが存在し、「goods」テーブルの「id」をもとに、どの商品を購入したかを紐づけたい。
とすると、以下のように「goods_id」と「id」の型をそろえる必要があります。
$table->bigIncrements('id'); // goodsテーブルのID。型はBIGINT
$table->integer('goods_id'); //・・・ダメ。
$table->bigInteger('goods_id'); //・・・OK
まとめ
他にも「単純なスペルミス」など、色んなエラーのパターンがあるとは思います。
ただ、今回は私個人が毎度のように抜けてしまう部分を紹介させてもらいました。
Laravel初学者の方々などのお役に立てたら幸いです。