1

My model is something like this:

namespace App;
use Illuminate\Database\Eloquent\SoftDeletes;

class Photo extends Model {
    use SoftDeletes;
    protected $dates = ['deleted_at'];
}

_ I can soft delete using:

$\App\Photo::find(1)->delete();

_ It does not work when I try to use soft delete on multiple rows:

\App\Photo::whereIn('id', [1,2,3])->delete();

Does any one know why?

1

3 Answers 3

3

No, you can't soft delete multiple rows. The only Laravel way is the DB facade in this case. Here is how I would soft delete multiple rows.

DB::table('table_name')->whereIn('id', [array of ids])
            ->update([
                'deleted_at' => now()
            ]);

or

ModelName::whereIn('id', [array of ids])
           ->update(['deleted_at' => now()]);

Instead of whereIn you can put in any where condition like you usually put and can update the deleted_at key. Soft delete is nothing but marking the column as deleted.

This is also a very efficient solution rather than running soft delete for each model inside a loop which can crash the system if there're too many items in the array. Hope this helps.

Sign up to request clarification or add additional context in comments.

2 Comments

I follow this, but it can't trash multiple rows selected, it only delete a rows, but when I load a page again, all the rows of data I've deleted appear again. Why?
If you're getting the data using model, make sure that you've added softDeletes trait in the model. If you're using DB facade to fetch data, make sure to add the filter whereNotNull('deleted_at')
2

The soft delete functionality only works on an instance of the Eloquent model itself. When you are doing this:

\App\Photo::find(1)->delete();

You are actually first retrieving the Photo with an ID of 1 from the database which is then prepared and made available as an instance of the Eloquent model (which can then use soft delete).

However, when you do this:

\App\Photo::whereIn('id', [1,2,3])->delete();

You are not actually retrieving anything from the database, you are basically just preparing DELETE SQL in a more convenient way. This effectively runs something like:

DELETE FROM `photos` WHERE `id` IN (1,2,3);

This is different from something like:

foreach (\App\Photo::whereIn('id', [1,2,3])->get() as $photo) {

    $photo->delete();  # $photo is an eloquent model and can soft-delete

}

Notice the ->get() which is actually grabbing data from the database first and will make it available as a collection of Eloquent models (which then can soft delete).

I don't think you can soft-delete a batch. In my foreach example using ->get() I imagine multiple queries are executed - something like:

UPDATE `photos` SET `deleted_at` = NOW() WHERE `id` = 1;
UPDATE `photos` SET `deleted_at` = NOW() WHERE `id` = 2;
UPDATE `photos` SET `deleted_at` = NOW() WHERE `id` = 3;

Hope that makes sense.

1 Comment

Thank you for your answer. I also found out that my boot function missing parent::boot(); In my case, this causes my code does not work.
0

Try this as well:

\App\Photo::whereIn('id', [1,2,3])
    ->get()
    ->map(function($photo) {
        $photo->delete();
    });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.