veilletech.fr
25 sept. Feed du jour
#07 LARAVEL Article

Laravel 13.33 : les colonnes calculées enfin à jour

La base a calculé. Le modèle le sait enfin.

Laravel 13.33 ajoute l'attribut #[Refreshes] : Eloquent relit les colonnes calculées par la base (storedAs, virtualAs, triggers, valeurs par défaut) après chaque insertion ou mise à jour, avant les événements du modèle. Plus besoin d'appeler refresh(), qui recharge toute la ligne et les relations.

2 min de lectureintermédiairevidéo 1:19
Partager
Sommaire7 sections
  1. Ce qui se passe
  2. Le problème
  3. La solution
  4. Le détail qui compte : l'ordre
  5. Les limites
  6. Comment s'y prendre
  7. À retenir

Ce qui se passe

Laravel 13.33 introduit l'attribut #[Refreshes], proposé par Caleb White (PR #61523). Il corrige un piège ancien d'Eloquent : les colonnes calculées par la base ne sont pas relues après une écriture.

Le problème

Prenons une facture dont le total TTC est calculé par la base :

PHP
$table->decimal('total_ttc', 10, 2)->storedAs('total_ht * (1 + vat_rate)');

Après Invoice::create([...]), $invoice->total_ttc vaut null. Après un update(), il garde l'ancienne valeur. La parade habituelle, refresh(), relit toute la ligne et recharge toutes les relations déjà chargées.

La solution

PHP
use Illuminate\Database\Eloquent\Attributes\Refreshes;
use Illuminate\Database\Eloquent\Model;

#[Refreshes('total_ttc', 'reference')]
class Invoice extends Model
{
    protected $fillable = ['total_ht', 'vat_rate'];
}

Plusieurs colonnes se passent en tableau ou en arguments successifs. Sans attribut, la propriété protected array $refreshes fait la même chose ; si les deux sont présents, la propriété l'emporte. Un modèle qui n'a ni l'un ni l'autre ne déclenche aucune requête en plus.

Après chaque INSERT ou UPDATE, Eloquent lit ces seules colonnes par la clé primaire et les recopie sur le modèle. Sont concernés create(), save(), saveQuietly(), saveOrIgnore(), update(), ainsi que increment(), decrement(), incrementEach() et decrementEach().

Le détail qui compte : l'ordre

La relecture a lieu avant les événements created et updated. Un observer qui envoie la facture lit donc le bon total, et wasChanged('total_ttc') répond true alors que votre code n'a jamais écrit cette colonne : elle figure dans getChanges().

Les limites

Comment s'y prendre

Cherchez les refresh() qui suivent un create() ou un update() : ce sont les premiers candidats. L'attribut vaut aussi pour les colonnes remplies par un trigger ou par une valeur par défaut que pose la base. Pour une écriture isolée, gardez refresh() : l'attribut ajouterait une requête à toutes les autres. Détails dans la documentation Eloquent.

Source : Eloquent Refreshes: Load Generated Columns After Save, Laravel News, 24 septembre 2026.