0

This works fine:

$post->comments()->withTrashed()->get()->each->delete();

Since it does indeed delete the 6 rows the each returns as a Collection.

However, this throws an exception:

$post->comments()->withTrashed()->get()->each->restore();

I noticed it also restored 1 row (the first row) in the database (the Collection has 6 rows).

Context: I use such code in an Observer to restore Comments when I restore a Post.

The following will throw the exact same exception InvalidArgumentException with message 'Illegale operator and value combination.' :

$post->comments()->withTrashed()->where('deleted_at', '>=', $post->deleted_at)->get()->each->restore();

The where() condition allows me to restore only comments softdeleted alongside the post's softdeletion (so that it does not also restore comments deleted by moderators prior to the whole post deletion).

Udo E.
  • 2,665
  • 2
  • 21
  • 33
Musa
  • 1,334
  • 1
  • 11
  • 21
  • Looks like you might encounter this [error](https://github.com/laravel/framework/blob/3ec56b8810bc40016252977c69ba27057dcecf7d/src/Illuminate/Database/Query/Builder.php#L763) is the respective `$value` is null. [The condition](https://github.com/laravel/framework/blob/3ec56b8810bc40016252977c69ba27057dcecf7d/src/Illuminate/Database/Query/Builder.php#L747) where the error may be thrown. – Adam Rodriguez Oct 08 '19 at 00:28
  • I identified the bug. The Observer triggers on ```restored()``` Post model event. So the ```$post->deleted_at``` attribute is ```null``` after first iteration (which explains why it updated only the first database row and then threw an exception since then it performs ```>=``` on null. I managed to quickfix changing ```restored()``` to ```restoring()``` but I'm not happy with it. I want to restore comments after the post is restored, not before. – Musa Oct 08 '19 at 02:28

2 Answers2

0

$post->comments()->onlyTrashed()->get()->each->restore();

Don't know if it helps but you can try this. Since restore can only work on trashed posts maybe that is what is causing the problem.

  • Also I don't think you need withTrashed() when you are deleting. Because a trashed comment can't be trashed twice. I'm sure if your run this twice it will open a problem like restore is. just do – Gerald Ibra Oct 08 '19 at 09:39
  • $post->comments()->get()->each->delete(); – Gerald Ibra Oct 08 '19 at 09:40
0
        $post->comments()
            ->onlyTrashed()->where('deleted_at', '>=', $post->deleted_at)
            ->get()
            ->each->restore();

This actually works. The problem was because my Observer triggers at restored, which would cause $post->deleted_at to be null right after first iteration. Problem was fixed using restoring() model event instead of restored().

This (above) answers my initial question.

I have not yet figured a way to keep using restored (I want comments to be restored after the post is restored), since restored makes $post->deleted_at become null thus non valid within my where() condition. I need to find a way to hold the original $post->deleted_at value, while using restored(). getDirty() and getChanges() did not help. I will accept my own answer in 3 days unless someone shares a way to also keep the restored event. I believe this is out of the scope of the initial question anyway?

Musa
  • 1,334
  • 1
  • 11
  • 21