在Laravel
中,對數據庫操作上提供類許多便於操作的函數,firstOrCreate()
就是一個典型例子,然而在最近在使用firstOrCreate()
函數的時候,莫名的踩坑了,特此記錄。
實現目的
統計當日每分鐘內票數,如果當前分鐘記錄存在,則票數做+1
操作,否則創建這條記錄並把票數做+1
操作。
數據庫中表結構如下:
CREATE TABLE `app_vote` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`vote_date` date NULL DEFAULT NULL,
`vote_minutes` int(11) NULL DEFAULT NULL,
`tickets` int(11) NULL DEFAULT 0,
`updated_at` timestamp(0) NULL DEFAULT NULL,
`created_at` timestamp(0) NULL DEFAULT NULL
PRIMARY KEY (`id`) USING BTREE
);
PHP
代碼如下所示,Vote
爲表app_vote
的Model
,首先使用Carbon()
來獲取當前時間數據,然後使用firstOrCreate()
對數據數據庫進行操作。
public function index()
{
$timeNow = Carbon::now();
$minutes = $timeNow->hour*24+$timeNow->minute;
$vote = Vote::firstOrCreate(['vote_date'=>$timeNow,'vote_minutes'=>$minutes]);
$vote->increment('tickets');
return $vote;
}
上述代碼的執行結果爲下圖中數據,由此可見結果並不是所期望的,目的結果應該是id=28
的tickets=11
,並且id>28
的記錄不存在。
猜測可能Carbon
與Model
層日期格式的適配存在問題,不支持date
格式的自動轉換,根據猜測修改代碼如下,測試後結果正確。
public function index()
{
$timeNow = Carbon::now();
$minutes = $timeNow->hour*24+$timeNow->minute;
//修改 'vote_date'=>$timeNow->toDateString()
$vote = Vote::firstOrCreate(['vote_date'=>$timeNow->toDateString(),'vote_minutes'=>$minutes]);
$vote->increment('tickets');
return $vote;
}
結論:
結果表明Laravel
的Model
層與Carbon
適配存在問題,並不能自動適配所有的時間格式,當不識別的時候需要手動轉換,例如數據庫中字段爲date
時候,需要使用Carbon
的toDateString
函數進行時間格式的轉換。
參考:
[1] https://carbon.nesbot.com/docs/
[2] https://learnku.com/articles/8478/use-of-firstorcreate-firstornew-and-updateorcreate-methods