Как я могу установить значение по умолчанию столбца метки времени на текущую метку времени с миграциями Laravel?

105

Я хотел бы создать столбец отметки времени со значением по умолчанию CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP с использованием Laravel Schema Builder/Migrations. Я несколько раз просматривал документацию по Laravel и не понимаю, как сделать это по умолчанию для столбца метки времени.

Функция timestamps() делает значения по умолчанию 0000-00-00 00:00 для обоих столбцов, которые она делает.

Теги:
laravel-5
laravel-4

8 ответов

206

Поскольку это сырое выражение, вы должны использовать DB::raw() для установки CURRENT_TIMESTAMP в качестве значения по умолчанию для столбца:

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

Это работает безупречно для каждого драйвера базы данных.

Начиная с Laravel 5.1.25 (см. PR 10962 и совершить 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'));

Gotchas

  • MySQL

    Начиная с MySQL 5.7, 0000-00-00 00:00:00 больше не считается допустимой датой. Как описано в Руководстве по обновлению Laravel 5.2, все столбцы timestamp должны получать действительное значение по умолчанию при вставке записей в вашу базу данных. Вы можете использовать модификатор столбца 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 для указания этой проблемы в комментариях.

  • 0
    Намного лучше предложение, чем мое. Используйте это вместо моего примера DB::statement это намного проще.
  • 0
    Может ли это также использоваться для операторов PARTITION BY в ваших тестах?
Показать ещё 3 комментария
39

Чтобы создать оба столбца 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 version >= 5.6.5, чтобы иметь несколько столбцов с CURRENT_TIMESTAMP

  • 2
    Почему бы просто не использовать $table->timestamps()->default(DB::raw('CURRENT_TIMESTAMP')); ?
  • 0
    @dave Потому что тогда updated_at не изменился бы, когда запись была изменена после ее первоначального создания.
Показать ещё 3 комментария
24

Начиная с Laravel 5.1.26, помеченного на 2015-12-02, добавлен модификатор useCurrent():

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

PR 10962 (за ним следует commit 15c487fe). к этому добавлению.

Вы также можете прочитать проблемы 3602 и 11518, которые представляют интерес.

В принципе, MySQL 5.7 (с конфигурацией по умолчанию) требует, чтобы вы определяли либо значение по умолчанию, либо значение NULL для полей времени.

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

Это сработало для меня чудеса.

  • 0
    Это хороший трюк. Я хотел бы, чтобы построитель схемы поддерживал секционированные таблицы, поскольку я использую их повсеместно. Я попытался покопаться в коде, но для меня не так уж очевидно, где это мод.
6

Это не работает для факта:

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

Он не удаляет "default 0", который, кажется, подходит для выбора отметки времени, и он просто добавляет пользовательский по умолчанию. Но мы нуждаемся в этом без кавычек. Не все, что манипулирует БД, происходит от Laravel4. Это его точка. Он хочет использовать стандартные значения по умолчанию для определенных столбцов, например:

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

Я не думаю, что это возможно с Ларавелем. Я искал час, чтобы увидеть, возможно ли это.


Обновление: Paulos Freita answer показывает, что это возможно, но синтаксис не является простым.

  • 5
    Возможно, смотрите ответ Пауло Фрейтаса в этой теме.
  • 0
    Отлично. Прекрасные вещи. Недурно, мне это тоже помогло.
Показать ещё 2 комментария
1

В Laravel 5 просто:

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

Документация: http://laravel.com/docs/5.1/migrations#creating-columns

  • 9
    Но это не устанавливает значение по умолчанию как CURRENT_TIMESTAMP, как задано в вопросе.
  • 0
    я пытаюсь это, но учитывая ноль в 5.4 IDK почему, но когда я пытаюсь -> useCurrent (); его работа отлично
Показать ещё 1 комментарий
0

Используйте следующее:

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

Надеюсь, это поможет вам. Спасибо.

0

Вот как вы это делаете, я проверил его, и он работает на моем Laravel 4.2.

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

Надеюсь, что это поможет.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню