Laravel查询构建器嵌套Where子句:产品筛选功能开发困惑
解决Laravel嵌套查询实现特定搜索筛选的问题
我明白你要实现的是筛选出两类产品:一类是在sales_agreement表中有记录且financing字段不为空的产品,另一类是完全没有销售协议记录的产品。下面我来帮你完成这个查询逻辑。
首先明确核心筛选逻辑:
- 保留:有销售协议且
financing非空的产品 - 保留:无任何销售协议的产品
- 排除:有销售协议但
financing为空的产品(比如示例中的motor)
方法一:Eloquent关联查询(推荐,符合Laravel ORM风格)
先确保你的Product模型已经定义好和SalesAgreement的关联关系:
// app/Models/Product.php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; class Product extends Model { public function salesAgreements(): HasMany { return $this->hasMany(SalesAgreement::class, 'product_id'); } }
然后通过whereHas和whereDoesntHave组合条件查询:
$filteredProducts = Product::select('id as product_id', 'product_name') // 筛选有销售协议且financing非空的产品 ->whereHas('salesAgreements', function ($query) { // 同时处理NULL和空字符串两种情况 $query->whereNotNull('financing') ->where('financing', '<>', ''); }) // 或者筛选没有任何销售协议的产品 ->orWhereDoesntHave('salesAgreements') ->get();
方法二:查询构建器左连接(原生SQL风格)
如果你更习惯用原生查询的写法,也可以用左连接实现:
use Illuminate\Support\Facades\DB; $filteredProducts = DB::table('products') ->select('products.id as product_id', 'products.product_name') ->leftJoin('sales_agreement', 'products.id', '=', 'sales_agreement.product_id') ->where(function ($query) { // 条件1:没有关联的销售协议记录 $query->whereNull('sales_agreement.id') // 条件2:有销售协议但financing非空 ->orWhere(function ($subQuery) { $subQuery->whereNotNull('sales_agreement.financing') ->where('sales_agreement.financing', '<>', ''); }); }) ->distinct() // 避免同一产品有多个符合条件的销售协议时重复返回 ->get();
结果验证
执行上述任意一段代码后,返回的结果都会和你期望的一致:
| product_id | product_name |
|---|---|
| 2 | jeep |
| 1 | car |
| 4 | bicycle |
注意:如果你的financing字段默认是NULL而不是空字符串,可以去掉where('financing', '<>', '')这一行,只保留whereNotNull('financing')即可。
内容的提问来源于stack exchange,提问作者jerome
相关产品推荐
相关产品推荐

