简体   繁体   English

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

[英]How Can I Set the Default Value of a Timestamp Column to the Current Timestamp with Laravel Migrations?

I would like to make a timestamp column with a default value of CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP using the Laravel Schema Builder/Migrations.我想使用 Laravel Schema Builder/Migrations 创建一个默认值为CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP的时间戳列。 I have gone through the Laravel documentation several times, and I don't see how I can make that the default for a timestamp column.我已经多次浏览 Laravel 文档,但我不知道如何将其设为时间戳列的默认值。

The timestamps() function makes the defaults 0000-00-00 00:00 for both columns that it makes. timestamps()函数为它创建的两列设置默认值0000-00-00 00:00

Given it's a raw expression, you should use DB::raw() to set CURRENT_TIMESTAMP as a default value for a column:鉴于它是一个原始表达式,您应该使用DB::raw()CURRENT_TIMESTAMP设置为列的默认值:

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

This works flawlessly on every database driver.这在每个数据库驱动程序上都能完美运行。

As of Laravel 5.1.25 (see PR 10962 and commit 15c487fe ) you can now use the new useCurrent() column modifier method to achieve the same default value for a column:从 Laravel 5.1.25 开始(请参阅PR 10962提交 15c487fe ),您现在可以使用新的useCurrent()列修饰符方法来为列实现相同的默认值:

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

Back to the question, on MySQL you could also use the ON UPDATE clause through DB::raw() :回到问题,在 MySQL 上,您还可以通过DB::raw()使用ON UPDATE子句:

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

Again, as of Laravel 8.36.0 (see PR 36817 ) you can now use the new useCurrentOnUpdate() column modifier method together with the useCurrent() modifier to achieve the same default value for a column:同样,从 Laravel 8.36.0(请参阅PR 36817 )开始,您现在可以使用新的useCurrentOnUpdate()列修饰符方法和useCurrent()修饰符来为列实现相同的默认值:

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

Gotchas陷阱

  • MySQL MySQL

    Starting with MySQL 5.7, 0000-00-00 00:00:00 is no longer considered a valid date.从 MySQL 5.7 开始, 0000-00-00 00:00:00不再被视为有效日期。 As documented at the Laravel 5.2 upgrade guide , all timestamp columns should receive a valid default value when you insert records into your database.正如Laravel 5.2 升级指南中所述,当您将记录插入数据库时​​,所有时间戳列都应该收到一个有效的默认值。 You may use the useCurrent() column modifier (from Laravel 5.1.25 and above) in your migrations to default the timestamp columns to the current timestamps, or you may make the timestamps nullable() to allow null values.您可以在迁移中使用useCurrent()列修饰符(来自 Laravel 5.1.25 及更高版本)将时间戳列默认为当前时间戳,或者您可以使时间戳为nullable()以允许空值。

  • PostgreSQL & Laravel 4.x PostgreSQL 和 Laravel 4.x

    In Laravel 4.x versions, the PostgreSQL driver was using the default database precision to store timestamp values.在 Laravel 4.x 版本中,PostgreSQL 驱动程序使用默认的数据库精度来存储时间戳值。 When using the CURRENT_TIMESTAMP function on a column with a default precision, PostgreSQL generates a timestamp with the higher precision available, thus generating a timestamp with a fractional second part - see this SQL fiddle .当在具有默认精度的列上使用CURRENT_TIMESTAMP函数时,PostgreSQL 会生成具有更高精度的时间戳,从而生成带有小数秒部分的时间戳 -请参阅此 SQL fiddle

    This will led Carbon to fail parsing a timestamp since it won't be expecting microseconds being stored.这将导致 Carbon 无法解析时间戳,因为它不会期望存储微秒。 To avoid this unexpected behavior breaking your application you have to explicitly give a zero precision to the CURRENT_TIMESTAMP function as below:为避免这种意外行为破坏您的应用程序,您必须明确地为CURRENT_TIMESTAMP函数指定零精度,如下所示:

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

    Since Laravel 5.0, timestamp() columns has been changed to use a default precision of zero which avoids this.自 Laravel 5.0 起, timestamp()列已更改为使用默认精度为零,从而避免了这种情况。

Thanks to @andrewhl for pointing out the Laravel 4.x issue in the comments.感谢@andrewhl在评论中指出 Laravel 4.x 问题。

Thanks to @ChanakaKarunarathne for bringing out the new useCurrentOnUpdate() shortcut in the comments.感谢@ChanakaKarunarathne在评论中提出了新的useCurrentOnUpdate()快捷方式。

To create both of the created_at and updated_at columns:要同时创建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'));

You will need MySQL version >= 5.6.5 to have multiple columns with CURRENT_TIMESTAMP您将需要 MySQL 版本 >= 5.6.5 才能拥有多个具有CURRENT_TIMESTAMP的列

Starting from Laravel 5.1.26, tagged on 2015-12-02, a useCurrent() modifier has been added:从 Laravel 5.1.26 开始,标记为 2015-12-02,添加了一个useCurrent()修饰符:

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

PR 10962 (followed by commit 15c487fe ) leaded to this addition. PR 10962 (之后是提交 15c487fe )导致了这个添加。

You may also want to read issues 3602 and 11518 which are of interest.您可能还想阅读感兴趣的问题360211518

Basically, MySQL 5.7 (with default config) requires you to define either a default value or nullable for time fields.基本上,MySQL 5.7(带有默认配置)要求您为时间字段定义默认值或可为空。

As additional possibility for future googlers作为未来谷歌员工的额外可能性

I find it more useful to have null in the updated_at column when the record is been created but has never been modified .我发现在创建记录但从未修改过时在 updated_at 列中设置null更有用。 It reduces the db size (ok, just a little) and its possible to see it at the first sight that the data has never been modified.它减少了数据库的大小(好吧,只是一点点),并且第一眼就可以看到数据从未被修改过。

As of this I use:至此,我使用:

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

(In Laravel 7+8 with mysql 8). (在带有 mysql 8 的 Laravel 7+8 中)。


Edit: Since Laravel 8 you can also use:编辑:从 Laravel 8 开始,您还可以使用:

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

to achieve the same result.达到同样的效果。

Thanks to @bilogic for pointing this out.感谢@bilogic 指出这一点。

This doesn't work for a fact:这对事实不起作用:

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

It doesn't remove the 'default 0' that seems to come with selecting timestamp and it just appends the custom default.它不会删除似乎与选择时间戳一起出现的“默认 0”,它只是附加了自定义默认值。 But we kind of need it without the quotes.但我们有点需要它没有引号。 Not everything that manipulates a DB is coming from Laravel4.并非所有操作数据库的东西都来自 Laravel4。 That's his point.这就是他的观点。 He wants custom defaults on certain columns like:他希望在某些列上自定义默认值,例如:

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

I don't think it's possible with Laravel.我认为 Laravel 不可能。 I've been searching for an hour now to see whether it's possible.我一直在寻找一个小时,看看是否有可能。


Update: Paulos Freita's answer shows that it is possible, but the syntax isn't straightforward.更新: Paulos Freita 的回答表明这是可能的,但语法并不简单。

Use Paulo Freitas suggestion instead.请改用 Paulo Freitas 的建议


Until Laravel fixes this, you can run a standard database query after the Schema::create have been run.在 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");

It worked wonders for me.它为我创造了奇迹。

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

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

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

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

I used this for laravel 5.X, on the users table created_at to set the timestamps automatically on record creation. 我在laravel 5.X的用户表created_at上使用了它,以便在创建记录时自动设置时间戳。 (we have a client that wants to input users directly in the DB so I had to make sure the timestamps got set) (我们有一个客户希望直接在数据库中输入用户,因此我必须确保设置了时间戳记)

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

Use that line if you are doing a change migration. 如果要进行更改迁移,请使用该行。

If you are a fan of Carbon, this works great! 如果您是Carbon的粉丝,那么效果很好!

Or if you are setting this in your table creation migration. 或者,如果您在表创建迁移中进行了设置。

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

I use the following customization in Laravel to:我在 Laravel 中使用以下自定义:

  1. Default created_at to the current timestamp默认 created_at 为当前时间戳
  2. Update the timestamp when the record is updated更新记录时更新时间戳

First, I'll create a file, helpers.php , in the root of Laravel and insert the following:首先,我将在helpers.php的根目录中创建一个文件 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();
    }
}

In composer.json, I'll insert the following into autoload .在 composer.json 中,我将以下内容插入到autoload中。 This allows composer to auto-discover helpers.php.这允许作曲家自动发现 helpers.php。

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

I use the following in my Laravel models.我在我的 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'));
        }

This allows my team to continue using sqlite for unit tests.这允许我的团队继续使用 sqlite 进行单元测试。 ON UPDATE CURRENT_TIMESTAMP is a MySQL shortcut and is not available in 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");

This is how you do it, I have checked it and it works on my Laravel 4.2.这就是你的做法,我已经检查过了,它适用于我的 Laravel 4.2。

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

Hope this helps.希望这可以帮助。

Usethe following: 使用以下内容:

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

Hopefully, it will help you. 希望会对您有所帮助。 Thank you. 谢谢。

In Laravel 5 simply:在 Laravel 5 中:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM