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

Joe*_*473 140 php mysql laravel laravel-4 laravel-5

我想创建一个时间戳列,其默认值为CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP使用Laravel架构生成器/迁移.我已多次浏览Laravel文档,但我看不出如何将其作为timestamp列的默认值.

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

Pau*_*tas 266

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

$table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
Run Code Online (Sandbox Code Playgroud)

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

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

$table->timestamp('created_at')->useCurrent();
Run Code Online (Sandbox Code Playgroud)

如上所述,在MySQL上你也可以ON UPDATE通过DB::raw()以下方式使用该子句:

$table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
Run Code Online (Sandbox Code Playgroud)

陷阱

  • MySQL

    从MySQL 5.7开始,0000-00-00 00:00:00不再被视为有效日期.如Laravel 5.2升级指南中所述,当您将记录插入数据库时​​,所有时间戳列都应收到有效的默认值.您可以useCurrent()在迁移中使用列修饰符(来自Laravel 5.1.25及更高版本)将timestamp列默认为当前时间戳,或者可以使时间戳nullable()允许空值.

  • PostgreSQL和Laravel 4.x

    在Laravel 4.x版本中,PostgreSQL驱动程序使用默认数据库精度来存储时间戳值.在CURRENT_TIMESTAMP具有默认精度的列上使用该函数时,PostgreSQL会生成一个具有更高精度的时间戳,从而生成带有小数秒部分的时间戳 - 请参阅此SQL小提琴.

    这将导致Carbon无法解析时间戳,因为它不会期望存储微秒.为了避免这种意外行为破坏您的应用程序,您必须显式为该CURRENT_TIMESTAMP函数提供零精度,如下所示:

    $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP(0)'));
    
    Run Code Online (Sandbox Code Playgroud)

    从Laravel 5.0开始,timestamp()列已更改为使用默认精度零,这样可以避免这种情况.

    感谢@andrewhl在评论中指出了这个问题.

  • 并非完美无缺。对于 PostgreSQL 'CURRENT_TIMESTAMP' 返回以下格式的内容:2014-08-11 15:06:29.692439。这会导致 Carbon::createFromFormat('Ymd H:i:s', $timestamp) 方法失败(它无法解析尾随的毫秒数)。这在 Laravel 访问时间戳时使用。要修复 PostgreSQL,请使用:DB::raw('now()::timestamp(0)')(参考:http://www.postgresql.org/docs/8.1/static/functions-datetime.html#FUNCTIONS -日期时间-当前) (2认同)
  • @ JoeyD473 - 你应该接受这个作为答案. (2认同)

Bri*_*ams 48

要创建两个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'));
Run Code Online (Sandbox Code Playgroud)

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

  • 为什么不直接使用`$ table-> timestamps() - > default(DB :: raw('CURRENT_TIMESTAMP'));`? (3认同)

Gra*_*ble 33

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

Schema::table('users', function ($table) {
    $table->timestamp('created')->useCurrent();
});
Run Code Online (Sandbox Code Playgroud)

PR 10962(后面是提交15c487fe)导致了这一添加.

您可能还想阅读感兴趣的问题360211518.

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


ndb*_*erg 22

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

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

至此,我使用:

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

(在带有 mysql 8 的 Laravel 7 中)。


use*_*086 9

在 laravel 7 中,要设置当前时间,请使用以下命令:

$table->timestamp('column_name')->useCurrent();
Run Code Online (Sandbox Code Playgroud)


Gle*_*las 8

这对事实不起作用:

$table->timestamp('created_at')->default('CURRENT_TIMESTAMP');
Run Code Online (Sandbox Code Playgroud)

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

$table->timestamps()->default('CURRENT_TIMESTAMP');
Run Code Online (Sandbox Code Playgroud)

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


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

  • 这是可能的,请参阅Paulo Freitas在此主题中的回答. (5认同)

Mar*_*lln 8

请改用Paulo Freitas的建议.


在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");
Run Code Online (Sandbox Code Playgroud)

它为我创造了奇迹.


Sam*_*ira 5

如果您想为 dateTime 列设置当前日期时间(就像我在谷歌搜索时那样),请使用这种方式

$table->dateTime('signed_when')->useCurrent();
Run Code Online (Sandbox Code Playgroud)