模型字段属性转换时间后,结果集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

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
最佳答案

原因

where 里面会把实际的对象转为字符串来进行比较,你这里传进去 Carbon,会调用 __toString 方法,最终的结果为 2023-08-22 00:00:00,所以如果你只想传字符串,那就传这个 2023-08-22 00:00:00 ,也可以查询到。

原理

除此之外,还有解决办法。

查看 Carbon::__toString 方法的实现,可以看到,他会先获取 localToStringFormat 属性的值,或者回退到静态属性 toStringFormat 的值来作为转为字符串时候的格式。

file

然后继续寻找,可以找到 Carbon::settings 这个方法可以去设置这个属性。

file

那么,我们就有办法解决了。

解决方案

1、在模型重写 asDate 方法。

查看源代码可知,在调用 date 这个 Casts 时,框架内部会调用 asDate 这个方法

file

这个方法的结果是一个经过 Laravel 包装的 Carbon(继承自 Carbon)。那么我们就可以在对应模型中重写这个 asDate 方法。

    protected function asDate($value)
    {
        return parent::asDate($value)->settings(['toStringFormat' => 'Y-m-d']);
    }

这样,在 Collection::where 的时候,就可以直接使用日期字符串来查询了。

但是!这样修改后,在你打印这个字段的字符串形式时,将会为 2023-08-22 而不是原先默认的 2023-08-22 00:00:00 了,所以你最好确定一下,你是否真的需要这样修改(因为这里没有办法判断是哪个字段,所以这个模型下所有的使用了 date Casts 的字段都会受到影响。)。

2、创建自定义的 Casts

这个按照文档来就行了,原理都一样,就是调用 Carbon::settings 方法来设置一下 toStringFormat 的值。

8个月前 评论
讨论数量: 2

cast之后是一个对象,不是字符串,如果想在where里面查找,可以用filter过滤或者模型自己写一个转换,转换为字符串的时间格式

8个月前 评论

原因

where 里面会把实际的对象转为字符串来进行比较,你这里传进去 Carbon,会调用 __toString 方法,最终的结果为 2023-08-22 00:00:00,所以如果你只想传字符串,那就传这个 2023-08-22 00:00:00 ,也可以查询到。

原理

除此之外,还有解决办法。

查看 Carbon::__toString 方法的实现,可以看到,他会先获取 localToStringFormat 属性的值,或者回退到静态属性 toStringFormat 的值来作为转为字符串时候的格式。

file

然后继续寻找,可以找到 Carbon::settings 这个方法可以去设置这个属性。

file

那么,我们就有办法解决了。

解决方案

1、在模型重写 asDate 方法。

查看源代码可知,在调用 date 这个 Casts 时,框架内部会调用 asDate 这个方法

file

这个方法的结果是一个经过 Laravel 包装的 Carbon(继承自 Carbon)。那么我们就可以在对应模型中重写这个 asDate 方法。

    protected function asDate($value)
    {
        return parent::asDate($value)->settings(['toStringFormat' => 'Y-m-d']);
    }

这样,在 Collection::where 的时候,就可以直接使用日期字符串来查询了。

但是!这样修改后,在你打印这个字段的字符串形式时,将会为 2023-08-22 而不是原先默认的 2023-08-22 00:00:00 了,所以你最好确定一下,你是否真的需要这样修改(因为这里没有办法判断是哪个字段,所以这个模型下所有的使用了 date Casts 的字段都会受到影响。)。

2、创建自定义的 Casts

这个按照文档来就行了,原理都一样,就是调用 Carbon::settings 方法来设置一下 toStringFormat 的值。

8个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!