はい、今回はリレーションがあるテーブルがあったときに親の削除と同時に子レコードの削除も行い多と思います。
というのも今回親レコードを削除しようとしたときに以下のエラーがでたのでそれを解決していきます。
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails
レコードを削除しようとしたときのエラー文一部
Table of Contents
伝えたいこと
今回伝えたいことは、親レコードと対応している子レコードも一緒に削除する方法です。
もし、子レコードが存在するときに、親レコードが削除されるとエラーがでてしまうので、なぜ出るのかなどを説明しながら解決していきましょう!
そこでmigrationファイルの書きかたも徐々に覚えていきましょうね!
原因: 親レコードに紐づいている子レコードが削除されない。
今回エラーが起きたのは親レコードを削除しようとしたけど子レコードが残っているよ~おいていかないで―っていうエラーがでていたんですね。
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails
Code language: JavaScript (javascript)
なぜ、子レコードを置いたまま親のレコードは削除できないのか。
それはもしリレーション元のレコードがないとしたらデータの不整合性 が発生するからですね。
簡単に説明すると、論理的に矛盾が生じていますよ~ってこと。
子レコードからリレーション元のレコードを見に行こうとしたらあれ?ないじゃん!ってなるわけですね。
この不整合を解決させましょう!
解決策
今回の課題に対する解決策としては、migrationファイルで初めから親レコード消したらリレーション先の対応する子レコードも削除しちゃってねーっていう設定を入れます。
cascadeの設定を追加する。
では子レコード(リレーション先のレコード)のmigrationファイルにcascadeの設定を追加します。
cascadeについてはこちらのQiita記事で丁寧に記載されていました。
簡単に言うと、「参照先に何かあったらそれに合わせて自分も変化するよ~」っていう意味。
だと思っています!
ではcascadeの設定をmigrationファイルに追記していきますが、公式より記述方法があるのでそちらを参考にしてみます。
メソッド | 説明 |
---|---|
$table->cascadeOnUpdate(); | 更新をカスケードします。 |
$table->restrictOnUpdate(); | 更新を制限します。 |
$table->cascadeOnDelete(); | 削除をカスケードします。 |
$table->restrictOnDelete(); | 削除を制限します。 |
$table->nullOnDelete(); | 削除時に外部キーへNULLをセットします。 |
では書いていきます。
リレーション先(子レコードがある)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:seed
Code language: JavaScript (javascript)
まとめ
データの整合性に関してはデータベースを取り扱ううえで大切なのでしっかり意識して作りましょう!
今回利用したのはcascadeOnDelete()
でした!