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

时间:2013-08-05 20:59:53

标签: php mysql laravel laravel-4 laravel-5

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

timestamps()函数为其生成的两列创建默认值0000-00-00 00:00

13 个答案:

答案 0 :(得分:227)

鉴于它是原始表达式,您应该使用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()允许空值。< / p>

  • PostgreSQL&amp; 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在评论中指出了这个问题。

答案 1 :(得分: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版本&gt; = 5.6.5才能拥有多个CURRENT_TIMESTAMP

答案 2 :(得分:27)

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

答案 3 :(得分:16)

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

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

截至目前,我使用的是

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

(在Laravel 7和mysql 8中)。

答案 4 :(得分:8)

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

它为我创造了奇迹。

答案 5 :(得分:7)

这不适用于事实:

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

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

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

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


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

答案 6 :(得分:1)

我在laravel 5.X的用户表created_at上使用了它,以在创建记录时自动设置时间戳。 (我们有一个客户希望直接在数据库中输入用户,因此我必须确保设置了时间戳记)

<?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());

答案 7 :(得分:1)

我在 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();
    }
}

在 composer.json 中,我会将以下内容插入到 autoload 中。这允许 Composer 自动发现 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 中不可用。

答案 8 :(得分:0)

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

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

希望这有帮助。

答案 9 :(得分:0)

In Laravel 5 simply:

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

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

答案 10 :(得分:0)

使用以下内容:

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

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

答案 11 :(得分:0)

如果您要为dateTime列设置当前日期时间(就像我在Google上搜索时一样),请使用这种方式

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

答案 12 :(得分:0)

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

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