Laravel 更新时更改 created_at
Laravel changes created_at on update
我找到了关于这个主题的 ,但它对我不起作用。
所以,我在数据库中输入:
// Write lead to database
$lead = Lead::create($lead_data);
时间戳看起来像这样,这很好:
| 2016-01-08 10:34:15 | 2016-01-08 10:34:15 |
但后来我向外部服务器发出请求,我需要更新行:
$lead->user_id = $response['user_id'];
$lead->broker_id = $response['broker_id'];
$lead->save();
并且 created_at 字段被更改:
| 2016-01-08 04:34:17 | 2016-01-08 10:34:17 |
如何解决这个问题?
编辑
我需要一个只修改行为而不删除列或重置迁移的解决方案。必须在不触及数据的情况下对实时数据库执行修复。如下所示,我尝试了以下迁移:
$table->datetime('created_at')->default(DB::raw('CURRENT_TIMESTAMP'))->change();
但是没有任何反应。 created_at 字段在更新时仍会被修改。
如果您使用 Laravel 5.2 并使用 MySQL,则时间戳会引入一些 "bug"。您可以在 github here 上阅读有关该问题的所有信息。它与时间戳默认值有关,MySQL 在特定条件下自动分配 DEFAULT CURRENT_TIMESTAMP 或 ON UPDATE CURRENT_TIMESTAMP 属性。
基本上,您有三个选择。
- 更新MySQL变量:
如果将 explicit_defaults_for_timestamp
变量设置为 TRUE
,则不会自动为时间戳列分配 DEFAULT CURRENT_TIMESTAMP 或 ON UPDATE CURRENT_TIMESTAMP 属性。您可以阅读有关变量 here.
的更多信息
- 使用可为空的时间戳:
将 $table->timestamps()
更改为 $table->nullableTimestamps()
。默认情况下,$table->timestamps()
命令创建不可为空的时间戳字段。通过使用 $table->nullableTimestamps()
,您的时间戳字段可以为空,并且 MySQL 不会自动为第一个字段分配默认 CURRENT_TIMESTAMP 或更新 CURRENT_TIMESTAMP 属性。
- 自己定义时间戳:
不要使用 $table->timestamps
,而是自己使用 $table->timestamp('updated_at'); $table->timestamp('created_at');
。确保您的 'updated_at' 字段是 table 中的第一个时间戳,这样它将自动分配 DEFAULT CURRENT_TIMESTAMP 或 ON UPDATE CURRENT_TIMESTAMP 属性。
Skatch - 我认为您上面的解决方案不太正确,但在这种情况下可能没问题。
问题是您得到的是 PHP 日期,而不是默认的 MYSQL 时间戳。当您 运行 该迁移时,您最终会得到如下语句:
alter table alter column created_at default '2016:02:01 12:00:00';
注意日期字符串。当您 运行 您的迁移日期将始终用于您的 created_at,而不是几天后添加记录时的当前日期。
您可以 DB::raw('current_timestamp') 而不是 "date('Y:m:d H:i:s')" 来解决这个问题。
(对不起,不能只在上面添加评论 - 我的声誉还不够高...)
将此作为顶级答案发布,总结我们的评论讨论。
首先,在 Laravel 中引入了一个日期 bug - 正如@patricus 所指出的。错误讨论中建议的解决方案是使用 nullableTimestamps() 而不仅仅是 timestamps(),或者直接创建 created_at 和 updated_at 字段 - $table->timestamp('updated_at')->change()
。
这也可以用 raw SQL 解决。与此类似的 ALTER 语句
alter table loader_rawvalues MODIFY column updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
这可以直接应用于您现有的数据库表(首先测试它,或者当然!)。或者您可以使用 DB::unprepared() 从迁移中应用它 - 例如:
class CreateMyTable extends Migration
{
public function up()
{
Schema::create('mytable', function (Blueprint $table) {
$table->bigIncrements('id');
// ...
$table->timestamps();
});
DB::unprepared('alter table mytable MODIFY column updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP');
}
}
这一定是您的 table 字段定义的问题。我最近遇到了同样的问题,当我检查我的 table 时,created_at
有一个值为 on update CURRENT_TIMESTAMP
的“EXTRA
”,以使 Laravel 正常运行只需使用以下内容更新字段定义:
ALTER TABLE table_name CHANGE created_at created_at timestamp NOT NULL default CURRENT_TIMESTAMP;
我找到了关于这个主题的
所以,我在数据库中输入:
// Write lead to database
$lead = Lead::create($lead_data);
时间戳看起来像这样,这很好:
| 2016-01-08 10:34:15 | 2016-01-08 10:34:15 |
但后来我向外部服务器发出请求,我需要更新行:
$lead->user_id = $response['user_id'];
$lead->broker_id = $response['broker_id'];
$lead->save();
并且 created_at 字段被更改:
| 2016-01-08 04:34:17 | 2016-01-08 10:34:17 |
如何解决这个问题?
编辑
我需要一个只修改行为而不删除列或重置迁移的解决方案。必须在不触及数据的情况下对实时数据库执行修复。如下所示,我尝试了以下迁移:
$table->datetime('created_at')->default(DB::raw('CURRENT_TIMESTAMP'))->change();
但是没有任何反应。 created_at 字段在更新时仍会被修改。
如果您使用 Laravel 5.2 并使用 MySQL,则时间戳会引入一些 "bug"。您可以在 github here 上阅读有关该问题的所有信息。它与时间戳默认值有关,MySQL 在特定条件下自动分配 DEFAULT CURRENT_TIMESTAMP 或 ON UPDATE CURRENT_TIMESTAMP 属性。
基本上,您有三个选择。
- 更新MySQL变量:
如果将 explicit_defaults_for_timestamp
变量设置为 TRUE
,则不会自动为时间戳列分配 DEFAULT CURRENT_TIMESTAMP 或 ON UPDATE CURRENT_TIMESTAMP 属性。您可以阅读有关变量 here.
- 使用可为空的时间戳:
将 $table->timestamps()
更改为 $table->nullableTimestamps()
。默认情况下,$table->timestamps()
命令创建不可为空的时间戳字段。通过使用 $table->nullableTimestamps()
,您的时间戳字段可以为空,并且 MySQL 不会自动为第一个字段分配默认 CURRENT_TIMESTAMP 或更新 CURRENT_TIMESTAMP 属性。
- 自己定义时间戳:
不要使用 $table->timestamps
,而是自己使用 $table->timestamp('updated_at'); $table->timestamp('created_at');
。确保您的 'updated_at' 字段是 table 中的第一个时间戳,这样它将自动分配 DEFAULT CURRENT_TIMESTAMP 或 ON UPDATE CURRENT_TIMESTAMP 属性。
Skatch - 我认为您上面的解决方案不太正确,但在这种情况下可能没问题。
问题是您得到的是 PHP 日期,而不是默认的 MYSQL 时间戳。当您 运行 该迁移时,您最终会得到如下语句:
alter table alter column created_at default '2016:02:01 12:00:00';
注意日期字符串。当您 运行 您的迁移日期将始终用于您的 created_at,而不是几天后添加记录时的当前日期。
您可以 DB::raw('current_timestamp') 而不是 "date('Y:m:d H:i:s')" 来解决这个问题。
(对不起,不能只在上面添加评论 - 我的声誉还不够高...)
将此作为顶级答案发布,总结我们的评论讨论。
首先,在 Laravel 中引入了一个日期 bug - 正如@patricus 所指出的。错误讨论中建议的解决方案是使用 nullableTimestamps() 而不仅仅是 timestamps(),或者直接创建 created_at 和 updated_at 字段 - $table->timestamp('updated_at')->change()
。
这也可以用 raw SQL 解决。与此类似的 ALTER 语句
alter table loader_rawvalues MODIFY column updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
这可以直接应用于您现有的数据库表(首先测试它,或者当然!)。或者您可以使用 DB::unprepared() 从迁移中应用它 - 例如:
class CreateMyTable extends Migration
{
public function up()
{
Schema::create('mytable', function (Blueprint $table) {
$table->bigIncrements('id');
// ...
$table->timestamps();
});
DB::unprepared('alter table mytable MODIFY column updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP');
}
}
这一定是您的 table 字段定义的问题。我最近遇到了同样的问题,当我检查我的 table 时,created_at
有一个值为 on update CURRENT_TIMESTAMP
的“EXTRA
”,以使 Laravel 正常运行只需使用以下内容更新字段定义:
ALTER TABLE table_name CHANGE created_at created_at timestamp NOT NULL default CURRENT_TIMESTAMP;