Pivot model UPDATED_AT = null; ignored when using attach()
Laravel Version
12.0
PHP Version
8.4.11
Database Driver & Version
No response
Description
When using a custom pivot model, defining const UPDATED_AT = null; inside the pivot model is ignored. Instead, Laravel seems to respect the parent (main) model’s timestamp settings.
Models
-
Announcement -
User -
AnnouncementUser(custom pivot model)
Code Example
$announcement->users()->attach($userIds);
Expected Behavior
Since the pivot model AnnouncementUser has:
class AnnouncementUser extends Pivot
{
const UPDATED_AT = null;
}
I expect the updated_at column to be ignored during attach().
Actual Behavior
Laravel still tries to insert/update the updated_at column, resulting in:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in ...
Workaround
If I move
const UPDATED_AT = null;
to the Announcement model, the error disappears.
This suggests that the parent model overrides the pivot model’s UPDATED_AT configuration.
Steps To Reproduce
Create three models: Announcement, User, and a custom pivot model AnnouncementUser extending Illuminate\Database\Eloquent\Relations\Pivot.
In the AnnouncementUser model, set:
class AnnouncementUser extends Pivot
{
const UPDATED_AT = null;
}
Define the many-to-many relationship in the Announcement model:
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class)
->using(AnnouncementUser::class);
}
Run the following code:
$announcement->users()->attach($userIds);
Observe the error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in ...
/**
* Get the name of the "updated at" column.
*
* @return string
*/
public function updatedAt()
{
return $this->pivotUpdatedAt ?: $this->parent->getUpdatedAtColumn();
}
protected function formatAttachRecords($ids, array $attributes)
{
$records = [];
$hasTimestamps = ($this->hasPivotColumn($this->createdAt()) ||
$this->hasPivotColumn($this->updatedAt()));
public function hasPivotColumn($column)
{
return in_array($column, $this->pivotColumns);
}
public function withPivot($columns)
{
$this->pivotColumns = array_merge(
$this->pivotColumns,
is_array($columns) ? $columns : func_get_args()
);
return $this;
}
Maybe you can hack it somehow after you see this logic.
@mustafayusufozcan Have you tried
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class)
->using(AnnouncementUser::class)
->withTimestamps();
}
@mustafayusufozcan Have you tried
public function users(): BelongsToMany { return $this->belongsToMany(User::class) ->using(AnnouncementUser::class) ->withTimestamps(); }
Yes, I tried that. If both created_at and updated_at exist in the table, it works fine. But if you only want to use one of them, even when defining const UPDATED_AT = null;, it still throws an error.
@mustafayusufozcan did you know that
const UPDATED_AT
is for updated_at column name? not for determine it should be updated or not during attaching.
https://github.com/laravel/framework/blob/12.x/src%2FIlluminate%2FDatabase%2FEloquent%2FModel.php#L290
If you dont want updated_at to be updated or used during attaching, then you should define
public $timestamps = false;
and manually include created_at when attaching
->attach($id, ['created_at' => now()]);
return $this->pivotUpdatedAt ?: $this->parent->getUpdatedAtColumn();
this makes the updated at from pivot columns to be replaced by the parent's updated at.
Solution would be to manually attach and avoid the attach method.
UPDATE We use it with getColumns like this:
->withPivot((new ExamplePivot())->getColumns())
And we did not had this issue. @mustafayusufozcan can you try it like this?
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class)
->using(AnnouncementUser::class)->withPivot((new AnnouncementUser())->getFillable());
}