Laravel的Model的firstOrCreate()踩坑

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_voteModel,首先使用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=28tickets=11,并且id>28的记录不存在。
在这里插入图片描述

猜测可能CarbonModel层日期格式的适配存在问题,不支持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;
    }

结论:

结果表明LaravelModel层与Carbon适配存在问题,并不能自动适配所有的时间格式,当不识别的时候请手动转换,例如数据库中字段为date时候需要使用CarbontoDateString函数进行时间格式的转换。

参考:
[1] https://carbon.nesbot.com/docs/
[2] https://learnku.com/articles/8478/use-of-firstorcreate-firstornew-and-updateorcreate-methods

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章