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

使用Eloquent构建葡萄酒类型筛选复杂查询的问题

解决Laravel Eloquent查询葡萄酒类型的问题

先确认模型关联是否正确

首先必须确保三个模型的关联关系定义准确,否则whereHas方法会失效:

  • Wine模型:
class Wine extends Model
{
    public function variety()
    {
        return $this->belongsTo(Variety::class);
    }
}
  • Variety模型:
class Variety extends Model
{
    public function wines()
    {
        return $this->hasMany(Wine::class);
    }

    public function type()
    {
        return $this->belongsTo(Type::class);
    }
}
  • Type模型:
class Type extends Model
{
    public function varieties()
    {
        return $this->hasMany(Variety::class);
    }
}

修复你的whereHas查询

你之前的代码问题在于嵌套关联的写法错误,whereHas需要通过闭包逐层嵌套检查关联:

$redWines = Wine::whereHas('variety', function ($query) {
    $query->whereHas('type', function ($subQuery) {
        $subQuery->where('id', 1);
    });
})
// 在这里追加其他筛选条件,比如库存、标签
->where('stock', '>', 0)
->whereHas('tags', function ($tagQuery) {
    $tagQuery->where('name', 'like', '%organic%');
})
->get();

更高效的替代方案:使用关联查询(Join)

如果查询涉及多个筛选条件,用join可以减少数据库查询次数,性能更优:

$redWines = Wine::join('varieties', 'wines.variety_id', '=', 'varieties.id')
    ->join('types', 'varieties.type_id', '=', 'types.id')
    ->where('types.id', 1)
    // 添加其他筛选条件
    ->where('wines.stock', '>', 0)
    ->select('wines.*') // 仅选择葡萄酒表字段,避免字段冲突
    ->get();

可复用的查询范围封装

如果需要频繁按类型筛选,可以在Wine模型中封装查询范围:

public function scopeOfType($query, $typeId)
{
    return $query->whereHas('variety', function ($q) use ($typeId) {
        $q->whereHas('type', function ($sq) use ($typeId) {
            $sq->where('id', $typeId);
        });
    });
}

调用时会更简洁:

$redWines = Wine::ofType(1)->where('stock', '>', 0)->get();

内容的提问来源于stack exchange,提问作者Marko Stojanovic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 14:40:38