Laravel 14: Eloquent defaults() Method Explained | 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. Laravel 14 Adds a defaults() Method to Eloquent Models

   [Laravel](https://www.msaied.com/public/articles?category=laravel) 

 Laravel 14 Adds a defaults() Method to Eloquent Models
=======================================================

 Laravel 14 introduces a defaults() method for Eloquent models, letting you set dynamic default attribute values using config(), now(), feature flags, and any runtime PHP expression.

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

ShareCopy linkCopied

 ![Laravel 14 Adds a defaults() Method to Eloquent Models](https://cdn.msaied.com/725/6d4daa85070ffb81d6a9a3e25a8ed08c.png) 

  On this page +1. [Laravel 14 Brings a defaults() Method to Eloquent Models](#laravel-14-brings-a-codedefaultscode-method-to-eloquent-models)
2. [The Problem with $attributes](#the-problem-with-codeattributescode)
3. [The defaults() Method in Laravel 14](#the-codedefaultscode-method-in-laravel-14)
4. [Merge Priority](#merge-priority)
5. [Raw Values Only](#raw-values-only)
6. [When defaults() Runs](#when-codedefaultscode-runs)
7. [Upgrading: Check for Name Conflicts](#upgrading-check-for-name-conflicts)
8. [Key Takeaways](#key-takeaways)

 Laravel 14 Brings a `defaults()` Method to Eloquent Models
----------------------------------------------------------

Eloquent models have long used the `$attributes` property to define default column values. It works well for static values, but PHP only permits constant expressions in property defaults — meaning you cannot call `config()`, `now()`, or check a feature flag there. Laravel 14 solves this cleanly with a new `defaults()` method.

The feature was contributed by [Jack Bayliss](https://github.com/jackbayliss) in [PR #61688](https://github.com/laravel/framework/pull/61688) and is merged into the `master` branch. It may still change before Laravel 14 is officially released.

---

The Problem with `$attributes`
------------------------------

When default values depend on runtime state — a feature flag, a config value, or the current timestamp — developers had to override `__construct()` to apply them:

```php
class Subscription extends Model
{
    protected $attributes = [
        'cancelled' => false,
        'trial_days' => 14,
    ];

    public function __construct(array $attributes = [])
    {
        if (Feature::active('extended-trials')) {
            $this->attributes['trial_days'] = 30;
        }

        parent::__construct($attributes);
    }
}

```

This works, but it is boilerplate that clutters the model and is easy to get wrong (calling `parent::__construct()` at the wrong point, for example).

---

The `defaults()` Method in Laravel 14
-------------------------------------

In Laravel 14 you move that logic into a dedicated `defaults()` method:

```php
class Subscription extends Model
{
    protected function defaults(): array
    {
        return [
            'cancelled'  => false,
            'trial_days' => Feature::active('extended-trials') ? 30 : 14,
            'expires_at' => now()->addDays(config('billing.grace_period'))->toDateTimeString(),
        ];
    }
}

```

Instantiating the model now reflects the runtime state automatically:

```php
$subscription = new Subscription;
$subscription->trial_days; // 30 when the flag is active, 14 otherwise

```

---

Merge Priority
--------------

The constructor applies values in a predictable order:

1. `$attributes` property values are set first.
2. `defaults()` is merged over them — it wins when both define the same key.
3. Values passed to `new`, `create()`, or `fill()` are applied last and win over both.

```php
$subscription = Subscription::create(['trial_days' => 60]);
$subscription->trial_days; // 60

```

Defaults are merged before the model syncs its original attributes, so they are **not** treated as dirty changes. They are still written to the database on insert, just like `$attributes`.

---

Raw Values Only
---------------

Like `$attributes`, values returned from `defaults()` are **raw** — they bypass casts and mutators. Return the value exactly as it should be stored in the database:

```php
protected function defaults(): array
{
    return [
        // Column cast to `array` expects a JSON string
        'settings'   => json_encode(['theme' => 'light']),
        // Date column
        'expires_at' => now()->addDays(30)->toDateTimeString(),
    ];
}

```

Returning a PHP array for a JSON-cast column will cause a read error because the cast expects a string.

---

When `defaults()` Runs
----------------------

`defaults()` is called every time a model instance is constructed — including rows loaded from the database. Eloquent builds each retrieved row with a new model instance, so `defaults()` runs once per row before the database values replace the defaults.

---

Upgrading: Check for Name Conflicts
-----------------------------------

Because an existing model might already have a method named `defaults()`, Laravel 14 targets this as a breaking change. Before upgrading, scan your models:

```bash
grep -rn "function defaults" app/Models

```

Rename any method that is not intended to return default attribute values.

---

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

- `defaults()` replaces constructor hacks for dynamic Eloquent default attributes.
- It supports any PHP expression: `config()`, `now()`, feature flags, etc.
- Values are **raw** — no casts or mutators are applied.
- Explicitly passed attributes always win over `defaults()`.
- Run `grep -rn "function defaults" app/Models` before upgrading to avoid conflicts.
- The feature is merged but may change before Laravel 14 ships.

---

*Source: [Laravel 14 Adds a defaults() Method to Eloquent Models — Laravel News](https://laravel-news.com/laravel-model-defaults)*

- [Laravel 14](https://www.msaied.com/public/articles?search=Laravel%2014)
- [Eloquent](https://www.msaied.com/public/articles?search=Eloquent)
- [Model Defaults](https://www.msaied.com/public/articles?search=Model%20Defaults)
- [PHP](https://www.msaied.com/public/articles?search=PHP)
- [Feature Flags](https://www.msaied.com/public/articles?search=Feature%20Flags)

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

  What is the difference between $attributes and defaults() in Laravel 14 Eloquent models?$attributes only accepts constant PHP expressions, so you cannot use config(), now(), or feature flags there. The defaults() method runs at construction time and accepts any PHP expression, making it suitable for dynamic default values.

   Do values from defaults() go through Eloquent casts or mutators?No. Like $attributes, values returned from defaults() are raw and bypass casts and mutators. You must return the value in the exact format the database column expects — for example, a JSON string for a column cast to array.

   What should I do before upgrading to Laravel 14 if I already have a defaults() method on a model?Run `grep -rn "function defaults" app/Models` to find any existing defaults() methods. Rename any method that is not intended to return default attribute values, because Laravel 14's constructor will call defaults() and merge its return value into the model's attributes.

   ![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 and Laravel MCP Security Fixes: Update Now](https://www.msaied.com/public/articles/laravel-ai-sdk-and-laravel-mcp-security-fixes-update-now) [Next articlePostcodes for Laravel: GB Postcode Lookup and Geography Data](https://www.msaied.com/public/articles/postcodes-for-laravel-gb-postcode-lookup-and-geography-data)  

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

1. [Laravel 14 Brings a defaults() Method to Eloquent Models](#laravel-14-brings-a-codedefaultscode-method-to-eloquent-models)
2. [The Problem with $attributes](#the-problem-with-codeattributescode)
3. [The defaults() Method in Laravel 14](#the-codedefaultscode-method-in-laravel-14)
4. [Merge Priority](#merge-priority)
5. [Raw Values Only](#raw-values-only)
6. [When defaults() Runs](#when-codedefaultscode-runs)
7. [Upgrading: Check for Name Conflicts](#upgrading-check-for-name-conflicts)
8. [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/740/cce86edc21eddcbdd2f2454fadaf9c70.png)  · 3 min read### The Pipeline Pattern in Laravel: Custom Pipelines Beyond Middleware

5 Oct 2026 ](https://www.msaied.com/public/articles/the-pipeline-pattern-in-laravel-custom-pipelines-beyond-middleware-1) [ ![](https://cdn.msaied.com/739/2d6897fdcdcf090613f96f72a64b8a78.png)  · 4 min read### MySQL Full-Text Search in Laravel: Indexes, Relevance Scoring, and Boolean Mode

4 Oct 2026 ](https://www.msaied.com/public/articles/mysql-full-text-search-in-laravel-indexes-relevance-scoring-and-boolean-mode) [ ![](https://cdn.msaied.com/738/073696a3fefe18bec825beec5ac658f5.png)  · 4 min read### Laravel Queue Rate-Limited Middleware: Throttling Jobs Without Losing Work

4 Oct 2026 ](https://www.msaied.com/public/articles/laravel-queue-rate-limited-middleware-throttling-jobs-without-losing-work) 

  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)
