I found this answer on the subject, but it doesn't work for me.
So, I make an entry in the database:
// Write lead to database
$lead = Lead::create($lead_data);
And the timestamps look like this, which is good:
| 2016-01-08 10:34:15 | 2016-01-08 10:34:15 |
But then I make a request to an external server, and I need to update the row:
$lead->user_id = $response['user_id'];
$lead->broker_id = $response['broker_id'];
$lead->save();
and the created_at field gets changed:
| 2016-01-08 04:34:17 | 2016-01-08 10:34:17 |
How do I solve this problem?
EDIT
I need a solution that would just modify the behavior without dropping columns or resetting migrations. The fix has to be performed on a live database without touching the data. As suggested below, I tried the following migration:
$table->datetime('created_at')->default(DB::raw('CURRENT_TIMESTAMP'))->change();
but nothing happens. The created_at field still gets modified on update.
Posting this as a top level answer, summarizing our comment discussion.
First, there is a date bug introduced in Laravel - as noted by @patricus. The suggested solutions in the bug discussion are to either use nullableTimestamps() instead of just timestamps(), or to create the created_at and updated_at fields directly -
$table->timestamp('updated_at')->change()
.This can also be fixed with raw SQL. An ALTER statement similar to this
That can be applied directly to your existing DB tables (Test it first, or course!). OR you can use DB::unprepared() to apply it from your migration - for example:
If you're on Laravel 5.2 and using MySQL, there was a bit of a "bug" introduced with the timestamps. You can read all about the issue on github here. It has to do with the timestamp defaults, and MySQL automatically assigning DEFAULT CURRENT_TIMESTAMP or ON UPDATE CURRENT_TIMESTAMP attributes under certain conditions.
Basically, you have three options.
If you set the
explicit_defaults_for_timestamp
variable toTRUE
, no timestamp column will be assigned the DEFAULT CURRENT_TIMESTAMP or ON UPDATE CURRENT_TIMESTAMP attributes automatically. You can read more about the variable here.Change
$table->timestamps()
to$table->nullableTimestamps()
. By default, the$table->timestamps()
command creates timestamp fields that are not nullable. By using$table->nullableTimestamps()
, your timestamp fields will be nullable, and MySQL will not automatically assign the first one the DEFAULT CURRENT_TIMESTAMP or ON UPDATE CURRENT_TIMESTAMP attributes.Instead of using
$table->timestamps
, use$table->timestamp('updated_at'); $table->timestamp('created_at');
yourself. Make sure your 'updated_at' field is the first timestamp in the table, so that it will be the one that is automatically assign the DEFAULT CURRENT_TIMESTAMP or ON UPDATE CURRENT_TIMESTAMP attributes.Skatch - I think your solution above is not quite right, but is probaby fine in this case.
The issue is that you are getting the PHP date, not the default MYSQL timestamp for your default. When you run that migration you end up with a statement like this:
Notice the string for your date. When you run your migration THAT date will always be used for your created_at, not the current date when a record is added days later.
Instead of doing "date('Y:m:d H:i:s')", you can do DB::raw('current_timestamp') to address this issue.
(sry, couldn't just add a comment above - my reputation is not high enough yet...)