【问题标题】:Laravel changes created_at on updateLaravel 在更新时更改 created_at
【发布时间】:2016-04-12 22:33:46
【问题描述】:

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

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

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

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

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

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

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

created_at 字段发生变化:

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

我该如何解决这个问题?

编辑

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

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

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

【问题讨论】:

  • 在更新之前如何加载 $lead 变量?
  • $lead 变量被create 方法填充,但无论如何,我在写入后也用$lead = Lead::find($lead->id); 尝试过,问题仍然存在。

标签: php laravel laravel-5 eloquent laravel-5.2


【解决方案1】:

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

基本上,您有三个选择。

  1. 更新 MySQL 变量:

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

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

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

  1. 自己定义时间戳:

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

【讨论】:

  • 我需要一个可以在实时运行的数据库上实施的解决方案。重置迁移和删除列不是一种选择。
  • 这个愚蠢的错误仍然存​​在于 Lara8 中。我只有“created_at”字段,所以我必须覆盖 UPDATED_AT 常量。如果它为空 - 每次更新时“created_at”都会更改。 FALSE 解决了问题
【解决方案2】:

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

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

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

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

您可以使用 DB::raw('current_timestamp') 代替“date('Y:m:d H:i:s')”来解决这个问题。

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

【讨论】:

  • 你说得对,我没想到。无论如何,我尝试了所有方法,包括您的建议 $table->datetime('created_at')->default(DB::raw('CURRENT_TIMESTAMP'))->change();,但这是唯一可行的方法……下次我会尝试更好地使用 SQL。
  • 您需要通过迁移来执行此操作吗?本机 SQL 命令很简单:“alter table mytable modify column mycolumn timestamp default current_timestamp NOT NULL on update current_timestamp;”直接在数据库上运行它,一切都应该得到修复。 (先测试!)。如果您必须通过迁移来完成,您可以使用 DB::unprepared($MyRawSQL); 来完成。类似 public function up() { Schema::create(....); DB::unprepared($MySQL); }
  • - 这也绕过了@patricus 提到的错误。
  • 是的,原始数据库查询应该可以解决这个问题...感谢您的输入,将在下一个项目中派上用场(这个项目现在工作得很好)。在答案中写一个完整的解决方案,我会给你打勾:)
【解决方案3】:

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

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

这也可以通过原始 SQL 来解决。与此类似的 ALTER 语句

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

这可以直接应用于您现有的数据库表(首先测试它,或者当然!)。或者您可以使用 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');
    }
}

【讨论】:

  • 我认为您需要在没有 ON UPDATE 语句的情况下更改 created_at 字段,updated_at 可以正常工作。 :)
  • 要确认,如果您需要运行迁移来修复 updated_at 问题,基于 sgrover 的解决方案,您可以将以下内容添加到您的迁移中,用于所有需要修复而不删除的表:DB::unprepared('alter table faqs modify column created_at timestamp default current_timestamp NOT NULL'); 沿with DB::unprepared('alter table faqs modify column updated_at timestamp default current_timestamp NOT NULL'); 这会将 TIMESTAMP 设置为默认为 CURRENT TIMESTAMP 并删除额外的 ON UPDATE 规则。
【解决方案4】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-19
    • 1970-01-01
    • 2016-04-01
    • 2014-12-23
    • 1970-01-01
    • 2014-08-15
    • 2020-10-23
    相关资源
    最近更新 更多