denny's avatar
Level 4

Most efficient solution to delete through hasMany relationship in a way that fires "deleting" method on the collection?

In my app, I have Site and Archive models where each Site hasMany Archives. Each Archive, in addition to having a record in the DB, has a file that's uploaded to S3.

When deleting an individual Archive, I have a job attached to the deleting event to process the file deletion in the background:

  class Archive extends Model
  {
    public static function boot()
    {
      parent::boot();

      //when archive deleted, make sure to remove the file from S3
      Archive::deleting(function ($archive) {
          return dispatch(new DeleteArchive($archive->path));
      });
    }
  }

That part works great. Delete an Archive record and the file is gone from S3 in a few moments.

In addition, I want to be able to have the user delete a Site and then cascade that deletion through all of the associated Archives.

I was hoping that would be as easy as doing $site->archives()->delete() but this only deletes the records in the DB and never fires the 'deleting' event on my Archive model.

Apparently there is a logical (yet unintuitive) reason for this (as explained here: https://github.com/laravel/framework/issues/2536), and the suggested solution is to individually load each Archive record that needs to be deleted such as:

class Site extends Model
{
  public static function boot()
  {
    parent::boot();

    Site::deleting(function ($site) {
      $site->archives()->each(function($archive) {
        $archive->delete();
      });
    });
  }
}

I'm pretty new to Laravel but something about having to cycle through each individual $archive like that feels dirty and inefficient based on everything else I've encountered in the framework thus far.

Is that really the best way to handle a cascading delete where we need to be able to hook into the deleting event?

Thanks!

0 likes
0 replies

Please or to participate in this conversation.