Eray Erdin
Eray Erdin

Reputation: 3179

How to Select Fields When Refreshing Model in Laravel

As you probably know, we can use refresh method on a model instance in order to refresh it from the database.

Refresh completely reloads all columns from database. refresh method does not seem to take any input, so I was wondering if there is a way to refresh some fields from the database.

To demonstrate, let's have a pseudo-model as below:

Foo
---
bar: char
baz: char

And I have a single instance of Foo called $foo. $foo->refresh() fetches both $foo->bar and $foo->baz. How do I only fetch/refresh bar field?

Thanks in advance.


Environment

Upvotes: 0

Views: 685

Answers (1)

Pablo Villalba
Pablo Villalba

Reputation: 533

I think there's no way to do such. The best option you have is to get the PK of your $foo object and query for the fields you want:

$id = $foo->id;
$refreshed = Foo::select('bar')->where('id', '=', $id)->first();
$foo->bar = $refreshed->bar;

However, this will unsync your model with the database. Another option is to create a custom method in your model that does it in a more abstract way and retrieves the new unsynced object:

// In your model:
public function refreshField(string $field)
{
    $this->$field = (new static())
        ->select($field)
        ->where($this->key(), '=', $this->{$this->key()})
        ->first()->$field;

    return $this;
}

// Then outside:
$foo = Foo::first();
// perform actions. . .
$foo->refreshField('bar');

Again, keep in mind that this will keep your model unsynced with the database. Also, this is a POC, I didn't test it, but the general idea should work. If you create a parent model and extend all your other models from this (which extends from Eloquent), this should work with any of your models.

For a more complete version, you can pass an array instead of a string and retrieve all the fields that you want to refresh, then assign them in a loop:

public function refresFields(string ...$fields)
{
    $fields = $this->$field = (new static())
        ->select($fields)
        ->where($this->key(), '=', $this->{$this->key()})
        ->first();

    foreach ($fields as $field) {
        $this->$field = $field;
    }

    return $this;
}

I wouldn't recommend this, but if you really need it, give it a try. Good luck

Upvotes: 1

Related Questions