web-dev-qa-db-fra.com

Comment définir la valeur par défaut d'une colonne d'horodatage sur l'horodatage actuel avec les migrations Laravel?

J'aimerais créer une colonne timestamp avec la valeur par défaut CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP à l'aide de Laravel Schema Builder/Migrations. J'ai parcouru la documentation de Laravel à plusieurs reprises et je ne vois pas comment en faire une valeur par défaut pour une colonne timestamp.

La fonction timestamps() crée les valeurs par défaut 0000-00-00 00:00 pour les deux colonnes qu’elle crée.

108
JoeyD473

Comme il s'agit d'une expression brute, vous devez utiliser DB::raw() pour définir CURRENT_TIMESTAMP comme valeur par défaut pour une colonne:

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

Cela fonctionne parfaitement sur chaque pilote de base de données.

A partir de Laravel 5.1.25 (voir PR 10962 et commit 15c487fe ), vous pouvez utiliser la nouvelle méthode de modificateur de colonne useCurrent() pour définir le CURRENT_TIMESTAMP comme valeur par défaut pour une colonne:

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

Comme demandé, sur MySQL, vous pouvez également utiliser la clause ON UPDATE à DB::raw():

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

Gotchas

  • MySQL

    À partir de MySQL 5.7, 0000-00-00 00:00:00 n'est plus considéré comme une date valide. Comme indiqué dans le Guide de mise à niveau de Laravel 5.2 , toutes les colonnes d’horodatage doivent recevoir une valeur par défaut valide lorsque vous insérez des enregistrements dans votre base de données. Vous pouvez utiliser le modificateur de colonne useCurrent() (à partir de Laravel 5.1.25 et supérieur) dans vos migrations pour définir par défaut les colonnes d’horodatage sur les horodatages actuels, ou vous pouvez définir l’horodatage nullable() pour autoriser les valeurs null.

  • PostgreSQL & Laravel 4.x

    Dans les versions Laravel 4.x, le pilote PostgreSQL utilisait la précision de la base de données par défaut pour stocker les valeurs d’horodatage. Lorsque vous utilisez la fonction CURRENT_TIMESTAMP sur une colonne avec une précision par défaut, PostgreSQL génère un horodatage avec la précision la plus élevée disponible, générant ainsi un horodatage avec une seconde partie fractionnaire - voir ce violon SQL .

    Cela a conduit Carbon à échouer lors de l'analyse syntaxique d'un horodatage, car il ne s'attend pas à ce que des microsecondes soient stockées. Pour éviter ce problème inattendu de casser votre application, vous devez explicitement donner une précision nulle à la fonction CURRENT_TIMESTAMP comme ci-dessous:

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

    Depuis Laravel 5.0, les colonnes timestamp() ont été modifiées pour utiliser une précision par défaut de zéro, ce qui évite cela.

    Merci à @andrewhl pour avoir signalé ce problème dans les commentaires.

210
Paulo Freitas

Pour créer les colonnes created_at et updated_at:

$t->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
$t->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'));

Vous aurez besoin de la version MySQL> = 5.6.5 pour avoir plusieurs colonnes avec CURRENT_TIMESTAMP

40
Brian Adams

À partir de Laravel 5.1.26, identifié le 2015-12-02, un modificateur useCurrent() a été ajouté:

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

PR 10962 (suivi de commit 15c487fe ) a conduit à cet ajout.

Vous voudrez peut-être aussi lire les numéros 3602 et 11518 qui vous intéressent.

Pour résumer, MySQL 5.7 (avec la configuration par défaut) exige que vous définissiez une valeur par défaut ou une valeur nullable pour les champs horaires.

25
Gras Double

Utilisez Paulo Freitas suggestion à la place.


Jusqu'à ce que Laravel corrige ce problème, vous pouvez exécuter une requête de base de données standard après l'exécution du 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");

Cela a fonctionné à merveille pour moi.

8
Marwelln

Cela ne fonctionne pas pour un fait:

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

Il ne supprime pas le "0 par défaut" qui semble venir avec la sélection de l'horodatage et ajoute simplement le paramètre par défaut personnalisé. Mais nous en avons besoin sans les guillemets. Tout ce qui manipule une base de données ne vient pas de Laravel4. C'est son point. Il veut des valeurs personnalisées par défaut sur certaines colonnes comme:

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

Je ne pense pas que ce soit possible avec Laravel. Je cherche depuis une heure pour voir si c'est possible.


Mise à jour: de Paulos Freita réponse montre que c'est possible, mais que la syntaxe n'est pas simple. 

6
Glenn Plas

Je l'ai utilisé pour laravel 5.X, dans la table des utilisateurs created_at pour définir automatiquement l'horodatage lors de la création de l'enregistrement. (nous avons un client qui veut entrer des utilisateurs directement dans la base de données, je devais donc m'assurer que les horodatages étaient réglés)

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

Utilisez cette ligne si vous effectuez une migration de modification.

Si vous êtes fan de Carbon, cela fonctionne très bien!

Ou si vous définissez ceci dans votre migration de création de table.

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

Voici comment vous le faites, je l'ai vérifié et cela fonctionne sur mon Laravel 4.2.

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

J'espère que cela t'aides.

0
Jawad

Dans Laravel 5 simplement:

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

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

0
JoenMarz