News

Laravel 14 Adds a defaults() Method to Eloquent Models

Published
Laravel 14 Adds a defaults() Method to Eloquent Models image

Eloquent models set default attribute values with the $attributes property. It works for fixed values, but PHP only allows constant expressions in a property's default value, so you cannot call config(), now(), or a feature flag there. Laravel 14 adds a defaults() method that returns the same array from code that runs when the model is created.

Before and After

Take a subscription model that gives new subscriptions a 14-day trial, and 30 days when an extended-trials feature flag is active. With $attributes, the flag has to be checked in the constructor:

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);
    }
}

In Laravel 14, the same logic goes in defaults():

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(),
        ];
    }
}
$subscription = new Subscription;

$subscription->trial_days; // 30 when the flag is active, 14 otherwise

Laravel 11 made the same move for casts, when the application skeleton switched from the $casts property to a casts() method (Model Casts are moving to methods in Laravel 11). defaults() gives $attributes a method version too.

How It Works

The model constructor calls defaults() and merges the result into $attributes. The order in the constructor decides which value wins:

  1. Values from the $attributes property are set first
  2. defaults() is merged over them, so it wins when both define the same key
  3. The attributes you pass to new, create(), or fill() are applied last, so they win over both
$subscription = Subscription::create(['trial_days' => 60]);

$subscription->trial_days; // 60

Defaults are merged before the model syncs its original attributes, so they do not count as dirty changes. They are still written to the database when the model is inserted, the same as $attributes.

Raw Values

Like $attributes, the values from defaults() are raw. They do not go through casts or mutators. Return the value as it would be stored in the database:

protected function defaults(): array
{
    return [
        // A column cast to `array` expects a JSON string
        'settings' => json_encode(['theme' => 'light']),

        // A date column
        'expires_at' => now()->addDays(30)->toDateTimeString(),
    ];
}

Returning a PHP array for a column cast to array or json fails when the attribute is read, because the cast expects a JSON string.

When defaults() Runs

The defaults() method runs every time a model instance is constructed. That includes models loaded from the database. Eloquent builds each retrieved row with a new model instance, so defaults() runs once per row, and then the row's values replace the defaults.

Upgrading

The method targets Laravel 14 because an existing model might already have a method named defaults(). In Laravel 14, the constructor calls it and merges whatever it returns into the attributes. Before upgrading, search your models for one:

grep -rn "function defaults" app/Models

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

Jack Bayliss contributed the method in #61688. It is merged into the master branch, and it can change before Laravel 14 is released.

Further Reading

Paul Redmond photo

Staff writer at Laravel News. Full stack web developer and author.

Sponsored

laravelcloud logo
Laravel Cloud

Easily create and manage your servers and deploy your Laravel applications in seconds.

Visit Laravel Cloud

The latest

View all →
Search Polymorphic Relations and Filament Tables With Laravel Searchable image

Search Polymorphic Relations and Filament Tables With Laravel Searchable

Read article
Laravel Rest Api 3.0: Typed Fields, Metrics, and OpenAPI Docs image

Laravel Rest Api 3.0: Typed Fields, Metrics, and OpenAPI Docs

Read article
Real-Time Inertia Props With Laravel Reverb image

Real-Time Inertia Props With Laravel Reverb

Read article
PhpStorm 2026.3 Adds an Agent Workspace and PHP 8.6 Support image

PhpStorm 2026.3 Adds an Agent Workspace and PHP 8.6 Support

Read article
Insert Middleware Before or After Existing Laravel Middleware image

Insert Middleware Before or After Existing Laravel Middleware

Read article
Laravel Herd 2: Coding Agents, Workspaces, and Cloud Deploys image

Laravel Herd 2: Coding Agents, Workspaces, and Cloud Deploys

Read article