77

In some of my tests, I have a user model I have created and I run some methods that need to save certain attributes. In rails, I would typically call something like user.reload which would repopulate the attributes from the database.

Is there a way in laravel to do that? I read through the api and couldn't find a method for it: http://laravel.com/api/4.1/Illuminate/Database/Eloquent/Model.html Any ideas on the "right" way to do this?

Jeff Puckett
  • 37,464
  • 17
  • 118
  • 167
matthew
  • 817
  • 1
  • 6
  • 7
  • Maybe the getDirty() method can help you. http://laravel.com/api/source-class-Illuminate.Database.Eloquent.Model.html#2149-2167 – Mathias Bak Jun 24 '14 at 11:57

5 Answers5

122

There was a commit submitted to the 4.0 branch made in August to add a reload() method, but so far it hasn't been merged with the newer Laravel branches.

But... Laravel 5 is providing a "fresh()" method that will return a new instance of the current model. Once you're using Laravel 5.0 or newer, you can reload a model like this:

$model = $model->fresh(); 

Note that fresh() doesn't directly update your existing $model, it just returns a new instance, so that's why we need to use "$model = ". It also accepts a parameter which is an array of relations that you want it to eager load.

If you aren't yet using Laravel 5 but you want the same functionality, you can add this method to your model(s):

public function fresh(array $with = array())
{
    $key = $this->getKeyName();
    return $this->exists ? static::with($with)->where($key, $this->getKey())->first() : null;
}

Update: If you're using Laravel 5.4.24 or newer, there is now a $model->refresh() method that you can use to refresh the object's attributes and relationships in place rather than fetching a new object like fresh() does. See Jeff Puckett answer for more specifics on that.

LinusGeffarth
  • 27,197
  • 29
  • 120
  • 174
orrd
  • 9,469
  • 5
  • 39
  • 31
94

Thanks to PR#19174 available since 5.4.24 is the refresh method.

$model->refresh();

This way you don't have to deal with reassignment as is shown in other answers with the fresh method, which is generally not helpful if you want to refresh a model that's been passed into another method because the variable assignment will be out of scope for the calling contexts to use later.

Jeff Puckett
  • 37,464
  • 17
  • 118
  • 167
  • 4
    This also works great for when utilizing model events! – kjdion84 Mar 05 '18 at 17:36
  • `fresh` is not working for me, when `refresh` is working. I'm using Laravel 5.7 – Yevgeniy Afanasyev Sep 30 '18 at 22:17
  • 7
    @Yevgeniy Afanasyev - `fresh()` returns a _new_ model instance, so you have to call `$model = $model->fresh()`, whereas `refresh()` reloads the model in place. – Soulriser Feb 20 '19 at 20:15
  • Laravel documentation links are broken. – Christos Lytras Aug 11 '20 at 01:53
  • @ChristosLytras thanks for the head's up. looks like they remove old docs for unsupported versions. looking at the current version, it's not really helpful, so instead of trying to maintain with future versions, I've just removed the link entirely – Jeff Puckett Aug 11 '20 at 02:52
  • hi @Jeff Puckett +1 thanks. the main use of `refresh()`/`fresh()` is **only** when you have an operation of `retrieve model/relationships`, `updating model/relationships` and finally **`re-retrieved model/relationships back from the database`**. I mean, talking within a HTTP request lifecycle, right, or is there another case? THANKS IN ADVANCE –  Jan 29 '23 at 19:09
71
  • refresh() is a mutable operation: It will reload the current model instance from the database.
  • fresh() is an immutable operation: It returns a new model instance from the database. It doesn't affect the current instance.
// Database state:
$user=User::create([
  'name' => 'John',
]);

// Model (memory) state:
$user->name = 'Sarah';

$user2 = $user->fresh();
// $user->name => 'Sarah';
// $user2->name => 'John'

$user->refresh();
// $user->name => 'John'
igaster
  • 12,983
  • 6
  • 26
  • 27
19

I can't see it either. Looks like you'll have to:

$model = $model->find($model->id);

You can also create one yourself:

public function reload()
{
    $instance = new static;

    $instance = $instance->newQuery()->find($this->{$this->primaryKey});

    $this->attributes = $instance->attributes;

    $this->original = $instance->original;
}

Just tested it here and it looks it works, not sure how far this goes, though, Eloquen is a pretty big class.

Andy Fleming
  • 7,655
  • 6
  • 33
  • 53
Antonio Carlos Ribeiro
  • 86,191
  • 22
  • 213
  • 204
  • 3
    -1: "Just tested it here and it looks it works, not sure how far this goes, though" - this is often pretty critical to get right. Plus, `$model->refresh();` is now available. – Jan Żankowski Nov 26 '20 at 16:06
1

I believe @Antonio' answer is the most correct, but depending on the use case, you could also use a combination of $model->setRawAttributes and $model->getAttributes.

$users = User::all();

foreach($users as $user)
{
    $rawAttributes = $user->getAttributes();

    // manipulate user as required 
    // ..
    // Once done, return attribute state

    $user->setRawAttributes($rawAttributes);
}

The primary downside to this is that you're only "reloading" the data attributes, not any relationships you've altered, etc. That might also be considered the plus side.

EDIT

As of L5 - fresh() is the way to go

Chris
  • 54,599
  • 30
  • 149
  • 186