Làm cách nào tôi có thể đặt Giá trị mặc định của Cột dấu thời gian thành Dấu thời gian hiện tại với Di chuyển của Laravel?


167

Tôi muốn tạo một cột dấu thời gian với giá trị mặc định là CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPsử dụng Trình tạo / Di chuyển lược đồ của Laravel. Tôi đã xem qua tài liệu của Laravel nhiều lần và tôi không thấy làm thế nào tôi có thể biến nó thành mặc định cho cột dấu thời gian.

Các timestamps()chức năng làm cho giá trị mặc định 0000-00-00 00:00cho cả cột rằng nó làm cho.

Câu trả lời:


310

Do đó là biểu thức thô, bạn nên sử dụng DB::raw()để đặt CURRENT_TIMESTAMPlàm giá trị mặc định cho cột:

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

Điều này hoạt động hoàn hảo trên mọi trình điều khiển cơ sở dữ liệu.

Phím tắt mới

Kể từ Laravel 5.1.25 (xem PR 10962cam kết 15c487fe ), bạn có thể sử dụng useCurrent()phương thức sửa đổi cột mới để đặt CURRENT_TIMESTAMPgiá trị làm giá trị mặc định cho cột:

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

Quay lại câu hỏi, trên MySQL bạn cũng có thể sử dụng ON UPDATEmệnh đề thông qua DB::raw():

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

Gotchas

  • MySQL

    Bắt đầu với MySQL 5.7, 0000-00-00 00:00:00không còn được coi là ngày hợp lệ. Như được ghi lại trong hướng dẫn nâng cấp của Laravel 5.2 , tất cả các cột dấu thời gian sẽ nhận được giá trị mặc định hợp lệ khi bạn chèn các bản ghi vào cơ sở dữ liệu của mình. Bạn có thể sử dụng công cụ useCurrent()sửa đổi cột (từ Laravel 5.1.25 trở lên) trong quá trình di chuyển của mình để mặc định các cột dấu thời gian thành dấu thời gian hiện tại hoặc bạn có thể tạo dấu thời gian nullable()để cho phép giá trị null.

  • PostgreSQL & Laravel 4.x

    Trong các phiên bản Laravel 4.x, trình điều khiển PostgreSQL đã sử dụng độ chính xác của cơ sở dữ liệu mặc định để lưu trữ các giá trị dấu thời gian. Khi sử dụng CURRENT_TIMESTAMPhàm trên một cột với độ chính xác mặc định, PostgreSQL tạo dấu thời gian với độ chính xác cao hơn có sẵn, do đó tạo dấu thời gian với phần thứ hai phân đoạn - xem câu đố SQL này .

    Điều này sẽ khiến Carbon thất bại trong việc phân tích dấu thời gian vì nó sẽ không mong đợi micro giây được lưu trữ. Để tránh hành vi bất ngờ này phá vỡ ứng dụng của bạn, bạn phải cung cấp độ chính xác bằng 0 cho CURRENT_TIMESTAMPhàm như sau:

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

    Kể từ Laravel 5.0, timestamp() các cột đã được thay đổi để sử dụng độ chính xác mặc định bằng 0 để tránh điều này.

    Cảm ơn @andrewhl đã chỉ ra vấn đề này trong các bình luận.


Cách tốt hơn đề nghị sau đó của tôi. Sử dụng điều này thay vì DB::statementví dụ của tôi , điều này đơn giản hơn nhiều.
Marwelln

Điều này cũng có thể được sử dụng cho các câu lệnh PHẦN THAM GIA trong các bài kiểm tra của bạn?
Glenn Plas

2
Không hoàn mỹ. Đối với PostgreSQL 'CURRENT_TIMESTAMP' trả về một cái gì đó ở định dạng: 2014-08-11 15: 06: 29,692439. Điều này làm cho phương thức Carbon :: createdFromFormat ('Ymd H: i: s', $ timestamp) không thành công (nó không thể phân tích được mili giây kéo dài). Điều này được sử dụng bởi Laravel khi truy cập dấu thời gian. Để sửa lỗi cho PostgreSQL, hãy sử dụng: DB :: raw ('now () :: timestamp (0)') (tham khảo: postgresql.org/docs/8.1/static/ .)
andrewhl

@andrewhl Thật ra tôi chỉ trả lời cho MySQL, vì đó là chủ đề câu hỏi. Nhưng cảm ơn vì đã chia sẻ điều này với chúng tôi, tôi sẽ cập nhật câu trả lời của mình để đề cập đến điều đó! :)
Paulo Freitas

55

Để tạo cả hai created_atupdated_atcột:

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

Bạn sẽ cần phiên bản MySQL> = 5.6.5 để có nhiều cột với CURRENT_TIMESTAMP


3
Tại sao không chỉ sử dụng $table->timestamps()->default(DB::raw('CURRENT_TIMESTAMP'));?
dave

1
@dave Bởi vì sau đó updated_atsẽ không thay đổi khi bản ghi được sửa đổi sau khi tạo ban đầu
Erik Berkun-Drevnig 7/10/2015

Vâng, thêm vào dấu thời gian đó () không cho phép mặc định dù sao đi nữa, vì vậy nó sẽ không hoạt động. Tôi đã cam kết mã để cho phép nó, nhưng các nhà quản lý Laravel thực sự không muốn mọi người sử dụng mặc định theo cách chúng tôi đang sử dụng (giả sử vì các phiên bản của MySQL trước 5.6.5 không cho phép nhiều cột có dấu thời gian làm mặc định).
dave

Trên thực tế, update_at được quản lý bởi Eloquent, do đó không cần bit "on update" vì nó sẽ được đặt khi một mô hình được cập nhật tự động.
dmyers

@dmyers Nếu bạn đang sử dụng hùng biện thì bạn chỉ có thể làm $t->timestamps();nhưng điều đó không trả lời được câu hỏi.
Brian Adams

44

Bắt đầu từ Laravel 5.1.26, được gắn thẻ vào ngày 2015-12-02, một công cụ useCurrent()sửa đổi đã được thêm vào:

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

PR 10962 (tiếp theo là cam kết 15c487fe ) dẫn đến sự bổ sung này.

Bạn cũng có thể muốn đọc các vấn đề 360211518 được quan tâm.

Về cơ bản, MySQL 5.7 (với cấu hình mặc định) yêu cầu bạn xác định giá trị mặc định hoặc nullable cho các trường thời gian.


10

Điều này không hoạt động cho một thực tế:

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

Nó không xóa 'mặc định 0' dường như đi kèm với việc chọn dấu thời gian và nó chỉ nối thêm mặc định tùy chỉnh. Nhưng chúng tôi loại cần nó mà không có dấu ngoặc kép. Không phải tất cả mọi thứ thao túng DB đều đến từ Laravel4. Đó là quan điểm của anh ấy. Anh ta muốn mặc định tùy chỉnh trên các cột nhất định như:

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

Tôi không nghĩ rằng nó có thể với Laravel. Tôi đã tìm kiếm trong một giờ để xem liệu nó có thể.


Cập nhật: Câu trả lời của Paulos Freita cho thấy điều đó là có thể, nhưng cú pháp không đơn giản.


Tuyệt quá. Công cụ hoàn hảo. Thumbs up, điều này cũng giúp tôi.
Glenn Plas

Nhận xét nhỏ, trước khi hét lên: điều này không hiệu quả với tôi trong laravel, hãy xem ngày mà câu trả lời này được viết: 2013. Nó đã có hiệu lực vào thời điểm đó. Tôi sẽ đánh giá cao nó trước khi bạn nhấn vào mũi tên xuống.
Glenn Plas

9

Như khả năng bổ sung cho các nhân viên của Google trong tương lai

Tôi thấy hữu ích hơn khi có null trong cột update_at khi bản ghi được tạo nhưng chưa bao giờ được sửa đổi . Nó giảm kích thước db (ok, chỉ một chút) và có thể thấy nó ngay từ cái nhìn đầu tiên rằng dữ liệu chưa bao giờ được sửa đổi.

Tôi sử dụng:

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

(Trong Laravel 7 với mysql 8).


7

Sử dụng đề nghị Paulo Freitas thay thế.


Cho đến khi Laravel sửa lỗi này, bạn có thể chạy truy vấn cơ sở dữ liệu tiêu chuẩn sau khi Schema::createđã chạy.

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

Nó làm việc kỳ diệu cho tôi.


Đó là một mẹo hay. Tôi muốn trình xây dựng lược đồ hỗ trợ các bảng được phân đoạn khi tôi sử dụng các bảng ở khắp mọi nơi. Tôi đã cố gắng đào sâu vào mã nhưng nó không rõ ràng với tôi nơi để sửa đổi điều này.
Glenn Plas

-2

Đây là cách bạn làm điều đó, tôi đã kiểm tra nó và nó hoạt động trên Laravel 4.2 của tôi.

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

Hi vọng điêu nay co ich.


-4

Trong Laravel 5 chỉ đơn giản là:

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

Tài liệu: http://laravel.com/docs/5.1/migations#creating-columns


12
Nhưng điều này không đặt mặc định là CURRENT_TIMESTAMP như được hỏi trong câu hỏi.
Josh

Tôi thử cái này trong, nhưng được cho null trong 5,4 idk tại sao, nhưng khi tôi thử -> useCản (); nó hoạt động tốt
Anthony Kal

không trả lời câu hỏi CURRENT_TIMESTAMPtrên created_atcột và on UPDATE CURRENT_TIMESTAMPtrên updated_atcột. Cho đến khi mọi người ở Laravel sửa nó, hãy sử dụng cái này: $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP')); $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'));
Hamza Rashid
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.