ฉันจะตั้งค่าเริ่มต้นของคอลัมน์การประทับเวลาเป็นการประทับเวลาปัจจุบันด้วยการย้ายถิ่นของ Laravel ได้อย่างไร


168

ฉันต้องการสร้างคอลัมน์การประทับเวลาด้วยค่าเริ่มต้นของการCURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPใช้ตัวสร้าง / การย้าย Laravel Schema ฉันได้อ่านเอกสาร 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()เพื่ออนุญาตให้มีค่า Null

  • 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 โดยคำแถลงในการทดสอบของคุณหรือไม่?
Glenn Plas

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 ที่จริงฉันตอบสำหรับ MySQL เท่านั้นเนื่องจากเป็นหัวข้อคำถาม แต่ขอขอบคุณที่แบ่งปันสิ่งนี้กับเราฉันจะอัปเดตคำตอบของฉันเพื่อให้ครอบคลุม! :)
Paulo Freitas

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'));?
dave

1
@dave เพราะupdated_atจะไม่เปลี่ยนแปลงเมื่อบันทึกถูกแก้ไขหลังจากการสร้างครั้งแรก
Erik Berkun-Drevnig

ใช่เพิ่มในการประทับเวลานั้น () ไม่อนุญาตให้มีการเริ่มต้นอย่างไรก็ตามเพื่อที่จะไม่ทำงานเลย ฉันยอมรับรหัสเพื่อให้อนุญาต แต่ผู้จัดการ Laravel ไม่ต้องการให้ผู้คนใช้ค่าเริ่มต้นตามวิธีที่เราใช้ (สมมติว่าเป็นเพราะรุ่นของ MySQL ก่อน 5.6.5 ไม่อนุญาตให้มีคอลัมน์หลายคอลัมน์ที่มีค่าเริ่มต้น)
dave

จริงๆแล้ว updated_at ได้รับการจัดการโดย Eloquent ดังนั้นจึงไม่จำเป็นต้องใช้บิต "ในการอัปเดต" เลยเพราะมันจะถูกตั้งค่าเมื่อมีการอัปเดตโมเดลโดยอัตโนมัติ
dmyers

@dmyers ถ้าคุณใช้ฝีปากคุณก็ทำได้$t->timestamps();แต่นั่นไม่ได้ตอบคำถาม
Brian Adams

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' ที่ดูเหมือนว่ามาพร้อมกับการเลือกการประทับเวลาและมันจะต่อท้ายค่าเริ่มต้นที่กำหนดเอง แต่เราต้องการมันโดยไม่มีคำพูด ไม่ใช่ทุกสิ่งที่จัดการ DB มาจาก Laravel4 นั่นคือจุดของเขา เขาต้องการค่าเริ่มต้นที่กำหนดเองในคอลัมน์บางอย่างเช่น:

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

ฉันคิดว่ามันเป็นไปไม่ได้กับ Laravel ตอนนี้ฉันกำลังค้นหาชั่วโมงเพื่อดูว่าเป็นไปได้


ปรับปรุง: คำตอบของ Paulos Freita แสดงให้เห็นว่าเป็นไปได้ แต่ไวยากรณ์ไม่ตรงไปตรงมา


ยิ่งใหญ่ สิ่งที่สมบูรณ์แบบ ยกนิ้วสิ่งนี้ช่วยฉันด้วย
Glenn Plas

คำพูดเล็ก ๆ น้อย ๆ ก่อนที่จะตะโกน: มันไม่ได้ผลสำหรับฉันใน laravel ลองดูวันที่คำตอบนี้ถูกเขียนขึ้น: 2013. มันใช้ได้แล้ว ฉันจะขอบคุณมันก่อนที่คุณจะแตะที่ลูกศรลง
Glenn Plas

9

ความเป็นไปได้เพิ่มเติมสำหรับผู้ใช้ Google ในอนาคต

ฉันคิดว่ามันมีประโยชน์มากขึ้นที่จะมีnullในคอลัมน์ updated_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

ใช้คำแนะนำของ 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

-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-columns


13
แต่สิ่งนี้ไม่ได้ตั้งค่าเริ่มต้นเป็น CURRENT_TIMESTAMP ตามที่ถามในคำถาม
Josh

ฉันลองสิ่งนี้ แต่ให้ null ใน 5.4 idk ทำไม แต่เมื่อฉันลอง -> useCurrent (); มันทำงานได้ดี
Anthony Kal

ไม่ตอบคำถาม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'));
Hamza Rashid
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.