Soft deletes (the SoftDeletes trait) don't actually remove a row — they set a deleted_at timestamp and Eloquent silently excludes it from normal queries. That silence is the whole feature, and also the thing people trip over.
Including soft-deleted rows: withTrashed()
$allUsers = User::withTrashed()->get(); // includes soft-deleted rows
Only the soft-deleted rows: onlyTrashed()
$deletedUsers = User::onlyTrashed()->get();
Restoring a soft-deleted row
$user = User::onlyTrashed()->find($id);
$user->restore();
Or in one line:
User::onlyTrashed()->where('id', $id)->restore();
Permanently deleting it
User::onlyTrashed()->where('id', $id)->forceDelete();
The relationship gotcha
This is the part that causes real bugs: a soft-deleted parent's related rows don't show up through a normal relationship query either, because the relationship query goes through the same SoftDeletes global scope.
// A post's soft-deleted comments are invisible here by default:
$post->comments;
// Include them explicitly:
$post->comments()->withTrashed()->get();
This matters most for withCount() and eager-loading: a count that silently excludes soft-deleted related rows can look like a data bug when it's actually the intended behavior — just not the behavior you expected in that specific query.