You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中如何在morphTo关联中使用whereHas?

在Laravel多态关联中使用whereHas查询的解决方案

嘿,针对你这个基于Product和Favorite多态关联的whereHas查询问题,我给你梳理清楚具体用法和示例,直接就能用!

首先先明确我们的关联关系:

  • Product模型通过favorites()方法和Favorite建立morphMany关联(一个Product可以被多次收藏)
  • Favorite模型通过favoritable()方法实现morphTo关联(收藏可以指向不同类型的模型,这里是Product)

下面分两种常见场景给你示例:

场景1:从Product出发,查询满足自身条件且关联收藏记录的商品

比如你要搜索名称包含$q的商品,并且这些商品被特定用户(比如ID=1)收藏过,代码可以这么写:

$q = $param['q'];
$query = Product::query()
    // 先过滤Product自身的条件:名称包含$q
    ->where('name', 'like', "%{$q}%")
    // 关联查询收藏记录,限定收藏者是用户ID=1
    ->whereHas('favorites', function ($subQuery) {
        $subQuery->where('user_id', 1);
    })
    ->get();

这里要注意:因为我们是从Product模型调用whereHas('favorites'),Eloquent会自动帮我们处理多态关联的匹配条件(即favoritable_type = Product::class和favoritable_id = products.id),不需要手动写这些!

如果要查询没有被任何用户收藏的商品,只需要把whereHas换成whereDoesntHave即可,用法完全一致。

进阶:查询收藏次数超过N次的商品

如果想找被收藏超过5次,且描述包含$q的商品,可以利用whereHas的第三个参数来做统计:

$q = $param['q'];
$query = Product::query()
    ->where('description', 'like', "%{$q}%")
    // 第三个参数是比较运算符,第四个是数值,这里表示关联的收藏记录数>5
    ->whereHas('favorites', function ($subQuery) {
        // 这里可以加额外的收藏记录条件,比如只算近30天的收藏
        $subQuery->where('created_at', '>=', now()->subDays(30));
    }, '>', 5)
    ->get();

场景2:从Favorite出发,查询关联的Product满足特定条件

比如你要找用户ID=1收藏的所有商品,且商品名称包含$q,可以这么写:

$q = $param['q'];
$query = Favorite::query()
    ->where('user_id', 1)
    // 关联查询favoritable(这里限定是Product类型),并过滤商品名称
    ->whereMorphTo('favoritable', Product::class, function ($subQuery) use ($q) {
        $subQuery->where('name', 'like', "%{$q}%");
    })
    ->with('favoritable') // 预加载关联的Product,避免N+1查询
    ->get();

这里用whereMorphTo可以更简洁地限定多态关联的类型,替代手动写where('favoritable_type', Product::class)的写法,代码更清晰。


内容的提问来源于stack exchange,提问作者moses toh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:47:42