LoginSignup
2
0

More than 1 year has passed since last update.

Laravelで直接データベースをいじったら地獄を見た件

Last updated at Posted at 2022-03-21

みなさん、こんにちは!

アプリを完成しましたが、データの削除の際に外部キーのエラーがあったので修正しようとしたところ、地獄を見たので愚痴らせてください。

サービスについてはこちら

laravel学んで2か月で自サービスを開発した話 Part1

何が起きたか

FireShot Capture 016 - フラワーギフト - flower-gift.herokuapp.com.png
以前、凍結されたぶりを削除しようとしたら、
fireshot_capture_013_-sqlstate_23000___integrity_constraint_violation__1451_cannot_delete_o_-_flower-gift.herokuapp.com.png

はい、外部キーの参照エラーです。
まあ、これは予想通りだったので、じゃけん直していこうね
necchusyou_face_boy1.png

注意!ここからは私の試行錯誤が含まれます。真似すると地獄を見ますのでやめましょう!

マイグレーションファイルを直接編集する

とりあえず、マイグレーションファイルを編集してphp artisan migrateすればええやろ!

create_processed_products_table.php
     Schema::create('processed_products', function (Blueprint $table) {
            $table->id();
            $table->foreignId('admin_id')->constrained('admins');
            $table->foreignId('product_id')->constrained();
            $table->foreignId('product_id')
            ->onUpdate('cascade')
            ->onDelete('cascade')
            ->constrained('products');
            $table->boolean('result');
            $table->timestamps();
        });

cascadeを付けて変更すればええやん!それで、php artisan migrate っと
character_program_fat.png

nothing migration

necchusyou_face_boy4.png

あ、あれっ?変更が反映されないぞ?

まあ、もしかしたら、変更がされているかもしれないし、削除ボタンと
fireshot_capture_013_-sqlstate_23000___integrity_constraint_violation__1451_cannot_delete_o_-_flower-gift.herokuapp.com.png

知ってた

データベースを直接編集する

マイグレーションファイルが編集できないんだったら、データベースを直接編集すればええやん!
スクリーンショット (63).png

ということで、データーベースの外部キーをRESTRICTからCASCADEに変更してと・・・
necchusyou_face_boy1.png

これなら大丈夫でしょ!

fireshot_capture_013_-sqlstate_23000___integrity_constraint_violation__1451_cannot_delete_o_-_flower-gift.herokuapp.com.png

33-4

さすがに知り合いに聞いてみた。

エンジニアさん「このエラーに関してどんなアプローチをしたんですか?」

tehepero2_youngman.png

マイグレーションファイルとデータベースの値を直接変更しちゃった

エンジニアさん「今から緊急会議です。ZOOMつないでください。」

bikkuri_me_tobideru_man.png

ええええええええええええ!!

結局何がいけなかったのか

エンジニアさんと実際に話してみてわかったことが

  • マイグレーションファイルは編集せずに、データベースに変更を加えるときは新しいマイグレーションファイルを作る
  • データベースを直接いじらない
  • データベースとマイグレーションの状況を合わせる
    ということらしいので、さっそく助言もいただきながら修正してみた。

マイグレーションファイルの作成

すでにあるマイグレーションファイルをいじるのはご法度なので、マイグレーションファイルを作成します

processed_comments_table_drop_foreign.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class ProcessedCommentsTableDropForeign extends Migration
{

    public function up()
    {
        Schema::table('processed_comments', function (Blueprint $table) {
            $table->dropForeign('processed_comments_comment_id_foreign');
        });
    }

    public function down()
    {
        Schema::table('processed_comments', function (Blueprint $table) {
            $table->foreign('comment_id')->references('id')->on('comments');
        });

    }
}

このマイグレーションファイルを更新して既にある外部キーをドロップします

しかし、upメゾットだけだと、更新時にエラーが起きた時、完全性が損なわれるので、downメゾットにはupメゾットの逆のことを書いていきます
この場合だと、外部キーをつける工程をdownメゾットに書きます

この逆のメゾットを考えるのが難しかった・・・

また、勝手にデータベースをいじってcascadeをつけてしまった分を補完するマイグレーションファイルを作ります

change_foreignkey_restrict_to_cascade.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class ChangeForeignkeyRestrictToCascade extends Migration
{

    public function up()
    {

        Schema::table('processed_products', function (Blueprint $table) {
            $table->dropForeign('processed_products_product_id_foreign');
        });
        Schema::table('processed_comments', function (Blueprint $table) {
            $table->foreign('comment_id')->references('id')->on('comments')
            ->onUpdate('cascade')
            ->onDelete('cascade');
        });
        Schema::table('processed_products', function (Blueprint $table) {
            $table->foreign('product_id')->references('id')->on('products')
            ->onUpdate('cascade')
            ->onDelete('cascade');
        });
         
    }

    public function down()
    {
        Schema::table('processed_products', function (Blueprint $table) {
            $table->dropForeign('processed_products_product_id_foreign');
            $table->foreign('product_id')->references('id')->on('products');
        });
        Schema::table('processed_comments', function (Blueprint $table) {
            $table->dropForeign('processed_comments_comment_id_foreign');
        });
    }
}

この状態でphp artisan migrate していきます

データベースにマイグレーションファイルを手動で追加

この状態で php artisan migrate:status でマイグレーションの状況を確認すると
スクリーンショット (64).png

なぜNOになっているかというと、データベースにさっきの2つのマイグレーションファイルがないからです

そのため何をするかというと
noname.png

データベースをいじくってLaravelをだまします

どういうことかというと、

スクリーンショット (65).png

これで再び php artisan migrate:status をすると2つのマイグレーションファイルがyesになります!

これでマイグレーションとLaravelの整合性が保たれました!
今度こそ凍結された商品を削除しましょう!

スクリーンショット (66).png

やったぜ

終わりに

マイグレーションは一方通行だから、絶対に編集しちゃだめだぞ!
また、データベースも直接いじらず、マイグレーションファイルから指令を出しましょう!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0