Laravel:为Eloquent集合添加‘lowest’属性
实现自定义标记最低价报价的方案
嘿,这个需求其实很好解决,我给你几个不同场景下的实现方案,你可以根据自己的业务需求来选:
方案一:分页后标记当前页的第一条(适合唯一最低价场景)
因为你已经用orderBy('price', 'ASC')把报价按价格升序排列了,所以当前分页结果里的第一条自然就是最低价。我们可以直接遍历集合,给第一条加上is_lowest标记:
$offers = Offer::with('user:id,fname', 'review') ->where('isbn', $isbn) ->where('match_id', null) ->orderBy('price', 'ASC') ->paginate(5); // 给报价集合添加自定义字段 $offers->getCollection()->transform(function ($offer) use ($offers) { // 比较当前offer的id和集合中第一个元素的id,标记最低价 $offer->is_lowest = $offer->id === $offers->first()->id; return $offer; });
这个方法简单直接,缺点是如果有多个报价价格相同且都是最低价,只会标记第一条。
方案二:标记当前页所有同最低价的报价
如果你的业务允许多个报价共享最低价,我们可以先拿到当前页的最低价格,再给所有价格等于这个值的报价标记:
$offers = Offer::with('user:id,fname', 'review') ->where('isbn', $isbn) ->where('match_id', null) ->orderBy('price', 'ASC') ->paginate(5); // 先获取当前页的最低价格(注意处理集合为空的情况) $lowestPrice = $offers->isNotEmpty() ? $offers->first()->price : null; $offers->getCollection()->transform(function ($offer) use ($lowestPrice) { $offer->is_lowest = $lowestPrice !== null && $offer->price === $lowestPrice; return $offer; });
这样当前页里所有价格等于最低价的都会被标记为is_lowest: true。
方案三:数据库层面直接标记(全局最低价)
如果需要标记的是所有符合查询条件(isbn匹配且match_id为null)中的最低价,而不只是当前分页的,那可以用数据库子查询直接在查询时生成is_lowest字段:
$offers = Offer::with('user:id,fname', 'review') ->select('offers.*', DB::raw('(price = (SELECT MIN(price) FROM offers WHERE isbn = ? AND match_id IS NULL)) AS is_lowest'), [$isbn]) ->where('isbn', $isbn) ->where('match_id', null) ->orderBy('price', 'ASC') ->paginate(5);
这个方法的优势是在数据库层面完成计算,不用PHP再处理集合,而且不管当前分页是哪一页,只要报价的价格等于全局最低价,都会被标记。需要注意子查询的条件要和主查询完全一致,避免出现错误的结果。
内容的提问来源于stack exchange,提问作者Oussama Fadlaoui
相关产品推荐
相关产品推荐

