digislexia's avatar

How to set value of column equals to created_at?

I have model with default timestamps: created_at, updated_at. I want to add new column published_at, that must be equal to created_at after creation, but may change later. I assumed that useCurrent method must do the work, but unfortunately it uses default CURRENT_TIMESTAMP, and created_at, updated_at uses date from carbon instance, so they may differ for time between model saving in code and actual saving in database. I see that model checks usesTimestamps and then called updateTimestamps, but inside it only checks createdAt and updatedAt columns.

Do i have any option to guarantee that my published_at column equals created_at after model creation? Or i should call another save in observer saved method only to set published_at = created_at?

0 likes
10 replies
newbie360's avatar

@digislexia

in Observer may be do something like this ?

    public function created(Book $book)
    {
        $book->published_at = $book->created_at;
        $book->timestamps = false;
        $book->save();
    }
martinbean's avatar

@digislexia If models are published by default then you can just add a callback to your model to set the published_at column to the current date and time:

class Post extends Model
{
    protected static function booted()
    {
        static::creating(function (Model $model) {
            // Set model’s published_at value to be current date and time
            $model->published_at = $model->freshTimestamp();
        });
    }
}

If you need this logic in multiple models, then you could extract it to a Publishable trait if you wanted.

1 like
martinbean's avatar

@newbie360 And the problem is…? Do you really think there’s going to be more than a second’s different between calling that function to set the published_at column, and Laravel calling it to set the values of the created_at and updated_at columns?

And even if there was a second’s difference, again: so what? @digislexia’s application isn’t going to break. No one’s going to look at a model and go, “Oh, no! The created_at value is 2021-09-21 15:29:50, but the published_at value is 2021-09-21 15:29:51! This application is broken!”

newbie360's avatar

@martinbean yes, you are right, but for me i will move the code to created event, since it only fired once on model created =)

martinbean's avatar

@newbie360 And if you do, then you’re now executing two database queries for the sake of setting a single column value.

digislexia's avatar

@martinbean I have to show if the published_at value has changed in my interface. I want to do this by checking that created_at is equal to published_at. So this can definitely break the application logic.

digislexia's avatar

@martinbean freshTimestamp like useCurrent cannot guarantee a complete match. If the difference in a second wasn't a problem, I wouldn't be creating this thread.

Snapey's avatar

can't you set default value on the migration?

Snapey's avatar

don't forget, if you are only creating posts in one place, you can just add 'published_at' =>now()

no need for any hidden away model event functions

Please or to participate in this conversation.