Laravel model: fresh() vs refresh()

Published on

Laravel models have two methods for reloading the latest database values: fresh() and refresh(). They're often necessary in unit tests to assert the changes a controller made to the model.

TLDR: fresh() vs refresh()

Calling $fresh​Model = $model->fresh():

  • Fetches a new instance from the DB, leaving $model unchanged
  • Won't reload relationships unless explicitly passed in via ->fresh(with: ...)
  • Always uses SELECT *, ignoring previously selected columns

Calling $model->refresh():

  • Reloads the same $model instance and hands it back
  • Reloads all previously loaded relationships
  • Always uses SELECT *, ignoring previously selected columns

When performance matters, use neither

In performance-critical code, use neither fresh() nor refresh(). They have the same performance problems as serializing models in queued jobs. For example:

$user = User::query()
    // Only select specific columns from the User model
    ->select('id', 'email', 'name')
    // Load the "posts" relation, but only specific columns
    ->with('posts:id,title')
    // Load the "activities" relation, but only the latest 5
    ->with(['activities' => fn (Builder $query) => $query->latest()->take(5)])
    ->firstWhere('email', 'user@example.com');

// Both `fresh()` and `refresh()` will:
// - "SELECT *" every User column, ignoring the subset we picked
// - Reload posts and activities, ignoring the constraints we set
$freshUser = $user->fresh(with: ['posts', 'activities']);
$user->refresh();

To refresh a model efficiently, requery it manually:

$freshUser = User::select('id', 'email', 'name')->find($user->id);