Laravel时间戳被更新,而无需明确调用

Tim*_*wis 3 php mysql transactions laravel laravel-5.4

所以我在Laravel更新和保存时遇到了一个烦人的问题。我有一个模型/表Invoiceinvoices,具有时间戳sent_at

Invoice.php

class Invoice extends Model {
    protected $dates = [
        "sent_at",
    ];
}
Run Code Online (Sandbox Code Playgroud)

我有以下功能来更新Invoice

InvoicesController.php

public function postPayInvoice(Request $request, $invoiceId){
    $user = $this->apiResponse->user;

    $invoiceItemIds = $request->input("invoice_item_ids");

    $invoice = Invoice::with(["invoiceItems" => function($subQuery) use($invoiceItemIds){
        return $subQuery->whereIn("invoice_items.id", $invoiceItemIds);
    }])->where("id", "=", $invoiceId)->first();

    \Log::info("Load: ".$invoice->sent_at);

    DB::beginTransaction();
    try {
        foreach($invoice->invoiceItems AS $invoiceItem){
            $invoiceItem->status = "paid";
            $invoiceItem->paid_at = Carbon::now();
            $invoiceItem->save();
        }

        $totalInvoices = $invoice->invoiceItems()->count();
        $paidInvoiceItems = $invoice->invoiceItems()->where("status", "=", "paid")->count();

        if($totalInvoices == $paidInvoiceItems){
            $invoice->status = "paid";
            $invoice->paid_at = Carbon::now();
        } else {
            $invoice->status = "partially_paid";
        }

        \Log::info("Pre: ".$invoice->sent_at);

        $invoice->save();

        \Log::info("Post: ".$invoice->sent_at);

    } catch(\Exception $ex){
        DB::rollBack();
        return $this->apiResponse->returnFail([], "Unable to Pay Invoice: ".$ex->getMessage(), 200);
    }

    DB::{$request->input("rollback", null) ? "rollback" : "commit"}();

    \Log::info("Post Commit: ".$invoice->sent_at);

    return $this->apiResponse->returnSuccess($invoice, "Invoice paid!", 200);
}
Run Code Online (Sandbox Code Playgroud)

这样做是支付选择InvoiceItems(儿童模式Invoice),并且,如果所有InvoiceItems被标记为paid,然后更新invoices.statuspaid(或partially_paid)和invoices.paid_atCarbon::now()(或null)。

一切正常,但是不知何故,此代码也在更新sent_at(因此,这些\Log语句)。当代码Invoice在应用所有保存逻辑之后,在保存之后,最后在提交之后立即加载时,将sent_at记录该属性:

[2019-05-08 12:43:24]本地信息:加载:2019-05-08 12:42:50
[2019-05-08 12:43:24]本地信息:之前:2019-05- 08 12:42:50
[2019-05-08 12:43:24] local.INFO:发布:2019-05-08 12:42:50
[2019-05-08 12:43:24] local.INFO:提交后:2019-05-08 12:42:50

如您所见,sent_at时间戳始终是2019-05-08 12:42:50。但是,只要我重新查询数据库,时间戳就是2019-05-08 12:43:24,这是paid_atupdated_at时间戳的值。

在此处输入图片说明

statussent_atpaid_atcreated_atupdated_at

请注意,这是从API调用的,随后请求加载Invoice模型列表,该请求具有以下逻辑来确定其他逻辑:

$cutoff = $this->sent_at->addDays(3)->endOfDay();
Run Code Online (Sandbox Code Playgroud)

但是我看不到如何修改该sent_at列(以下未调用保存/更新,即使这样做2019-05-08 12:43:24也并不等同于addDays(3)->endOfDay();

谁看过这个吗?它在另一个视图中弄乱了一些排序逻辑,所以我最终需要修复它。

编辑

如果禁用$invoice->save();,它的updated_at时间戳仍会更新,但是我不知道为什么。而且,很奇怪的是,禁用它$invoiceTransaction->save();$invoiceItem->save();导致对updated_at...的更改。确实会导致数据损坏,但这仍在开发中。

次要编辑

"CREATE TABLE `invoices` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`account_id` int(11) NOT NULL,
`description` text,
`subtotal` decimal(10,2) NOT NULL,
`grand_total` decimal(10,2) NOT NULL,
`status` enum('pending','sent','partially_paid','paid') NOT NULL DEFAULT 
'pending',
`sent_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`paid_at` timestamp NULL DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`deleted_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8"
Run Code Online (Sandbox Code Playgroud)

我相信那里是一个问题:

sent_at 时间戳记非NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

ayn*_*ber 5

This is due to the MySQL 5.7 configuration, and not Laravel.

The first TIMESTAMP column in a table, if not explicitly declared with the NULL attribute or an explicit DEFAULT or ON UPDATE attribute, is automatically declared with the DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP attributes.

src - Mysql Docs

The fix is to set the timestamp to nullable in the migration, and/or alter the table manually.

ALTER TABLE invoices CHANGE sent_at sent_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP;
Run Code Online (Sandbox Code Playgroud)