How to only use created_at in Laravel
PhpLaravelPhp Problem Overview
I want only use created_at , how to do it?
I know:
This can custom timestamps name
const CREATED_AT = 'created';
const UPDATED_AT = 'updated';
This can disable timestamps
public $timestamps = false;
Php Solutions
Solution 1 - Php
Eloquent does not provide such functionality out of the box, but you can create it on your own using the creating
event callback:
class User extends Eloquent {
public $timestamps = false;
public static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->created_at = $model->freshTimestamp();
});
}
}
Solution 2 - Php
Use on the top:
const UPDATED_AT = null;
And for 'created_at' field, you can use:
const CREATED_AT = null;
UPDATE FOR LARAVEL 5.5.0 - 5.5.5
This was broken in Laravel 5.5.0 (and fixed again in 5.5.5).
If you are using 5.5.x, make sure you are on the newest version.
If for some reason you cannot be on the newest version, here is a workaround.
Set the public $timestamps to false:
public $timestamps = false;
And when necessary:
public function setCreatedAtAttribute($value) {
$this->attributes['created_at'] = \Carbon\Carbon::now();
}
OR
public function setUpdatedAtAttribute($value) {
$this->attributes['updated_at'] = \Carbon\Carbon::now();
}
When the two fields "created_at" and "updated_at" are required, you do not have to do anything, of course ;)
Solution 3 - Php
I have a better answer from here for Laravel 5.2 or above.
U can use this in model-
class User extends Model
{
public $timestamps = false; // disable all behavior
public $timestamps = true; // enable all behavior
public $timestamps = [ "created_at" ]; // enable only to created_at
public $timestamps = [ "updated_at" ]; // enable only to updated_at
public $timestamps = [ "created_at", "updated_at" ]; // same as true, enable all behavior
}
So, for your question, the answer is -
public $timestamps = [ "created_at" ]; // enable only to created_at
Re-
public $timestamps = [ "created_at" ];
Not working in Laravel 6+
Solution 4 - Php
My solution:
class CreatePostsTable extends Migration {
public function up() {
Schema::create('posts', function(Blueprint $table){
$table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
});
}
This works for me
Solution 5 - Php
Since Laravel 5.*
Model:
// Disable updated_at (only created_at)
class Book extends Model
{
const UPDATED_AT = null;
/* ... */
}
Migration:
Schema::create('books', function (Blueprint $table): void {
/* ... */
$table->timestampTz('created_at')->nullable();
});
Solution 6 - Php
I solved by adding default value CURRENT_TIMESTAMP
in my database for the column created_at
. And In my model I use this below code
public $timestamps = false;
protected $dates = ['created_at'];
I hope this method works in all versions of laravel.
Solution 7 - Php
To disable only updated_at, you can override Model::setUpdatedAt() method, like following :
public function setUpdatedAt($value) {
// Do nothing.
}
Of course, if you wanted to do this for the created_at column, it's just as easy. And that's work for Laravel 5.1
Solution 8 - Php
On your model
set
const UPDATED_AT = null;
or
const CREATED_AT = null;
it stops Laravel trying to update the updated_at/created_at field
It works for Laravel 5.8
And it is better than overwrite: setUpdatedAt
in your model
public function setUpdatedAt($value) : self
{
// Do nothing.
return $this;
}
because it is shorter and because the check for if (! is_null(static::UPDATED_AT)
is happening in source code earlier than triggering
setUpdatedAt
Solution 9 - Php
In version 5.3 I just did public $timestamps = false;
and then added protected $fillable = ['created_at']. Note: You can add anything you want, just make sure it matches the one in your table.`
Solution 10 - Php
My solution for this is using a new __construct
method.
See:
class MyModel extends Eloquent {
public $timestamps = false;
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
$this->attributes['created_at'] = $this->freshTimestamp();
}
}
Solution 11 - Php
Approach with only setUpdatedAt
did not work with Laravel 5.1.7 because it has one more place where updated_at
gets processed.
Model class performUpdate method calls Builder class method:
public function update(array $values)
{
return $this->query->update($this->addUpdatedAtColumn($values));
}
which leads us to
return Arr::add($values, $column, $this->model->freshTimestampString());
I'm not sure, why Laravel is processing updated_at twice - in performUpdate
with $this->updateTimestamps()
and then later in Builder with $this->addUpdatedAtColumn($values)
.
With some debugging, I found that you have to also update your model with getUpdatedAtColumn override. At first I was afraid that it will try to update a non-existent field "null", but it turned out that Arr::add
is smart enough to ignore null keys.
So, in your model class add these:
public function setUpdatedAt($value)
{
// Do nothing.
}
public function getUpdatedAtColumn()
{
return null;
}
This should be enough to disable both updates.
Solution 12 - Php
Use on the top the class:
const UPDATED_AT = null;
or
const CREATED_AT = null;
Solution 13 - Php
A solution that is simple, decoupled, and reusable is to use a Model Observer. The idea is to capture the creating
event and fill the created_at
attribute. This method may be used by any number of models without having to repeat code or using unofficial tricks. Most importantly, it closely resembles the internal mechanics of the Model class, thus avoiding unexpected errors.
-
Create
SetCreatedAt
observer inApp\Observers
:namespace App\Observers;
use Illuminate\Database\Eloquent\Model;
class SetCreatedAt { /** * Sets created_at when creating the model. * * @param Model $model * @return void */ public function creating(Model $model) { $model->setCreatedAt($model->freshTimestamp()); } }
-
On
App\Providers\AppServiceProvider
inside theboot
method add the following line for each of the models that you want thecreated_at
to be generated for:/**
- Bootstrap any application services.
- @return void */ public function boot() { // Replace OrderLog with your model OrderLog::observe(SetCreatedAt::class); }
-
On your models, the only thing that you have to do is disable the timestamps:
// Disable timestamps on the model public $timestamps = false;
Tested with Laravel 5.3, but it should work with previous versions as well.
Good luck!
Solution 14 - Php
In 5.4, the problem it gives is that it also doesn't populate updated_at field even after update (Eloquent update).
instead add this method
public function setUpdatedAtAttribute($value)
{
// auto disable update_at in inserts
}
Solution 15 - Php
In Laravel 5.7, this was enough for me to have it work:
In migration:
$table->timestamp('created_at')->nullable();
instead of classic $table->timestamp('created_at');
In model:
const UPDATED_AT = null;
Solution 16 - Php
For anyone here looking for having updated_at
and not created_at
, but none of the other answers seems to work for you:
In Laravel 8, you need to set the model property CREATED_AT
to null
and the UPDATED_AT
to 'updated_at' or any other name you want to your updated_at field.
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The name of the "created at" column.
*
* @var string|null
*/
const CREATED_AT = null;
/**
* The name of the "updated at" column.
*
* @var string|null
*/
const UPDATED_AT = 'updated_at';
public function setCreatedAt($value)
{
// do nothing
}
}
And your migration...
Schema::create('users', function (Blueprint $table) {
// ...
$table->timestamp('updated_at'); // instead of $table->timestamps();
});
I am not sure why you need to set this property inside your model since it is already set in the parent class Illuminate\Database\Eloquent\Model
, but it only worked for me after I made this change.
Solution 17 - Php
You can use CURRENT_TIMESTAMP default value for created
field in your MySQL table and set
public $timestamps = false;
in your model.
Solution 18 - Php
I used very simple hack ;)
class MyClass extends Model {
const CREATED_AT = 'creation_date';
const UPDATED_AT = 'creation_date';
}
I just pointed both to the same column :)