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

时间:2019-05-08 16:58:12

标签: php mysql laravel transactions laravel-5.4

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

Invoice.php

class Invoice extends Model {
    protected $dates = [
        "sent_at",
    ];
}

我具有以下用于更新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);
}

此操作将支付所选的InvoiceItemsInvoice的子模型),并且,如果所有InvoiceItems都标记为paid,则更新{{1} }到invoices.status(或paid)和partially_paidinvoices.paid_at(或Carbon::now())。

这一切都很好,但是以某种方式,此代码也正在更新null(因此,sent_at语句)。当代码在应用所有保存逻辑之后,即在保存之后,最后在提交之后立即加载\Log时,将记录Invoice属性:

  

[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
  [2019-05-08 12:43:24] local.INFO:提交日期:2019-05-08 12:42:50

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

enter image description here

({updated_atstatussent_atpaid_atcreated_at

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

Invoice

但是我看不到如何修改$cutoff = $this->sent_at->addDays(3)->endOfDay(); 列(此后没有调用保存/更新,即使这样做,sent_at也并不等于2019-05-08 12:43:24 < / p>

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

编辑

如果我禁用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" 时间戳记非空DEFAULT CURRENT_TIMESTAMP开启UPDATE CURRENT_TIMESTAMP,

1 个答案:

答案 0 :(得分:5)

这是由于MySQL 5.7配置,而不是Laravel。

  

如果未使用NULL属性或显式的DEFAULT或ON UPDATE属性显式声明表中的第一个TIMESTAMP列,则会使用DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP属性自动声明。

src - Mysql Docs

解决方法是在迁移中将时间戳记设置为可为空,和/或手动更改表。

ALTER TABLE invoices CHANGE sent_at sent_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP;