framework icon indicating copy to clipboard operation
framework copied to clipboard

Pivot model UPDATED_AT = null; ignored when using attach()

Open mustafayusufozcan opened this issue 7 months ago • 5 comments

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 ...

mustafayusufozcan avatar Sep 03 '25 01:09 mustafayusufozcan


    /**
     * 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.

macropay-solutions avatar Sep 03 '25 07:09 macropay-solutions

@mustafayusufozcan Have you tried

public function users(): BelongsToMany
{
 return $this->belongsToMany(User::class)
    ->using(AnnouncementUser::class)
    ->withTimestamps();
}

ghabriel25 avatar Sep 05 '25 15:09 ghabriel25

@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 avatar Sep 05 '25 16:09 mustafayusufozcan

@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()]);

ghabriel25 avatar Sep 05 '25 18:09 ghabriel25


        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());
}

macropay-solutions avatar Sep 05 '25 18:09 macropay-solutions