When you create an Eloquent mannequin and skim a generated column straight again, you get null. Once you replace a mannequin the column retains its previous worth till you name refresh().
Laravel 13.33 launched the #[Refreshes] attribute to repair this potential difficulty: record the columns the database computes, and Eloquent reads them again after each insert and replace.
Let’s have a look at how you should utilize this trait to mechanically load generated columns after save with out remembering to referesh.
Generated Columns and Stale Fashions
Take an orders desk the place the database calculates complete from two different columns:
Schema::create('orders', perform (Blueprint $desk) {
$desk->id();
$desk->decimal('subtotal', 10, 2);
$desk->decimal('tax', 10, 2);
$desk->decimal('complete', 10, 2)->storedAs('subtotal + tax');
$desk->timestamps();
});
You may question and index complete like another column, however the mannequin you get again from create() doesn’t have it:
$order = Order::create(['subtotal' => 100, 'tax' => 8.25]);
Â
$order->complete; // null
Â
$order->replace(['tax' => 9.00]);
Â
$order->complete; // nonetheless null
Earlier than this launch, you needed to manually name $order->refresh() after every write, which reloads each column and each loaded relationship.
Including the Refreshes Attribute
Caleb White added #[Refreshes] in #61523. Put it on the mannequin and record the columns the database units:
use IlluminateDatabaseEloquentAttributesRefreshes;
use IlluminateDatabaseEloquentModel;
Â
#[Refreshes('total')]
class Order extends Mannequin
{
protected $fillable = ['subtotal', 'tax'];
}
After every insert or replace, Eloquent selects these columns for the saved row and copies them onto the mannequin:
$order = Order::create(['subtotal' => 100, 'tax' => 8.25]);
Â
$order->complete; // "108.25"
Â
$order->replace(['tax' => 9.00]);
Â
$order->complete; // "109.00"
To refresh a couple of column, move an array or a number of arguments. #[Refreshes(['total', 'slug'])] and #[Refreshes('total', 'slug')] do the identical factor.
When you configure fashions with properties as an alternative of attributes, set $refreshes:
class Order extends Mannequin
{
protected array $refreshes = ['total'];
}
When a mannequin has each, the property is used and the attribute is ignored. A mannequin with neither runs no additional question.
Generated Values in Mannequin Occasions
The refresh runs after the INSERT or UPDATE and earlier than Eloquent fires created or up to date, so listeners on both occasion see the brand new worth. An observer that sends a receipt can learn the entire the database calculated:
class OrderObserver
{
public perform created(Order $order): void
{
Mail::to($order->buyer)->ship(new OrderReceipt($order));
}
Â
public perform up to date(Order $order): void
{
if ($order->wasChanged('complete')) {
$order->buyer->notify(new OrderTotalChanged($order));
}
}
}
The wasChanged('complete') examine works as a result of Eloquent data the adjustments after the refresh. Your code by no means units complete, nevertheless it seems in getChanges() when the database calculates a brand new worth.
Which Writes Set off a Refresh
The refresh runs on a mannequin occasion in these eventualities:
- Inserts from
create(),save(),saveQuietly(), andsaveOrIgnore() - Updates from
replace(),save(), andsaveQuietly() - Increment/decrement calls:
increment(),decrement(),incrementEach(), anddecrementEach()
How the Refresh Question Works
The refresh is one SELECT for the listed columns, scoped to the mannequin’s major key:
choose `complete` from `orders` the place `id` = ? restrict 1
The question runs on the write connection. With learn replicas, a duplicate may not have the brand new row but.
It additionally skips world scopes, which implies a tenant or soft-delete scope can not conceal the row Eloquent simply saved. And it makes use of firstOrFail(): if the row is gone by the point the question runs, the save throws a ModelNotFoundException.
Refreshes or refresh()
#[Refreshes] matches columns you learn proper after a write: storedAs and virtualAs columns, values {that a} set off units, and database defaults that Eloquent doesn’t set. The attribute provides a question to each write, so record solely the columns you learn again.
Name $model->refresh() if you want the entire row or the loaded relationships re-read. You may also name it for a one-off write, the place including the attribute to the mannequin would put an additional question on each different save.
The Eloquent documentation covers the attribute below “Refreshing Attributes After Writes.”

