Paul Redmond explicó el cambio en Laravel News el 1 de octubre de 2026. Laravel 14 añade a los modelos Eloquent un método protegido defaults(): array. La propiedad $attributes sigue siendo útil para valores fijos, pero PHP solo permite expresiones constantes en los valores iniciales de las propiedades. Las llamadas a config(), now() y las comprobaciones de funcionalidades deben ejecutarse en otro punto.

Subscription.php
<?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(),
        ];
    }
}

El ejemplo usa un modelo Subscription. Las nuevas suscripciones empiezan con 14 días de prueba y cancelled queda en false. Feature::active('extended-trials') puede elevar trial_days a 30. El método también calcula expires_at mediante now()->addDays(config('billing.grace_period'))->toDateTimeString(). Antes, el constructor comprobaba la feature flag y modificaba trial_days antes de llamar a parent::__construct($attributes).

Eloquent ejecuta defaults() durante la construcción y combina el resultado con los atributos del modelo. Primero aplica los valores de $attributes. Después defaults() sobrescribe las claves coincidentes. Los valores entregados a new, create() o fill() se aplican al final y tienen prioridad. Por eso Subscription::create(['trial_days' => 60]) conserva 60. La combinación sucede antes de sincronizar los atributos originales, así que estos valores no aparecen como dirty. Al insertar, sí se guardan en la base de datos como los valores de $attributes.

Los valores de defaults() llegan sin procesar. En ese momento no pasan por casts ni mutadores. Una columna settings con cast array o JSON necesita una cadena JSON, por ejemplo json_encode(['theme' => 'light']). Para una fecha puede usarse now()->addDays(30)->toDateTimeString(). Si se devuelve un array de PHP para una columna con cast array o JSON, la lectura falla porque el cast espera JSON.

El método se ejecuta cada vez que Eloquent construye una instancia, también al hidratar filas obtenidas de la base de datos. Cada fila recuperada genera un modelo nuevo y sus valores almacenados sustituyen después a los valores predeterminados calculados.

Laravel 11 había aplicado un cambio parecido a los casts al pasar el esqueleto de la aplicación de la propiedad $casts al método casts(). Laravel 14 introduce defaults() para evitar ambigüedades con métodos existentes que ya usen ese nombre. Antes de actualizar, conviene buscar con `grep -rn "function defaults" app/Models` y renombrar los métodos que no devuelvan atributos predeterminados. Jack Bayliss aportó el cambio en la PR #61688. Ya está fusionado en la rama master, aunque todavía puede cambiar antes del lanzamiento de Laravel 14.