Laravel: de fout ‘Unknown column updated_at’ oplossen

De Eloquent-ORM van Laravel maakt het werken met je database eenvoudig: alle CRUD-operaties en de meeste queries kosten je een paar regels code. Eloquent gaat er daarbij van uit dat de kolommen created_at en updated_at in je tabel bestaan, en dat is precies wat er misgaat wanneer deze fout opduikt.

Laravel: de fout ‘Unknown column updated_at’ oplossen
Kort antwoord

Eloquent schrijft bij elke insert created_at en updated_at weg: de fout betekent dat je tabel ze niet heeft. Drie oplossingen, afhankelijk van het geval: voeg ze toe met een migratie via $table->timestamps(), schakel ze uit met public $timestamps = false; op het model, of geef hun echte namen op met de constanten CREATED_AT en UPDATED_AT.

De melding valt bij de eerste save() of create() op een model:

code
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in 'INSERT INTO'

De oorzaak is altijd dezelfde: Eloquent houdt twee datumkolommen bij, created_at en updated_at, en schrijft ze bij elke insert en elke update weg. Heeft de tabel ze niet, dan faalt de query. Er zijn drie manieren om dit op te lossen, en welke de juiste is hangt af van de tabel, niet van je voorkeur.

Artikel uit het leertraject Webontwikkeling. Fout gereproduceerd en oplossingen gecontroleerd op Laravel 13.30.1 met MariaDB 11.8.9.

De fout herkennen

De formulering verschilt per database en per operatie, maar het gaat altijd over updated_at of created_at:

code
-- à l'insertion (MySQL / MariaDB)
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in 'INSERT INTO'

-- à la mise à jour
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'reports.updated_at' in 'SET'

-- sur SQLite
SQLSTATE[HY000]: General error: 1 table reports has no column named updated_at

Kijk eerst wat er werkelijk in de tabel staat:

bash
php artisan tinker --execute='echo implode(", ", Schema::getColumnListing("reports"));'
code
id, title

Ontbreken created_at en updated_at, ga dan verder met de volgende stap. Staan ze er wel, maar onder een andere naam, spring dan meteen naar de derde oplossing.

Oplossing 1: de kolommen toevoegen

De volledige werkwijze staat in de gids over migraties in Laravel.

Dit is in de meeste gevallen het juiste antwoord. Weten wanneer een rij is aangemaakt en gewijzigd komt vroeg of laat van pas, bij het debuggen net zo goed als bij het sorteren. De helper timestamps() maakt beide kolommen in één keer aan, nullable:

bash
php artisan make:migration add_timestamps_to_reports_table --table=reports
database/migrations/2026_09_02_000000_add_timestamps_to_reports_table.php
public function up(): void
{
    Schema::table('reports', function (Blueprint $table) {
        $table->timestamps();
    });
}

public function down(): void
{
    Schema::table('reports', function (Blueprint $table) {
        $table->dropTimestamps();
    });
}
bash
php artisan migrate

Na de migratie gaat de insert door en worden de datums gevuld. Gecontroleerd: de tabel bevat inderdaad id, title, created_at, updated_at en $report->created_at geeft een instantie van Illuminate\Support\Carbon terug, die je kunt formatteren en vergelijken.

Staat er al data in de tabel, dan komen de kolommen op NULL te staan voor de bestaande rijen, en dat is geen probleem. Wil je toch een waarde, zet die er dan expliciet in:

php
$table->timestamp('created_at')->nullable()->useCurrent();
$table->timestamp('updated_at')->nullable()->useCurrent()->useCurrentOnUpdate();

Oplossing 2: de timestamps op het model uitschakelen

Hoort de tabel die datums helemaal niet te dragen, denk aan een koppeltabel, een bevroren referentielijst of een schema dat een extern systeem oplegt, zeg dat dan tegen het model:

app/Models/Video.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Video extends Model
{
    public $timestamps = false;
}

Eloquent vult die twee kolommen daarna niet meer, en de insert werkt. Je bevestigt de stand met $video->usesTimestamps(), dat false teruggeeft.

Diezelfde uitschakeling kan ook eenmalig op één instantie, bijvoorbeeld om een waarde recht te zetten zonder updated_at aan te raken:

php
$task->timestamps = false;
$task->title = 'Titre corrigé';
$task->save();   // updated_at blijft ongewijzigd
Schakel ze niet uit om de fout het zwijgen op te leggen

Hoort de tabel die kolommen te hebben, dan lost $timestamps = false niets op: het haalt informatie weg waar je later naar op zoek gaat. Houd deze oplossing voor tabellen waar een wijzigingsdatum werkelijk geen betekenis heeft.

Oplossing 3: de kolommen bestaan onder een andere naam

In een gegroeide database heten de kolommen vaak date_creation, creation_date of modified_on. Hernoemen hoeft niet: geef Eloquent de echte namen door met twee constanten.

app/Models/Clip.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Clip extends Model
{
    const CREATED_AT = 'creation_date';
    const UPDATED_AT = 'updated_date';
}

Eloquent schrijft voortaan in die kolommen. Gecontroleerd op Laravel 13: na Clip::create(['title' => 'Extrait']) staat het tijdstip netjes in de kolom creation_date, en getUpdatedAtColumn() geeft updated_date terug.

Bestaat maar een van de twee datums, zet de andere dan op null:

php
const CREATED_AT = 'creation_date';
const UPDATED_AT = null;   // geen kolom voor de laatste wijziging

De accessors $clip->created_at en $clip->updated_at volgen deze constanten daarentegen niet: ze geven null terug. Lees de kolom onder haar echte naam, $clip->creation_date, of generiek met $clip->{$clip->getCreatedAtColumn()}.

Welke oplossing kies je

Situatie Oplossing
Gewone applicatietabel, kolommen simpelweg vergeten De kolommen toevoegen met een migratie
Pivottabel, bevroren referentielijst, opgelegd schema public $timestamps = false;
Gegroeide database met anders genoemde datumkolommen De constanten CREATED_AT en UPDATED_AT
Eén schrijfactie mag updated_at niet aanraken $model->timestamps = false; vóór save()

Veelgemaakte fouten

De timestamps uitschakelen om de fout het zwijgen op te leggen Op een gewone applicatietabel haalt $timestamps = false nuttige informatie weg in plaats van je schema te repareren. Voeg liever de kolommen toe.
Kolommen als NOT NULL op een tabel met data timestamps() maakt ze nullable, en dat gaat goed. Een definitie met NOT NULL zonder standaardwaarde laat de migratie stuklopen.
De kolommen van de oude database hernoemen Onnodig en riskant: de constanten CREATED_AT en UPDATED_AT wijzen prima naar de bestaande namen.
UPDATED_AT = null vergeten Heeft je tabel alleen een aanmaakkolom, dan roept UPDATED_AT op zijn standaardwaarde dezelfde fout weer op bij een update.

EloquentLaravelMigrationsPHP

Damien Flandrin Webdeveloper sinds 2010, maker van Gekkode en Email Impact. Elk artikel wordt vóór publicatie getest op een echt project. Contact
Nieuwsbrief

Nieuwe tests, tutorials en projecten, per e-mail.

Reproduceerbare tests, geversioneerde code, gedateerde resultaten. Nooit spam.