如何使用Laravel迁移将时间戳列的默认值设置为当前时间戳?

问题描述 投票:121回答:8

我想使用Laravel Schema Builder / Migrations创建一个时间戳列,其默认值为CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP。我已多次浏览Laravel文档,但我看不出如何将其作为timestamp列的默认值。

timestamps()函数为它所做的两列提供默认值0000-00-00 00:00

php mysql laravel laravel-4 laravel-5
8个回答
242
投票

鉴于它是原始表达式,您应该使用DB::raw()CURRENT_TIMESTAMP设置为列的默认值:

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

这在每个数据库驱动程序上都可以正常运行。

新的捷径

从Laravel 5.1.25开始(参见PR 10962commit 15c487fe),您可以使用新的useCurrent()列修饰符方法将CURRENT_TIMESTAMP设置为列的默认值:

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

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

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

陷阱

  • MySQL的 从MySQL 5.7开始,0000-00-00 00:00:00不再被视为有效日期。如Laravel 5.2 upgrade guide中所述,当您将记录插入数据库时​​,所有时间戳列都应接收有效的默认值。您可以在迁移中使用useCurrent()列修饰符(来自Laravel 5.1.25及更高版本)将timestamp列默认为当前时间戳,或者可以使时间戳nullable()允许空值。
  • PostgreSQL和Laravel 4.x. 在Laravel 4.x版本中,PostgreSQL驱动程序使用默认数据库精度来存储时间戳值。在具有默认精度的列上使用CURRENT_TIMESTAMP函数时,PostgreSQL生成具有更高精度的时间戳,从而生成带有小数秒部分的时间戳 - see this SQL fiddle。 这将导致Carbon无法解析时间戳,因为它不会期望存储微秒。为了避免这种意外行为破坏你的应用程序,你必须明确给CURRENT_TIMESTAMP函数一个零精度,如下所示: $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP(0)')); 自Laravel 5.0以来,timestamp()列已更改为使用默认精度为零,这避免了这一点。 感谢@andrewhl在评论中指出了这个问题。

43
投票

要创建created_atupdated_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的多个列


31
投票

从2015年12月2日标记的Laravel 5.1.26开始,添加了useCurrent()修饰符:

Schema::table('users', function ($table) {
    $table->timestamp('created')->useCurrent();
});

PR 10962(其次是commit 15c487fe)领导了这一补充。

您可能还想阅读有趣的问题360211518

基本上,MySQL 5.7(使用默认配置)要求您为时间字段定义默认值或可为空。


7
投票

这对事实不起作用:

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

它不会删除选择时间戳时出现的“默认0”,它只会附加自定义默认值。但我们有点需要它没有引号。并非操作数据库的所有内容都来自Laravel4。这是他的观点。他希望在某些列上使用自定义默认值,例如:

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

我认为Laravel不可能。我一直在寻找一个小时,看看是否可能。


更新:Paulos Freita的answer表明它是可能的,但语法并不简单。


7
投票

请改用Paulo Freitas suggestion


在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");

它为我创造了奇迹。


2
投票

我在用户表created_at上使用这个laravel 5.X来在创建记录时自动设置时间戳。 (我们有一个客户端想直接在DB中输入用户,所以我必须确保设置时间戳)

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Carbon\Carbon;

class UpdatingUserTableTimeStampsForAccuracy extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dateTime('created_at')->change()->default(\Carbon\Carbon::now());
        });
    }

    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dateTime('created_at')->change();
        });
    }
}

如果您正在进行更改迁移,请使用该行。

如果你是Carbon的粉丝,这很棒!

或者,如果您在表创建迁移中进行设置。

 $table->dateTime('created_at')->default(\Carbon\Carbon::now());

0
投票

这就是你如何做到的,我已经检查了它,它适用于我的Laravel 4.2。

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

希望这可以帮助。


0
投票

在Laravel 5中简单地说:

$table->timestamps(); //Adds created_at and updated_at columns.

文档:http://laravel.com/docs/5.1/migrations#creating-columns


0
投票

使用以下内容:

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

希望它会对你有所帮助。谢谢。

© www.soinside.com 2019 - 2024. All rights reserved.