模型字段属性转换时间后,结果集where时间字段,传字符时间无法查询
Rank排名模型:
class Rank extends Model
{
protected $casts = [
//排名日期
'rank_date' => 'date:Y-m-d',
];
}
//有rank_date为2023-08-22得数据
$all = Rank::all();
//传字符时间,没有值,查找不到
$all->where('rank_date', '2023-08-22')->value('rank_date');
//传Carbon实例,有值,查到得到
$all->where('rank_date', Carbon::parse('2023-08-22'))->value('rank_date');
请问以上是什么原因造成得呢,感觉使用casts
转为时间Carbon
实例后更不方便了。框架版本laravel 9
原因
where 里面会把实际的对象转为字符串来进行比较,你这里传进去 Carbon,会调用
__toString
方法,最终的结果为2023-08-22 00:00:00
,所以如果你只想传字符串,那就传这个2023-08-22 00:00:00
,也可以查询到。原理
除此之外,还有解决办法。
查看 Carbon::__toString 方法的实现,可以看到,他会先获取
localToStringFormat
属性的值,或者回退到静态属性toStringFormat
的值来作为转为字符串时候的格式。然后继续寻找,可以找到 Carbon::settings 这个方法可以去设置这个属性。
那么,我们就有办法解决了。
解决方案
1、在模型重写
asDate
方法。查看源代码可知,在调用
date
这个 Casts 时,框架内部会调用asDate
这个方法这个方法的结果是一个经过 Laravel 包装的 Carbon(继承自 Carbon)。那么我们就可以在对应模型中重写这个
asDate
方法。这样,在
Collection::where
的时候,就可以直接使用日期字符串来查询了。但是!这样修改后,在你打印这个字段的字符串形式时,将会为
2023-08-22
而不是原先默认的2023-08-22 00:00:00
了,所以你最好确定一下,你是否真的需要这样修改(因为这里没有办法判断是哪个字段,所以这个模型下所有的使用了date
Casts 的字段都会受到影响。)。2、创建自定义的 Casts
这个按照文档来就行了,原理都一样,就是调用
Carbon::settings
方法来设置一下toStringFormat
的值。