Laravel移行でタイムスタンプ列のデフォルト値を現在のタイムスタンプに設定する方法はありますか


167

CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPLaravel Schema Builder / Migrations を使用するデフォルト値でタイムスタンプ列を作成したいと思います。Laravelのドキュメントを何度か読みましたが、タイムスタンプ列のデフォルトに設定する方法がわかりません。

timestamps()機能はデフォルトを作る0000-00-00 00:00ことが可能両方の列のために。

回答:


310

それが生の式であることを考えると、列のデフォルト値としてDB::raw()設定するにはを使用する必要CURRENT_TIMESTAMPがあります。

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

これは、すべてのデータベースドライバで問題なく動作します。

新しいショートカット

Laravel 5.1.25(PR 10962およびcommit 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()、現在のタイムスタンプにタイムスタンプ列をデフォルトにあなたの移行中(Laravel 5.1.25からと上)列修飾子を、またはあなたがタイムスタンプを作ることが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についてのみ回答しました。しかし、これを私たちと共有してくれてありがとう、それをカバーするために私の答えを更新します!:)
パウロフレイタス2014

55

両方を作成するにcreated_atしてupdated_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'));ですか?
デイブ、2015年

1
@dave updated_atレコードが最初の作成後に変更されても変更されないため
Erik Berkun-Drevnig

そうですね、それに加えて、timestamps()はデフォルトを許可しないため、まったく機能しません。私はそれを許可するためにコードをコミットしましたが、Laravelマネージャーは、私たちが使用している方法でデフォルトを使用することを本当に望んでいません(5.6.5より前のバージョンのMySQLは、デフォルトとしてタイムスタンプを持つ複数の列を許可しないため)。
デイブ

実際、updated_atはEloquentによって管理されているため、モデルが自動的に更新されるときに設定されるため、「更新時」ビットはまったく必要ありません。
dmyers

@dmyers雄弁を使用している場合、あなたはそれを行うことができます$t->timestamps();が、それは質問に答えません。
ブライアンアダムス

44

2015-12-02でタグ付けされたLaravel 5.1.26以降、useCurrent()修飾子が追加されました。

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

PR 10962(続いてcommit 15c487fe)がこの追加につながりました

興味のある問題360211518を読むこともできます。

基本的に、MySQL 5.7(デフォルト設定を使用)では、デフォルト値または時間フィールドのnull許容のいずれかを定義する必要があります。


10

これは事実では機能しません:

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

タイムスタンプの選択に伴うと思われる「デフォルト0」を削除せず、カスタムデフォルトを追加するだけです。しかし、私たちは引用符なしでそれを必要としています。DBを操作するすべてがLaravel4から来るわけではありません。それが彼のポイントです。彼は次のような特定の列のカスタムデフォルトを求めています。

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

Laravelでそれが可能であるとは思わない。私はそれが可能であるかどうか確かめるために1時間探していました。


更新: Paulos Freitaの回答は、それが可能であることを示していますが、構文は単純ではありません。


すごい。完璧なもの。いいね、これも私を助けました。
Glenn Plas 2014年

少し発言してから、叫ぶ前に:これはlaravelでは機能しません。この回答が書かれた日付(2013年)を見てください。当時は有効でした。下矢印をタップする前にお願いします。
Glenn Plas

9

将来のグーグルの追加の可能性として

レコードが作成されたが変更されていない場合は、updated_at列にnullを含める方が便利です。これにより、データベースのサイズが小さくなり(大丈夫、少しだけ)、データが変更されていないことが一目でわかります。

この時点で私は使用します:

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

(mysql 8を含むLaravel 7では)。


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 2013

-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として設定しません。
Josh、

私はこれを試しますが、5.4 idkの理由でnullが指定されていますが、-> useCurrent();を試すと、その仕事はうまくいく
Anthony Kal

質問に答えるしないCURRENT_TIMESTAMPcreated_at、列とon UPDATE CURRENT_TIMESTAMPupdated_atの列。Laravelの人々はそれを修正するまで、これを使用する: $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP')); $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'));
ハムザ・ラシッド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.