Laravel #\[Refreshes\]: Load Generated Columns After Save | Mohamed Said       [Skip to content](#main)  [ ![](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png) Mohamed SaidLaravel Backend Engineer ](https://www.msaied.com/public) - [Home](https://www.msaied.com/public)
- [Projects](https://www.msaied.com/public/projects)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [About](https://www.msaied.com/public#about)

           [  Contact](https://www.msaied.com/public#contact) Menu 

Menu
----

Close 

 - [HomeStart here](https://www.msaied.com/public)
- [ProjectsCase studies](https://www.msaied.com/public/projects)
- [ArticlesEngineering notes](https://www.msaied.com/public/articles)
- [CertificatesCredentials](https://www.msaied.com/public/certificates)
- [AboutHow I work](https://www.msaied.com/public#about)
- [ContactGet in touch](https://www.msaied.com/public#contact)

  [Start a conversation](https://www.msaied.com/public#contact) [WhatsApp](https://wa.me/201094619204) [Email](mailto:hello@msaied.com) 

 1. [Home](https://www.msaied.com/public)
2. /
3. [Articles](https://www.msaied.com/public/articles)
4. /
5. [Laravel](https://www.msaied.com/public/articles?category=laravel)
6. /
7. Auto-Load Generated Columns After Save with Laravel's #\[Refreshes\] Attribute

   [Laravel](https://www.msaied.com/public/articles?category=laravel) [Tips &amp; Tricks](https://www.msaied.com/public/articles?category=tips-tricks) 

 Auto-Load Generated Columns After Save with Laravel's #\[Refreshes\] Attribute
===============================================================================

 Laravel 13.33 introduced the #\[Refreshes\] PHP attribute for Eloquent models. Declare which database-computed columns to reload and Eloquent fetches them automatically after every insert or update.

 ![](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp) [Mohamed Said](https://www.msaied.com/public#person) Published 23 Sep 2026 · Updated 24 Sep 2026 · 4 min read

ShareCopy linkCopied

 ![Auto-Load Generated Columns After Save with Laravel's #[Refreshes] Attribute](https://cdn.msaied.com/697/2450936023128760d64547a61ee24087.png) 

  On this page +1. [The Problem: Stale Models After a Write](#the-problem-stale-models-after-a-write)
2. [The Fix: #\[Refreshes\] in Laravel 13.33](#the-fix-refreshes-in-laravel-1333)
3. [Multiple Columns](#multiple-columns)
4. [Property-Based Configuration](#property-based-configuration)
5. [Generated Values in Model Events](#generated-values-in-model-events)
6. [Which Write Methods Trigger a Refresh](#which-write-methods-trigger-a-refresh)
7. [How the Refresh Query Works](#how-the-refresh-query-works)
8. [\#\[Refreshes\] vs. refresh()](#refreshes-vs-refresh)
9. [Key Takeaways](#key-takeaways)

 The Problem: Stale Models After a Write
---------------------------------------

When your database schema uses generated columns — columns whose value the database engine computes from other columns — Eloquent does not know about the result after a write. You get `null` on a freshly created model, and a stale value after an update.

Consider an `orders` table where `total` is a stored generated column:

```php
Schema::create('orders', function (Blueprint $table) {
    $table->id();
    $table->decimal('subtotal', 10, 2);
    $table->decimal('tax', 10, 2);
    $table->decimal('total', 10, 2)->storedAs('subtotal + tax');
    $table->timestamps();
});

```

Before Laravel 13.33, reading `total` right after a write returned nothing useful:

```php
$order = Order::create(['subtotal' => 100, 'tax' => 8.25]);
$order->total; // null

$order->update(['tax' => 9.00]);
$order->total; // still null

```

The only workaround was calling `$order->refresh()` manually after each write, which reloads every column and every loaded relationship — more work than you usually need.

The Fix: #\[Refreshes\] in Laravel 13.33
----------------------------------------

Laravel 13.33 ships the `#[Refreshes]` PHP attribute (contributed by Caleb White in PR #61523). Add it to your model and list the columns the database computes:

```php
use Illuminate\Database\Eloquent\Attributes\Refreshes;
use Illuminate\Database\Eloquent\Model;

#[Refreshes('total')]
class Order extends Model
{
    protected $fillable = ['subtotal', 'tax'];
}

```

After each insert or update, Eloquent runs a targeted `SELECT` for those columns and copies the values onto the model instance:

```php
$order = Order::create(['subtotal' => 100, 'tax' => 8.25]);
$order->total; // "108.25"

$order->update(['tax' => 9.00]);
$order->total; // "109.00"

```

### Multiple Columns

Pass an array or several arguments — both forms are equivalent:

```php
#[Refreshes(['total', 'slug'])]
#[Refreshes('total', 'slug')]

```

### Property-Based Configuration

If you prefer model properties over PHP attributes, use `$refreshes` instead:

```php
class Order extends Model
{
    protected array $refreshes = ['total'];
}

```

When both are present, the property wins and the attribute is ignored. A model with neither runs no extra query.

Generated Values in Model Events
--------------------------------

The refresh runs **after** the `INSERT` or `UPDATE` but **before** Eloquent fires `created` or `updated`. Observers and listeners therefore see the database-computed value immediately:

```php
class OrderObserver
{
    public function created(Order $order): void
    {
        Mail::to($order->customer)->send(new OrderReceipt($order));
    }

    public function updated(Order $order): void
    {
        if ($order->wasChanged('total')) {
            $order->customer->notify(new OrderTotalChanged($order));
        }
    }
}

```

The `wasChanged('total')` check works because Eloquent records the change after the refresh, even though your application code never set `total` directly.

Which Write Methods Trigger a Refresh
-------------------------------------

- **Inserts:** `create()`, `save()`, `saveQuietly()`, `saveOrIgnore()`
- **Updates:** `update()`, `save()`, `saveQuietly()`
- **Increment/decrement:** `increment()`, `decrement()`, `incrementEach()`, `decrementEach()`

How the Refresh Query Works
---------------------------

Eloquent issues a single `SELECT` scoped to the model's primary key:

```sql
select `total` from `orders` where `id` = ? limit 1

```

A few important details:

- The query runs on the **write connection**, so read-replica lag is not a concern.
- Global scopes (soft deletes, tenant scopes) are **skipped**, so the row is always found.
- It uses `firstOrFail()` — if the row has been deleted between the write and the refresh, a `ModelNotFoundException` is thrown.

\#\[Refreshes\] vs. refresh()
-----------------------------

| Scenario | Use | |---|---| | Always need a generated column after every write | `#[Refreshes]` | | Need the full row or relationships reloaded | `$model->refresh()` | | One-off write where adding the attribute would penalise every other save | `$model->refresh()` |

Key Takeaways
-------------

- `#[Refreshes]` was introduced in Laravel 13.33 and eliminates the need to call `refresh()` just to read database-generated column values.
- It adds exactly one `SELECT` per write, limited to the columns you list.
- Model events (`created`, `updated`) fire after the refresh, so listeners always see the computed value.
- The `$refreshes` property alternative is available for teams that avoid PHP attributes on models.
- Use `$model->refresh()` when you need the entire row or loaded relationships reloaded.

---

*Source: [Eloquent Refreshes: Load Generated Columns After Save — Laravel News](https://laravel-news.com/eloquent-refreshes-attribute)*

- [Laravel](https://www.msaied.com/public/articles?search=Laravel)
- [Eloquent](https://www.msaied.com/public/articles?search=Eloquent)
- [Generated Columns](https://www.msaied.com/public/articles?search=Generated%20Columns)
- [Laravel 13](https://www.msaied.com/public/articles?search=Laravel%2013)
- [PHP Attributes](https://www.msaied.com/public/articles?search=PHP%20Attributes)

 Frequently asked questions 
---------------------------

  Does #\[Refreshes\] work with virtual (non-stored) generated columns?Yes. The attribute is designed for any column whose value the database sets, including both stored (`storedAs`) and virtual (`virtualAs`) generated columns, as well as values set by database triggers or defaults that Eloquent does not manage.

   Will #\[Refreshes\] cause problems when using read replicas?The refresh query runs on the write connection, not a read replica, so replication lag does not affect it. The query always targets the server where the row was just written.

   What happens if I declare both the #\[Refreshes\] attribute and the $refreshes property on the same model?The $refreshes property takes precedence and the PHP attribute is ignored. A model with neither defined runs no extra query after writes.

   ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)About the author
----------------

[Mohamed Said](https://www.msaied.com/public#person)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

[About](https://www.msaied.com/public#about) [GitHub ↗](https://github.com/EG-Mohamed) [LinkedIn ↗](https://www.linkedin.com/in/msaiedm/) [WhatsApp ↗](https://wa.me/201094619204) [Email Address ↗](mailto:hello@msaied.com) [My CV ↗](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)  

   [Previous articleLaravel AI SDK 1.0: Classification, Tool Approvals, and Vercel Chat Streaming](https://www.msaied.com/public/articles/laravel-ai-sdk-10-classification-tool-approvals-and-vercel-chat-streaming) [Next articleJetBrains Air: Run AI Coding Agents Directly in JetBrains IDEs](https://www.msaied.com/public/articles/jetbrains-air-run-ai-coding-agents-directly-in-jetbrains-ides)  

   On this page
-------------

1. [The Problem: Stale Models After a Write](#the-problem-stale-models-after-a-write)
2. [The Fix: #\[Refreshes\] in Laravel 13.33](#the-fix-refreshes-in-laravel-1333)
3. [Multiple Columns](#multiple-columns)
4. [Property-Based Configuration](#property-based-configuration)
5. [Generated Values in Model Events](#generated-values-in-model-events)
6. [Which Write Methods Trigger a Refresh](#which-write-methods-trigger-a-refresh)
7. [How the Refresh Query Works](#how-the-refresh-query-works)
8. [\#\[Refreshes\] vs. refresh()](#refreshes-vs-refresh)
9. [Key Takeaways](#key-takeaways)

 ###  Have a technical challenge?

 Tell me what you’re building. I reply within two working days.

[Start a conversation](https://www.msaied.com/public#contact) 

   Related articles
-----------------

 [ ![](https://cdn.msaied.com/743/8998fac3a41451ab3fe1588194e17a43.png) Filament · 3 min read### Securing Filament Plugins with Plumb: Automated Security Scoring for PHP Packages

5 Oct 2026 ](https://www.msaied.com/public/articles/securing-filament-plugins-with-plumb-automated-security-scoring-for-php-packages) [ ![](https://cdn.msaied.com/742/2d02018669cdeedccb5de2efb898f0ee.png) Filament · 3 min read### Filament v3.3.56 Released: File Hash Names and Livewire Upload Fix

5 Oct 2026 ](https://www.msaied.com/public/articles/filament-v3356-released-file-hash-names-and-livewire-upload-fix) [ ![](https://cdn.msaied.com/741/5b55c123ad08e4d34e1f4b99ad6a428b.png)  · 3 min read### Filament v4 Schema-Based Forms, Infolists, and the Unified Schema API

5 Oct 2026 ](https://www.msaied.com/public/articles/filament-v4-schema-based-forms-infolists-and-the-unified-schema-api-5) 

  Have a technical challenge?
----------------------------

Tell me what you’re building. I reply within two working days.

 [Discuss your project ↗](https://www.msaied.com/public#contact) 

  © 2026 Mohamed Said · Built with Laravel, meant to last.Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

 - [Home](https://www.msaied.com/public)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [GitHub](https://github.com/EG-Mohamed)
- [LinkedIn](https://www.linkedin.com/in/msaiedm/)
- [WhatsApp](https://wa.me/201094619204)
- [Email Address](mailto:hello@msaied.com)
- [My CV](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
- [Sitemap](https://www.msaied.com/public/sitemap.xml)
