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


166

我想创建一个CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP使用Laravel Schema Builder / Migrations 作为默认值的时间戳列。我已经多次浏览过Laravel文档,但没有看到如何将它设置为timestamp列的默认值。

timestamps()函数0000-00-00 00:00为其创建的两个列都设置默认值。

Answers:


310

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

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

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

新捷径

从Laravel 5.1.25开始(请参阅PR 10962提交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升级指南中所述,在将记录插入数据库时​​,所有时间戳列均应收到有效的默认值。您可以useCurrent()在迁移中使用column修饰符(来自Laravel 5.1.25及更高版本)将timestamp列默认为当前时间戳,或者可以使timestamps 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)'));

    从Laravel 5.0开始,将timestamp()列更改为使用默认精度零,从而避免了这种情况。

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


更好的建议然后是我的。用这个代替我的DB::statement例子,这要简单得多。
Marwelln 2014年

您的测试中也可以将其用于PARTITION BY语句吗?
Glenn Plas 2014年

2
并非完美无缺。对于PostgreSQL,“ CURRENT_TIMESTAMP”返回以下格式的内容:2014-08-11 15:06:29.692439。这将导致Carbon :: createFromFormat('Ymd H:i:s',$ timestamp)方法失败(无法解析尾随的毫秒)。Laravel在访问时间戳时使用它。要修复PostgreSQL,请使用:DB :: raw('now():: timestamp(0)')(参考:postgresql.org/docs/8.1/static/…
andrewhl

@andrewhl实际上,我只针对MySQL回答,因为这是问题所在。但是,感谢您与我们分享这个问题,我将更新答案以解决这一问题!:)
Paulo Freitas 2014年

55

要同时创建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


3
为什么不只是使用$table->timestamps()->default(DB::raw('CURRENT_TIMESTAMP'));
戴夫

1
@dave,因为updated_at在最初创建记录后对其进行修改时,该记录不会更改
Erik Berkun-Drevnig 2015年

是的,再加上timestamps()仍然不允许默认值,所以根本不起作用。我已经提交了代码以允许它使用,但是Laravel管理人员实际上并不希望人们使用我们使用它的默认方式(假设因为5.6.5之前的MySQL版本不允许多个带有时间戳的列作为默认值)。
戴夫

实际上,updated_at由Eloquent管理,因此根本不需要“更新时”位,因为它将在模型自动更新时设置。
dmyers '16

@dmyers如果您使用的是雄辩的话,那么您可以做,$t->timestamps();但是不能回答问题。
布赖恩·亚当斯

44

从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(具有默认配置)要求您为时间字段定义默认值或可为空。


10

这对于事实不起作用:

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

它不会删除选择时间戳似乎附带的“默认0”,而只是附加自定义默认值。但是我们有点需要没有引号。并非所有操纵数据库的东西都来自Laravel4。那是他的意思。他希望在某些列上自定义默认值,例如:

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

我认为Laravel无法实现。我一直在搜索一个小时,以查看是否有可能。


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


大。完美的东西。竖起大拇指,这也对我有帮助。
Glenn Plas

在大声喊叫之前,不多说一句:这在​​laravel中对我不起作用,请看一下此答案的撰写日期:2013年。在您点击向下箭头之前,我们将不胜感激。
Glenn Plas '18年

9

作为未来的Google员工的另一种可能性

我发现在创建记录但从未修改过记录时在update_at列中使用null更为有用。它减小了数据库大小(可以,只是一点),并且有可能一眼就看到它从未被修改过。

为此,我使用:

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

(在Laravel 7和mysql 8中)。


7

请改用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");

它为我创造了奇迹。


这是一个很好的把戏。我希望架构生成器支持分区表,因为我到处都在使用分区表。我试图深入研究代码,但是对我来说,在哪里修改它并不是很明显。
Glenn Plas

-2

这是您的操作方式,我已经检查了它,并且可以在Laravel 4.2上运行。

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

希望这可以帮助。


-4

在Laravel 5中:

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

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


12
但这并没有按照问题中的要求将默认值设置为CURRENT_TIMESTAMP。
乔什

我尝试了这个,但是在5.4 idk中给出了null,为什么,但是当我尝试-> useCurrent();时 它的工作很好
Anthony Kal

没有回答CURRENT_TIMESTAMPon created_atcolumn和on UPDATE CURRENT_TIMESTAMPon updated_atcolumn的问题。拉维尔(Laravel)的耕人们要修复它,请使用: $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP')); $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'));
Hamza Rashid
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.