Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

t0berius's avatar

laravel delete model with all relations

My current model has some relations. How can I delete them too, in case of model will be deleted? This query won't delete the related models, only the 'main model'.

I use this code to call:

 $checks = Check::where('created_at','<=', Carbon::now()->subHours(3))->with('checks')->with('results')->delete();

Here's my current model of Check

public function checks()
   {
       return $this->hasMany('App\CheckProcedure');
   }

public function results()
   {
       return $this->hasMany('App\CheckResult');
   }

protected static function boot(){
    parent::boot();

    static::deleted(function($check)
    {
        foreach($check->checks as $check_object_check) {
            $check_object_check->delete();
        }

        foreach($check->results as $check_object_result) {
            $check_object_result->delete();
        }
    });
}

Results and checks contain more than one entry for each check. Meaning this to make things clear:

One check may have n CheckResult and may have n CheckProcedure (I'll of course delete all of them too).

0 likes
12 replies
ctroms's avatar

If you're using MySQL you can add 'ON DELETE CASCADE' to your foreign key. This will automatically delete any records that reference the parent when the parent is deleted. If your using Laravel's migrations add

$table->foreign('fk_id')->references('id')->on('table')->onDelete('cascade');

to your foreign key definition.

You can also add a delete method to your model and delete your relationships first then let the model complete the delete operation.

public function delete() {
    $this->checks()->delete();
    $this->results()->delete();
    parent::delete();
}

or have a look at Eloquent Events and specifically the deleting or deleted events.

4 likes
t0berius's avatar

@ctroms

Using the code you posted results in the same problem as before, only the main model gets deleted. The two related ones aren't deleted.

ctroms's avatar

@jaheller Which code is not working the delete method in the model or the onDelete('cascade') method.

ctroms's avatar

@jaheller Try to change your boot method to

protected static function boot() {
    parent::boot();
    
    static::deleting(function($check) {
        $check->checks()->delete();
        $check->results()->delete();
    });
}

Since these relationships are on this model you shouldn't need to iterate over each one. Change your event to deleting rather than deleted.

t0berius's avatar

@ctroms

This doesn't work too. Only the check is deleted, not the related items.

ctroms's avatar

@jaheller Sorry. I didn't notice last night but I believe the issue is in your original query. Eloquent's events are not fired when you use a where constraint. In order to use the model event you would have to pull it into memory first . Leave your boot method and adjust your query to the following and it should work.

$checks = Check::where('created_at','<=', Carbon::now()->subHours(3))
    ->each(function($check) {
        $check->delete();
    });

I would still suggest letting MySQL handle this with a cascade if you are in fact using MySQL.

1 like
Snapey's avatar

delete cascade on the database only works if actually removing the model, but what about soft deletes?

I add this observer to the model, and it deletes related models, as @ctroms suggested

    //observe this model being deleted and delete the child events
    public static function boot ()
    {
        parent::boot();

        self::deleting(function (Campaign $campaign) {

            foreach ($campaign->events as $event)
            {
                $event->delete();
            }
        });
    }

a campaign has many events, and an event has many shifts, and shifts have many activities - all have to be set soft deleted

so, in the Event model;

    //observe this model being deleted and delete the child activities
    public static function boot ()
    {
        parent::boot();

        self::deleting(function (CampaignEvent $event) {

            foreach ($event->shifts as $shift)
            {
                $shift->delete();
            }
        });
    }

and then similarly in the Shift model.

here, delete campaign -> delete all events ->delete all shifts

but of course it works just as well if I delete a single event - it automatically cascades to the shifts.

9 likes
ctroms's avatar

@Snapey Nice solution and good point on soft deletes. I was, possibly incorrectly, making assumptions.

Ykay's avatar

@jaheller I don't know if you have this figured out, but I don't see any solutions in the comment section. I just had a similar problem and figured it out quite easily (after scratching my head for about 30 minutes).

Anyway, you could just delete related models of the model, since you already created the Eloquent relationship for it. I won't be able to use your example, but the followed explanation should give you an idea:

So I have two models - User and Property User.php

public function properties()
    {
        return $this->hasMany('App\Models\Property');
    }

Property.php

public function user()
    {
        return $this->belongsTo('App\User');
    }

Thus, if I want to delete a particular user, and of course, I don't want any his properties to be retained in the database:

public function destroy($id)
    {
        $user = User::findOrFail($id);

        $user->properties()->delete();

        $user->delete();

        return [
            'message' => 'Delete Complete!'
        ];
    }

I hope you or anyone else finds this useful! Regards :)

6 likes
capslock's avatar

@Ykay Thankyou! Encountered similar problem and this worked for me.

Please or to participate in this conversation.