我想使用Laravel Schema Builder/Migrations创建一个默认值为CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP的时间戳列。我已经多次阅读Laravel文档,我不知道如何将其作为时间戳列的默认值。
timestamps()函数将它所生成的两列的默认值设置为0000-00-00 00:00。
我想使用Laravel Schema Builder/Migrations创建一个默认值为CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP的时间戳列。我已经多次阅读Laravel文档,我不知道如何将其作为时间戳列的默认值。
timestamps()函数将它所生成的两列的默认值设置为0000-00-00 00:00。
当前回答
创建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
其他回答
创建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
作为未来谷歌人的额外可能性
我发现,当记录被创建但从未被修改时,在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::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()快捷方式。
使用保罗·弗雷塔斯的建议。
在Laravel修复此问题之前,您可以在Schema::create运行之后运行标准数据库查询。
Schema::create("users", function($table){
$table->increments('id');
$table->string('email', 255);
$table->string('given_name', 100);
$table->string('family_name', 100);
$table->timestamp('joined');
$table->enum('gender', ['male', 'female', 'unisex'])->default('unisex');
$table->string('timezone', 30)->default('UTC');
$table->text('about');
});
DB::statement("ALTER TABLE ".DB::getTablePrefix()."users CHANGE joined joined TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL");
它对我产生了奇效。
唯一对我有用的是
DB::statement("ALTER TABLE orders CHANGE updated_at updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");