Итак, я столкнулся с досадной проблемой обновления и сохранения 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
.
(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,