0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel】既存カラムに onDelete cascade を追加した際のメモ

Last updated at Posted at 2022-04-02

環境:Laravel 6.2
検索した感じでは8でも変わってないはず、、

状況

ユーザーの退会処理を作ろうと思い、$user->delete();を行ったところ下記のエラーが出た

Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails

ユーザーが投稿した記事(articlesテーブル)が外部キーでユーザーと紐づいているため、
先に該当ユーザーが投稿した記事を削除しないとエラーが出てしまうようだ

対応案

ユーザーの退会処理を行うメソッド内で、先に記事削除の処理を書けば一応解決はする。
しかし、articlesテーブルの外部キーにonDelete cascadeを設定してやれば、そのあたり自動でやってくれるので、今回はそちらを行うことにした。

onDelete cascade追加用のマイグレーションファイル作成

articlesテーブルの中身がすべて消えても良いなら
ロールバックしてarticlesテーブル作成用のマイグレーションファイルを書き直せば良いが
今回は消したくなかったので、onDelete cascade追加用のマイグレーションファイルを新たに作成した。

onDelete cascade追加用のマイグレーションファイル
<?php

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

class AddCascadeToUserIdOnArticleTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('articles', function (Blueprint $table) {
            $table->dropForeign(['user_id']);//いったん外部キーを削除する。
            $table->foreign('user_id')
                ->references('id')->on('users')
                ->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('articles', function (Blueprint $table) {
            $table->dropForeign(['user_id']);
            $table->foreign('user_id')
                ->references('id')->on('users');
        });
    }
}

注意点としては、上記コードupメソッド内のコメントにも書いているが
先に外部キーを削除する必要があるので、upメソッド内に$table->dropForeign(['user_id']);を記述していること。

ちなみにこのdropForeignの引数は、本来であれば「リレーションのテーブル名_外部キーを設定しているカラム名_foreign」なので、dropForeign(articles_user_id_foreign)となるが、今回のようにリレーションのテーブル名(users)に対して、外部キーを設定しているカラム名がuser_id(usersの単数形+_id)といった形で、Laravelの命名ルールに則っている場合は、上記コードのようにdropForeign(['user_id'])という書き方もできる。

確認

もちろん$user->delete();を行えば動作確認はできるし、
phpmyadminでの確認やコマンドでDBにログインしての確認もできる。

スクリーンショット-2022-04-02-163931.jpg

ちなみに
onDelete cascade は「連動して削除する」だが
onDelete restrict は「連動せず、削除を制限する(エラーが出る)」。restrictがデフォルト。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?