LoginSignup
0

More than 1 year has passed since last update.

posted at

updated at

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

みなさん、こんにちは!

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

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

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

やったぜ

終わりに

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

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
What you can do with signing up
0