Отметка времени Laravel обновляется без явного вызова для этого - PullRequest
3 голосов
/ 08 мая 2019

Итак, я столкнулся с досадной проблемой обновления и сохранения Laravel.У меня есть модель / таблица Invoice и invoices, у которой есть отметка времени 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);
}

Чтоэто платит выбранным InvoiceItems (дочерняя модель Invoice), и, если все InvoiceItems помечены как paid, то обновляются invoices.status до paid (или partially_paid) и invoices.paid_at до Carbon::now() (или null).

Все это прекрасно работает, но каким-то образом этот код также обновляет sent_at (следовательно, операторы \Log).Когда код загружает Invoice, после применения всей логики сохранения, сразу после сохранения и, наконец, сразу после фиксации, регистрируется атрибут sent_at:

[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[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_at и updated_at.

enter image description here

(status, sent_at, paid_at, created_at, updated_at)

Обратите внимание, что это вызывается из API с последующим запросом на загрузку списка Invoice модели, которые имеют следующую логику для определения такой дополнительной логики:

$cutoff = $this->sent_at->addDays(3)->endOfDay();

Но я не понимаю, как это могло бы изменить столбец sent_at (никакое сохранение / обновление не вызывается после, и даже если2019-05-08 12:43:24 не равняется addDays(3)->endOfDay();

Кто-нибудь видел это раньше? Это испортило некоторую логику упорядочения в другом представлении, поэтому мне нужно со временем исправить это ...

Edit

Если я отключу $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"

Я считаю, что здесь есть проблема:

sent_at отметка времени NOT NULL DEFAULT CURRENT_TIMESTAMP при обновлении CURRENT_TIMESTAMP,

1 Ответ

5 голосов
/ 08 мая 2019

Это связано с конфигурацией MySQL 5.7, а не с Laravel.

Первый столбец TIMESTAMP в таблице, если он явно не объявлен с атрибутом NULL или явным атрибутом DEFAULT или ON UPDATE, автоматически объявляется с атрибутами DEFAULT CURRENT_TIMESTAMP и ON UPDATE CURRENT_TIMESTAMP.

src - Mysql Docs

Исправлено: в метке времени для метки времени устанавливается значение NULL, и / или вручную изменяется таблица.

ALTER TABLE invoices CHANGE sent_at sent_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...