Eloquent model timestamp updated without changes

Gustavo Oliveira
2 min readJun 18, 2024

--

When performing an update, Laravel's Eloquent ORM only touches the timestamp (updated_at) when something was modified. However, depending on your database, the values can be stored with a different value.

Case in Point

MySQL and SQLite store boolean as integer values 1 and 0. As a result, updating a boolean 1 with true will touch the timestamp, which can be confusing.

Solution

To avoid this, you can use attribute casting to cast the column to boolean in the model class.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class ChecklistItem extends Model
{
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return ['checked' => 'boolean'];
}
}

This way, Eloquent will check for changes after casting. Here is a simplified version of how Eloquent checks if changes occured (full version here):

    /**
* Determine if the new and old values for a given key are equivalent.
*
* @param string $key
* @return bool
*/
public function originalIsEquivalent($key)
{
if (! array_key_exists($key, $this->original)) {
return false;
}

$attribute = Arr::get($this->attributes, $key);
$original = Arr::get($this->original, $key);

if ($attribute === $original) {
return true;
}

...

elseif ($this->hasCast($key, static::$primitiveCastTypes)) {
return $this->castAttribute($key, $attribute) ===
$this->castAttribute($key, $original);
}

...
}

--

--

Gustavo Oliveira
Gustavo Oliveira

No responses yet