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

hannylicious's avatar

Restoring a Soft Deleted record - best way?

Howdy all, I've got an app where a user can 'delete' a record they create and it gets soft deleted. That works fine. In the flash message that shows above after the delete (Trip xxx has been successfully deleted! UNDO) - UNDO is linked to a URL (trips/{trip->id}/restore). My methods in the controller look like this:

public function destroy(Trip $trip)
{
    $trip->delete();
    flash()->warning('Trip '.$trip->id.' successfully deleted! <a href=trips/'.$trip->id.'/restore>UNDO</a>');
    return redirect('trips');
}

public function restore(Request $request) 
{
    $trip = Trip::withTrashed()->where('id', $request['id'])->restore();
    return redirect ('trips');
}

When I click 'undo' it redirects me appropriately to the trips - but it doesn't restore the deleted trip.

Any thoughts?

0 likes
7 replies
tomopongrac's avatar
Level 51

Try

public function restore($id) 
{
    $trip = Trip::withTrashed()->find($id)->restore();
    return redirect ('trips');
}
2 likes
hannylicious's avatar

Huzzah! You've done it!

Excellent. I'm glad it was a simple fix - this really helped a lot. 3 cheers to you good sir!

Off topic:

Is there a best practice for getting rid of old soft deletes after a certain time period?

Prullenbak's avatar

something like

$carbon = //time till when they should be deleted
Trip::onlyTrashed()->where('deleted_at', '<', $carbon)->forceDelete();

don't know if forceDelete will work on a query, but you can try?

hannylicious's avatar

@kfirba - I will write up a cronjob - good idea, although @Prullenbak idea might be a cool way to attempt it programatically.

One other question if either you feel up to it.... when I run restore() on the trip... it changes the trip_date field to the current day/time. Originally that is set by the user when they create the trip... but when it's restored it saves it as the current day/time.

Is there a reason behind that? I would figure it would change the 'updated_at' column, but not the trip_date column.

hannylicious's avatar

I figured it out. It was in the DB. It had an attribute to 'on update set Current Timestamp', which was weird.

Fixed it though. Changed the migration to allow that particular column to be ->nullable(), reran the migration and life is good. Thanks for all your help!

kfirba's avatar

@hannylicious The cronjob that you will write will contain the logic to remove old records.

Your cronjob will eventually run a code like:

Trip::onlyTrashed()->where('deleted_at', '<', Carbon::subDays(30))->forceDelete();

The cronjob will just execute the code above every X days/months/years you want.

Please or to participate in this conversation.