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

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

timestamps()函数为它所创建的两列设置默认值0000-00-00 00:00

255012 次浏览

但事实并非如此:

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

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

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

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


Paulos Freita的回答表明这是可能的,但语法并不简单。

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

它对我产生了奇效。

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

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

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

从Laravel 5.1.25(参见10962年公关提交15 c487fe)开始,你现在可以使用新的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(参见36817年公关)开始,你现在可以使用新的useCurrentOnUpdate()列修饰符方法和useCurrent()修饰符来为列实现相同的默认值:

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

陷阱

  • < p > < >强MySQL
    从MySQL 5.7开始,0000-00-00 00:00:00不再被认为是一个有效的日期。正如Laravel 5.2升级指南中所记录的那样,在将记录插入数据库时,所有时间戳列都应该接收一个有效的默认值。您可以在迁移中使用useCurrent()列修饰符(来自Laravel 5.1.25及以上版本)来默认时间戳列为当前时间戳,或者您可以使时间戳nullable()允许空值。

  • < p > < >强PostgreSQL,Laravel 4.倍

    在Laravel 4。x版本时,PostgreSQL驱动程序使用默认的数据库精度来存储时间戳值。当在具有默认精度的列上使用CURRENT_TIMESTAMP函数时,PostgreSQL会生成一个具有更高精度的时间戳,从而生成一个带有分数秒部分的时间戳——查看这个SQL小提琴

    这将导致Carbon解析时间戳失败,因为它不希望存储微秒。为了避免这种意外的行为破坏你的应用程序,你必须显式地给CURRENT_TIMESTAMP函数一个0精度,如下所示:

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

    自Laravel 5.0以来,timestamp()列已更改为使用默认精度为零,从而避免了这种情况。

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

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

创建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

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

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

希望这能有所帮助。

从Laravel 5.1.26开始,标记在2015-12-02,useCurrent()修饰符已经添加:

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

10962年公关(后面跟着提交15 c487fe)导致了这个添加。

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

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

在Laravel 5中:

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

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

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

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

我使用的是:

$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指出这一点。

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

$table->dateTime('signed_when')->useCurrent();

在laravel 7,8中设置当前时间使用以下方法:

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

我在Laravel中使用以下自定义:

  1. 默认created_at为当前时间戳
  2. 更新记录时更新时间戳

首先,我将在Laravel的根目录中创建一个文件helpers.php,并插入以下内容:

<?php


if (!function_exists('database_driver')) {
function database_driver(): string
{
$connection = config('database.default');
return config('database.connections.' . $connection . '.driver');
}
}


if (!function_exists('is_database_driver')) {
function is_database_driver(string $driver): bool
{
return $driver === database_driver();
}
}

在作曲家。,我将插入以下内容到autoload。这允许编写器自动发现helpers.php。

    "autoload": {
"files": [
"app/Services/Uploads/Processors/processor_functions.php",
"app/helpers.php"
]
},

我在Laravel模型中使用以下方法。

        if (is_database_driver('sqlite')) {
$table->timestamps();
} else {
$table->timestamp('created_at')->default(\DB::raw('CURRENT_TIMESTAMP'));
$table->timestamp('updated_at')
->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
}

这允许我的团队继续使用sqlite进行单元测试。ON UPDATE CURRENT_TIMESTAMP是MySQL的快捷方式,在sqlite中不可用。

唯一对我有用的是

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

它将100%工作。通过这种方式,您可以在更改列的datetype后设置默认的datetime值。

Schema::table('table_name', function (Blueprint $table) {
$table->dateTime('ans_time')->default(now())->change();
});