Laravel 在更新时更改 created_at

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34673729/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 13:00:37  来源:igfitidea点击:

Laravel changes created_at on update

phplaravellaravel-5eloquentlaravel-5.2

提问by Skatch

I found this answeron the subject, but it doesn't work for me.

我在这个主题上找到了这个答案,但它对我不起作用。

So, I make an entry in the database:

所以,我在数据库中创建一个条目:

// Write lead to database
$lead = Lead::create($lead_data);

And the timestamps look like this, which is good:

时间戳看起来像这样,这很好:

| 2016-01-08 10:34:15 | 2016-01-08 10:34:15 |

But then I make a request to an external server, and I need to update the row:

但随后我向外部服务器发出请求,我需要更新该行:

$lead->user_id = $response['user_id'];
$lead->broker_id = $response['broker_id'];
$lead->save();

and the created_at field gets changed:

并且 created_at 字段被更改:

| 2016-01-08 04:34:17 | 2016-01-08 10:34:17 |

How do I solve this problem?

我该如何解决这个问题?

EDIT

编辑

I need a solution that would just modify the behavior without dropping columns or resetting migrations. The fix has to be performed on a live database without touching the data. As suggested below, I tried the following migration:

我需要一个只修改行为而不删除列或重置迁移的解决方案。必须在不接触数据的情况下在实时数据库上执行修复。如下所示,我尝试了以下迁移:

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

but nothing happens. The created_at field still gets modified on update.

但什么也没有发生。created_at 字段仍然在更新时被修改。

回答by patricus

If you're on Laravel 5.2 and using MySQL, there was a bit of a "bug" introduced with the timestamps. You can read all about the issue on github here. It has to do with the timestamp defaults, and MySQL automatically assigning DEFAULT CURRENT_TIMESTAMP or ON UPDATE CURRENT_TIMESTAMP attributes under certain conditions.

如果您使用的是 Laravel 5.2 并使用 MySQL,那么时间戳会引入一些“错误”。您可以在此处阅读 github 上有关该问题的所有信息。它与时间戳默认值有关,MySQL 在某些条件下自动分配 DEFAULT CURRENT_TIMESTAMP 或 ON UPDATE CURRENT_TIMESTAMP 属性。

Basically, you have three options.

基本上,您有三个选择。

  1. Update MySQL variable:
  1. 更新 MySQL 变量:

If you set the explicit_defaults_for_timestampvariable to TRUE, no timestamp column will be assigned the DEFAULT CURRENT_TIMESTAMP or ON UPDATE CURRENT_TIMESTAMP attributes automatically. You can read more about the variable here.

如果将该explicit_defaults_for_timestamp变量设置为TRUE,则不会自动为时间戳列分配 DEFAULT CURRENT_TIMESTAMP 或 ON UPDATE CURRENT_TIMESTAMP 属性。您可以在此处阅读有关该变量的更多信息。

  1. Use nullable timestamps:
  1. 使用可为空的时间戳:

Change $table->timestamps()to $table->nullableTimestamps(). By default, the $table->timestamps()command creates timestamp fields that are not nullable. By using $table->nullableTimestamps(), your timestamp fields will be nullable, and MySQL will not automatically assign the first one the DEFAULT CURRENT_TIMESTAMP or ON UPDATE CURRENT_TIMESTAMP attributes.

更改$table->timestamps()$table->nullableTimestamps()。默认情况下,该$table->timestamps()命令创建不可为空的时间戳字段。通过使用$table->nullableTimestamps(),您的时间戳字段将可以为空,并且 MySQL 不会自动为第一个字段分配 DEFAULT CURRENT_TIMESTAMP 或 ON UPDATE CURRENT_TIMESTAMP 属性。

  1. Define the timestamps yourself:
  1. 自己定义时间戳:

Instead of using $table->timestamps, use $table->timestamp('updated_at'); $table->timestamp('created_at');yourself. Make sure your 'updated_at' field is the first timestamp in the table, so that it will be the one that is automatically assign the DEFAULT CURRENT_TIMESTAMP or ON UPDATE CURRENT_TIMESTAMP attributes.

与其使用$table->timestamps$table->timestamp('updated_at'); $table->timestamp('created_at');不如使用自己。确保您的“updated_at”字段是表中的第一个时间戳,以便它自动分配 DEFAULT CURRENT_TIMESTAMP 或 ON UPDATE CURRENT_TIMESTAMP 属性。

回答by sgrover

Skatch - I think your solution above is not quite right, but is probaby fine in this case.

Skatch - 我认为你上面的解决方案不太正确,但在这种情况下可能很好。

The issue is that you are getting the PHP date, not the default MYSQL timestamp for your default. When you run that migration you end up with a statement like this:

问题是您获取的是 PHP 日期,而不是默认的默认 MYSQL 时间戳。当您运行该迁移时,您最终会得到如下语句:

alter table alter column created_at default '2016:02:01 12:00:00';

Notice the string for your date. When you run your migration THAT date will always be used for your created_at, not the current date when a record is added days later.

注意日期的字符串。当您运行迁移时,该日期将始终用于您的 created_at,而不是几天后添加记录时的当前日期。

Instead of doing "date('Y:m:d H:i:s')", you can do DB::raw('current_timestamp') to address this issue.

您可以执行 DB::raw('current_timestamp') 来解决此问题,而不是执行 "date('Y:m:d H:i:s')"。

(sry, couldn't just add a comment above - my reputation is not high enough yet...)

(对不起,不能只是在上面添加评论 - 我的声誉还不够高......)

回答by sgrover

Posting this as a top level answer, summarizing our comment discussion.

将此作为顶级答案发布,总结我们的评论讨论。

First, there is a date bugintroduced in Laravel - as noted by @patricus. The suggested solutions in the bug discussion are to either use nullableTimestamps() instead of just timestamps(), or to create the created_at and updated_at fields directly - $table->timestamp('updated_at')->change().

首先,Laravel 中引入了一个日期错误- 正如@patricus 所指出的。错误讨论中建议的解决方案是使用 nullableTimestamps() 而不仅仅是 timestamps(),或者直接创建 created_at 和 updated_at 字段 - $table->timestamp('updated_at')->change()

This can also be fixed with raw SQL. An ALTER statement similar to this

这也可以通过原始 SQL 修复。与此类似的 ALTER 语句

alter table loader_rawvalues MODIFY column updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

That can be applied directly to your existing DB tables (Test it first, or course!). OR you can use DB::unprepared() to apply it from your migration - for example:

这可以直接应用于您现有的数据库表(首先测试它,或者当然!)。或者您可以使用 DB::unprepared() 从您的迁移中应用它 - 例如:

class CreateMyTable extends Migration
{
    public function up()
    {
        Schema::create('mytable', function (Blueprint $table) {
            $table->bigIncrements('id');
            // ...
            $table->timestamps();
        });

        DB::unprepared('alter table mytable MODIFY column updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP');
    }
}

回答by Khairul Imam

That must be an issue on your table field definition. I faced the same issue recently, and when I check my table, the created_athas an "EXTRA" with value on update CURRENT_TIMESTAMP, to have Laravel behave normally just update the field definition with something like:

这一定是您的表字段定义的问题。我最近遇到了同样的问题,当我检查我的表时,created_at有一个 " EXTRA" 值on update CURRENT_TIMESTAMP,要让 Laravel 正常运行,只需使用以下内容更新字段定义:

ALTER TABLE table_name CHANGE created_at created_at timestamp NOT NULL default CURRENT_TIMESTAMP;