HOW TO CORRECTLY CONFIGURE SOFT DELETING WITH CASCADE DELETION
Sep 06, 2024 Copy Link
I was working on the Delete Scenario, where I had to specify which table must be SoftDeleting and which must be completely deleted. We all know that if the table is marked with the `softDeletes`
method and you come to remove a record the `deleted_at`
column must be populated, right? right but, this did not happen to me!
So, lemme memic the wrong schema that I have designed, and let's start with the `users`
migration:
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Also, the `posts`
migration would be:
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->softDeletes();
$table->timestamps();
});
}
When you gonna delete a user that has many posts, the `cascadeOnDelete`
method will work and the posts will be completely deleted. To resolve that trouble you must mark the parent table with the `softDeletes`
method too:
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
...
$table->softDeletes();
$table->timestamps();
});
}
If you try to delete any user that owns posts the `users.deleted_at`
will be populated but his posts will never be deleted! therefore you must configure something to delete the user's posts when he is gonna be deleted so, let's quickly jump into the `boot`
method:
/**
* Bootstrap the model and its traits.
*
* @return void
*/
public static function boot()
{
parent::boot();
static::deleting(fn($user) => $user->posts()->delete());
}
Now, if you gonna delete any user you will find out that the `deleted_at`
column has been populated in both tables 🕺