Як я можу встановити значення за замовчуванням стовпця часової позначки на поточну мітку за допомогою міграції Laravel?


168

Я хотів би зробити стовпчик часових позначок із значенням за замовчуванням, CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPвикористовуючи Builder / Міграцію схеми Laravel. Я декілька разів переглядав документацію 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 та 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 , усі стовпчики часових позначок повинні отримувати дійсне значення за замовчуванням, коли ви вставляєте записи у свою базу даних. Ви можете використовувати 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

Чи можна це також використовувати для операцій PARTITION BY у ваших тестах?
Гленн Плас

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, оскільки це питання. Але дякую, що поділився цим із нами, я оновлю свою відповідь, щоб висвітлити це! :)
Пауло Фрейтас

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'));?
Дейв

1
@dave Тому що тоді updated_atне змінилося б, коли запис було змінено після його первинного створення
Ерік Беркун-Древниг

Так, додати, що часові позначки () взагалі не дозволяють встановити параметри за замовчуванням, так що це не працює взагалі. Я вчинив код, щоб дозволити його, але менеджери Laravel не дуже хочуть, щоб люди використовували за замовчуванням так, як ми його використовуємо (якщо вважати, що версії MySQL до 5.6.5 не дозволяють декілька стовпців, які мають часові позначки за замовчуванням).
Дейв

Насправді оновлення_at управляється красномовним, тому зовсім не потрібно біт "on update", оскільки він буде встановлений при автоматичному оновленні моделі.
dmyers

@dmyers Якщо ви використовуєте красномовний, ви можете просто зробити, $t->timestamps();але це не відповідає на питання.
Брайан Адамс

44

Починаючи з Laravel 5.1.26, позначений тегами 2015-12-02, додано useCurrent()модифікатор:

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

PR 10962 (далі комісія 15c487fe ) призвела до цього доповнення.

Ви також можете прочитати питання 3602 та 11518, які цікавлять вас.

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


10

Це не працює на факт:

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

Він не видаляє "за замовчуванням 0", який, мабуть, поставляється з вибором часової позначки, і просто додає спеціальний замовчування. Але нам це начебто потрібно без цитат. Не все, що маніпулює БД, походить від Laravel4. Це його суть. Він хоче замовчувати за замовчуванням у певних стовпцях, таких як:

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

Я не думаю, що це можливо з Laravel. Я вже годину шукав, щоб побачити, чи це можливо.


Оновлення: Paulos Freita в відповідь показує , що це можливо, але синтаксис НЕ так просто.


Чудово. Ідеальний матеріал. Великі пальці вгору, і це мені допомогло.
Гленн Плаз

невелике зауваження, перш ніж кричати: це не працює для мене в laravel, погляньте на дату написання цієї відповіді: 2013. Це було дійсно тоді. Буду вдячний, перш ніж натиснути стрілку вниз.
Гленн Плас

9

Як додаткова можливість для майбутніх гуглерів

Мені здається, корисніше мати null у стовпці оновленого_at коли створений запис, але він ніколи не змінювався . Це зменшує розмір db (добре, трохи), і його можна побачити з першого погляду, що дані ніколи не змінювалися.

З цього я використовую:

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

(У Laravel 7 з mysql 8).


7

Використовуйте замість цього пропозицію Пауло Фрейтаса .


Поки 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

-2

Ось як ви це робите, я перевірив це, і він працює на моєму Laravel 4.2.

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

Сподіваюся, це допомагає.


-5

У Laravel 5 просто:

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

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


13
Але це не встановлює значення за замовчуванням як CURRENT_TIMESTAMP, як задано у питанні.
Джош

я спробую це, але з урахуванням нуля в 5.4 idk чому, але коли я намагаюся -> useCurrent (); її робота чудово
Ентоні Кал

не відповідає на питання CURRENT_TIMESTAMPпро created_atколонку і on UPDATE CURRENT_TIMESTAMPпро updated_atколонку. Доки люди з Laravel виправлять це, скористайтеся цим: $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP')); $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'));
Хамза Рашид
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.