我想使用Laravel Schema Builder/Migrations创建一个默认值为CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP的时间戳列。我已经多次阅读Laravel文档,我不知道如何将其作为时间戳列的默认值。

timestamps()函数将它所生成的两列的默认值设置为0000-00-00 00:00。


当前回答

作为未来谷歌人的额外可能性

我发现,当记录被创建但从未被修改时,在updated_at列中设置null更有用。它减少了数据库大小(好吧,只是一点点),它可以在第一眼看到数据从未被修改过。

我使用的是:

$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->default(DB::raw('NULL ON UPDATE CURRENT_TIMESTAMP'))->nullable();

(在Laravel 7+8与mysql 8)。


编辑:因为Laravel 8你还可以使用:

$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->nullable()->useCurrentOnUpdate();

达到同样的效果。

感谢@bilogic指出这一点。

其他回答

唯一对我有用的是

DB::statement("ALTER TABLE orders CHANGE updated_at updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");

这就是你怎么做的,我已经检查过了,它在我的Laravel 4.2上工作。

$table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));

希望这能有所帮助。

假设它是一个原始表达式,你应该使用DB::raw()将CURRENT_TIMESTAMP设置为列的默认值:

$table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));

这在每个数据库驱动程序上都可以完美地工作。

从Laravel 5.1.25(参见PR 10962和提交15c487fe)开始,你现在可以使用新的useCurrent()列修改器方法来实现列的默认值:

$table->timestamp('created_at')->useCurrent();

回到问题,在MySQL上,你也可以通过DB::raw()使用on UPDATE子句:

$table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));

同样,在Laravel 8.36.0(参见PR 36817)中,你现在可以使用新的useCurrentOnUpdate()列修饰符方法和useCurrent()修饰符来为列实现相同的默认值:

$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();

陷阱

MySQL Starting with MySQL 5.7, 0000-00-00 00:00:00 is no longer considered a valid date. As documented at the Laravel 5.2 upgrade guide, all timestamp columns should receive a valid default value when you insert records into your database. You may use the useCurrent() column modifier (from Laravel 5.1.25 and above) in your migrations to default the timestamp columns to the current timestamps, or you may make the timestamps nullable() to allow null values. PostgreSQL & Laravel 4.x In Laravel 4.x versions, the PostgreSQL driver was using the default database precision to store timestamp values. When using the CURRENT_TIMESTAMP function on a column with a default precision, PostgreSQL generates a timestamp with the higher precision available, thus generating a timestamp with a fractional second part - see this SQL fiddle. This will led Carbon to fail parsing a timestamp since it won't be expecting microseconds being stored. To avoid this unexpected behavior breaking your application you have to explicitly give a zero precision to the CURRENT_TIMESTAMP function as below: $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP(0)')); Since Laravel 5.0, timestamp() columns has been changed to use a default precision of zero which avoids this.

感谢@andrewhl指出Laravel 4。X问题在评论中。

感谢@ChanakaKarunarathne在评论中提出了新的useCurrentOnUpdate()快捷方式。

但事实并非如此:

$table->timestamp('created_at')->default('CURRENT_TIMESTAMP');

它不会删除选择时间戳时似乎附带的'default 0',只是附加了自定义的默认值。但我们不需要引号。并不是所有操作DB的东西都来自Laravel4。这就是他的观点。他想在某些列上自定义默认值,比如:

$table->timestamps()->default('CURRENT_TIMESTAMP');

我觉得拉威尔不可能。我已经找了一个小时了,看看有没有可能。


更新:保罗·弗雷塔的回答表明这是可能的,但语法并不简单。

创建created_at和updated_at列:

$t->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
$t->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'));

你需要MySQL版本>= 5.6.5有多个列的CURRENT_TIMESTAMP