Override created_at value
Asked Answered
A

4

7

I'm trying to insert date into created at but nothing worked

I tried to use create as normal

$this->create([ 'product_id' => "$id", 'shop_name' => $shop,'created_at' => $date ]);

I tried to change the date format to match laravel

$date = date('Y-m-d H:i:s',strtotime($id['created_at']));

I also tried to user mutators to change the value each time

public function setFirstNameAttribute($value)
{
    $this->attributes['created_at'] = $value;
}

How can I set a specific date in created_at rather than the default date?

Alerion answered 6/2, 2018 at 20:24 Comment(7)
Well, your attribute in the mutator is created not created_at, but setting the value of created_at when creating should work. Are you getting an error?Reverso
@Devon I changed to created_at, anyway it didn't solve it, the value is not being overridden and the stored date is '2018-02-06' for all records. I really don't know why!Alerion
First you need to take a step back and think if changing the created_at date is reasonable. Normally you'd never need to change that date.Eustazio
@Eustazio I'm using API and I must change it to match the other database otherwise I won't attempt to change itAlerion
In that case you should have defined your table with date fields like API_created_date and API_updated_date to indicate what they actually hold. More intuitive and no problems updating. If you're not too deep in the project now I suggest you change thatEustazio
If there's no way to override it I will follow your suggestion. I never through it will be so hard like this.Alerion
@JoumanaIssa are these values fillable in your model? What is the value of the $guarded or $fillable properties?Reverso
B
17

Do you have fillable or guarded arrays set for your model?

If so, the create method will skip the fields that are not mass assignable.

If you want to fill in your own, you can do something like this:

$product = app(Product::class);
$product->timestamps = false; // disable timestamps for this creation

// set what you want to set
$product->product_id = $id;
$product->shop_name = $shop;
$product->created_at = $datetime; // <- datetime here
$product->save();

Although, if you look at the code (vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasTimestamps.php), and the created_at field is fillable, it should not set another value if it was set during creation. (See the isDirty check there)


If you never wish to use the created_at and updated_at the normal way, just set timestamps to false in your model:

public $timestamps = false;
Blintz answered 6/2, 2018 at 22:17 Comment(1)
I've used Laravel v5.5. I don't have to use $product->timestamps = false;. Moreover, I've just used this: $product->setCreatedAt($datetime);Ellora
S
0

I think you must set your timestamp in your Model to false

timestamps = false;
Santamaria answered 7/2, 2018 at 1:48 Comment(0)
L
0

This is quite an old question, but I thought I'd add that you can also use the Model::unguard() method to temporarily disable mass assignment on the model, which will also let you set custom values for created_at on the fly, as well as anything else protected by MA. Note that it also cascades to child relationships, as per below:

    $user = Auth::user();

    User::unguard();

    $user->drill_completions()->create([
        'day' => null,
        'sequence_completed_at' => Carbon::now(),
        'created_at' => Carbon::now()->subHours(32) // unguard has been set on the parent model, but here we are using it to enable setting created_at on the child relationship
    ]);

    User::reguard();

As above, you can reset again using Model::reguard();.

Lumumba answered 5/2, 2022 at 20:1 Comment(0)
L
0

In cases like this, it's helpful to step through the Laravel framework code itself.

If you look at Builder::create(), you can see it's just a convenience method for creating a new model instance and then saving it.

This ends up calling Model::performInsert(), which calls the HasTimestamps trait's updateTimestamps() method before performing the insert.

In HasTimestamps::updateTimestamps() you'll see that it only sets created_at if the attribute is not "dirty". It will be dirty because you've set it explicitly (See HasAttributes::isDirty()).

So long story short, the behavior should be that if you specify created_at specifically, your value overrides the default value. If it's not, it's likely because you have the model's $guarded or $fillable property set in a way that excludes the timestamps.

Laevorotatory answered 5/10, 2023 at 16:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.