【Laravel8】親レコードをリレーション先の子レコードと一緒に削除する

はい、今回はリレーションがあるテーブルがあったときに親の削除と同時に子レコードの削除も行い多と思います。

というのも今回親レコードを削除しようとしたときに以下のエラーがでたのでそれを解決していきます。

SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails

レコードを削除しようとしたときのエラー文一部

伝えたいこと

今回伝えたいことは、親レコードと対応している子レコードも一緒に削除する方法です。

もし、子レコードが存在するときに、親レコードが削除されるとエラーがでてしまうので、なぜ出るのかなどを説明しながら解決していきましょう!

そこでmigrationファイルの書きかたも徐々に覚えていきましょうね!

原因: 親レコードに紐づいている子レコードが削除されない。

今回エラーが起きたのは親レコードを削除しようとしたけど子レコードが残っているよ~おいていかないで―っていうエラーがでていたんですね。

SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint failsCode language: JavaScript (javascript)

なぜ、子レコードを置いたまま親のレコードは削除できないのか。

それはもしリレーション元のレコードがないとしたらデータの不整合性 が発生するからですね。

簡単に説明すると、論理的に矛盾が生じていますよ~ってこと。

子レコードからリレーション元のレコードを見に行こうとしたらあれ?ないじゃん!ってなるわけですね。

この不整合を解決させましょう!

解決策

今回の課題に対する解決策としては、migrationファイルで初めから親レコード消したらリレーション先の対応する子レコードも削除しちゃってねーっていう設定を入れます。

cascadeの設定を追加する。

では子レコード(リレーション先のレコード)のmigrationファイルにcascadeの設定を追加します。

cascadeについてはこちらのQiita記事で丁寧に記載されていました。

簡単に言うと、「参照先に何かあったらそれに合わせて自分も変化するよ~」っていう意味。

だと思っています!

ではcascadeの設定をmigrationファイルに追記していきますが、公式より記述方法があるのでそちらを参考にしてみます。

メソッド説明
$table->cascadeOnUpdate();更新をカスケードします。
$table->restrictOnUpdate();更新を制限します。
$table->cascadeOnDelete();削除をカスケードします。
$table->restrictOnDelete();削除を制限します。
$table->nullOnDelete();削除時に外部キーへNULLをセットします。
https://readouble.com/laravel/8.x/ja/migrations.html 参照

では書いていきます。

リレーション先(子レコードがある)migrationファイル

<?php

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

class Posts extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');

            $table->string('post');
            $table->timestamps();

            $table->unsignedBigInteger('user_id');


            //外部キー
            $table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete()->comment('user_idはusersテーブルのIDと紐づいている。');

        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}Code language: HTML, XML (xml)

ここで、cascadeOnDelete() を利用しました。

こちらのアクションを指定することで、参照先(親レコード)が削除されると自動的に参照元(子レコード)も削除されるようになります!

最後に、再度migrationする必要があるので検証環境の為リフレッシュさせてtableを作りなおしておきました!

必要に応じてmigrationの対応をしてください!

//データベースをリフレッシュする。
php artisan migrate:refresh


//seedingを使ってデータを入れなおす。
php artisan db:seedCode language: JavaScript (javascript)

まとめ

データの整合性に関してはデータベースを取り扱ううえで大切なのでしっかり意識して作りましょう!

今回利用したのはcascadeOnDelete() でした!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA