Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

joao_uefrom's avatar

laravel is forcing the use of timestamps in the pivot table during seeding.

Hello, well, the title says it all. I’m seeding my database, which has the following relationship:

•	contextos - table
•	acoes - table
•	contexto_acao - pivot table

The issue occurs when I try to seed:

$adicionar = Acao::create([
    'nome'      => 'Adicionar',
    'slug'      => 'adicionar',
    'descricao' => '',
    'criado_em' => now()
]);

$contexto = Contexto::create([
    'nome'      => 'Períodos',
    'slug'      => 'periodo',
    'descricao' => '',
    'criado_em' => now(),
]);

$contexto->acoes()->attach($adicionar->id, ['criado_em' => now()]);

Laravel is trying to fill the updated_at column in the pivot table, but I don’t have timestamps in my pivot. In fact, my pivot is a class that extends Pivot, and I’ve defined public $timestamps = false;. In my Acao and Contexto classes, in the belongsToMany relationship, I haven’t used ->withTimestamps()

Let me know if you’d like any further adjustments!

Sorry for my english, it was Chatgpt :D

0 likes
31 replies
joao_uefrom's avatar

I forgot to mention, but I'm using Laravel 11 and PostgreSQL 16.

This is the error that appears: SQLSTATE[42703]: Undefined column: 7 ERROR: column "updated_at" of relation "contexto_acao" does not exist

aruszala's avatar

@joao_uefrom please share your migration files for the models in question. You probably have $table->timestamps(); in your migration files.

joao_uefrom's avatar

I didn't find it

aruszala's avatar

@joao_uefrom check your database tables to see if the updated_at and/or deleted_at columns exist. Alternatively run php artisan migrate:fresh - just keep in mind that this will erase and recreate your database tables and all data will be lost.

JussiMannisto's avatar

Have you created a model class for the pivot table? If you have, make sure its $timestamps property is set to false.

joao_uefrom's avatar

@JussiMannisto I did this but without success

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\Pivot;

class ContextoAcao extends Pivot
{
    public $timestamps = false;

    public function acao(): BelongsTo
    {
        return $this->belongsTo(Acao::class, 'acao_id');
    }

    public function contexto(): BelongsTo
    {
        return $this->belongsTo(Contexto::class, 'contexto_id');
    }
}
aruszala's avatar

@joao_uefrom also make sure to add public $timestamps = false; to your Contexto and Acao models as I don't see $table->timestamps(); in the migration files.

joao_uefrom's avatar

@aruszala yes, public $timestamps = false; is added to the Acao and Contexto models, but without success.

JussiMannisto's avatar

@joao_uefrom The attach() method has a 3rd parameter named $touches, which is true by default. Try passing false:

$contexto->acoes()->attach(
	id: $adicionar->id,
	attributes: ['criado_em' => now()],
	touch: false
);
joao_uefrom's avatar

@aruszala for example

class Contexto extends Model
{
    protected $table      = 'contextos';
    public    $timestamps = false;

    protected $fillable = [
        'nome',
        'contexto',
        'descricao',
        'criado_em'
    ];

    public function acoes(): BelongsToMany
    {
        return $this
            ->belongsToMany(Acao::class, 'contexto_acao', 'contexto_id', 'acao_id')
            ->withPivot('descricao')
            ->using(ContextoAcao::class);
    }
}
JussiMannisto's avatar

@joao_uefrom Btw, don't set $timestamps to false on Contexto and Acao. It won't help and the timestamps will stop working on those models.

aruszala's avatar

@JussiMannisto the updated_at and created_at columns do not exist in the database for these models. Take a look at the migration files that were posted.

aruszala's avatar

@joao_uefrom also change the line for criado_em in your migration files to thtis:

$table->timestamp('criado_em')->useCurrent();
joao_uefrom's avatar

@aruszala In fact, I already did this, I have a customized base model with this, I just applied some changes when sending it here to make it "easier" to understand:

use Illuminate\Database\Eloquent\Model as EloquentModel;

abstract class Model extends EloquentModel
{
    public const CREATED_AT = 'criado_em';
    public const UPDATED_AT = 'modificado_em';
}

the code snippet ['criado_em' => now()] is in the seed exactly because public $timestamps = false; in the models, it is like this because I am not interested in the updated_atcolumn, I am only interested in created_at.

But whenever I try to insert into the pivot table, laravel insists on the updated_at column (which for me is called modificado_em), even though the pivot table is not marked to have timestamps with ->withTimestamps() in belongsToMany.

joao_uefrom's avatar

@aruszala $table->timestamp('criado_em')->useCurrent(); that's interesting, I'll put it here, but I don't think it will have any effect on how laravel inserts

aruszala's avatar

@joao_uefrom that's the problem. The model you're extending sets the UPDATED_AT field.

Add this to the models that DO NOT have the modificado_em in the database table:

    public const UPDATED_AT = null;
aruszala's avatar

@joao_uefrom if you're models are using:

    public const CREATED_AT = 'criado_em';
    public const UPDATED_AT = 'modificado_em';

then you shouldn't use public $timestamps = false; as you're actually using timestamps. You're just renaming the column names that should be used for them.

Just remember that if the migration DOES NOT have the modificado_em column, then add:

    public const UPDATED_AT = null;

to the model also.

joao_uefrom's avatar

@aruszala in fact the pivot model (which would be where the problem was occurring) does not inherit my custom class, it inherits the laravel Pivot class itself

aruszala's avatar

@joao_uefrom then add this to the model:

    const CREATED_AT = 'criado_em';
    const UPDATED_AT = null;

and REMOVE public $timestamps = false; as you're actually using the timestamp for CREATED_AT field.

JussiMannisto's avatar

I just tried this on a fresh Laravel 11 install and I had no issues.

Do you have any observers on any of the models? Have you walked through the exception stack trace carefully to see where the error comes from?

joao_uefrom's avatar

@aruszala @jussimannisto wait, that worked, moving "criado_em" => now() from seeding to $table->timestamp('created_on')->useCurrent(); migration. But was that really supposed to be a problem?

joao_uefrom's avatar

a correction* $table->timestamp('criado_em')->useCurrent(); translator's fault

aruszala's avatar

@joao_uefrom if you're models are using:

    public const CREATED_AT = 'criado_em';
    public const UPDATED_AT = 'modificado_em';

then you shouldn't use public $timestamps = false; as you're actually using timestamps. You're just renaming the column names that should be used for them.

Just remember that if the migration DOES NOT have the modificado_em column, then add:

    public const UPDATED_AT = null;

to the model also.

joao_uefrom's avatar

@aruszala Indeed, defining const UPDATED_AT = null; in Contexto and Acao also solves the problem, but for me, it doesn’t make sense, because $timestamps was already set to false. Shouldn’t Laravel ignore this?

aruszala's avatar

@joao_uefrom these are the timestamps, you just renamed them:

    public const CREATED_AT = 'criado_em';
    public const UPDATED_AT = 'modificado_em';
joao_uefrom's avatar

@aruszala Yes, I am indeed using timestamps, but manually, only in these tables and without the updated_at column. I didn’t realize that Laravel was seeing the created_at column being added manually and then trying to add updated_at automatically. After all, the documentation says:

If you do not want these columns to be automatically managed by Eloquent, you should define a $timestamps property on your model with a value of false

that was exactly what I did.

I am very grateful for your help!

1 like

Please or to participate in this conversation.