在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