Laravel 8.x关联问题:在HasOne中通过HasMany获取最高出价
Laravel HasOne关联实现:获取已审核的最高出价
我想在Laravel的HasOne关联里复用HasMany关联的筛选逻辑,现有Auction和Bid模型代码如下:
class Auction extends Model { //... public function bids(): HasMany { return $this->hasMany(Bid::class, 'auction_id'); } public function approvedBids(): HasMany { return $this->bids()->approved(); } public function topBids(): HasMany { return $this->approvedBids()->orderByDesc('price')->take(10); } public function topBid(): HasOne { //return $this->topBids()->firstOfMany(); // 无法正常工作 //return $this->hasOne(Bid::class, 'auction_id')->ofMany('price','max')->approved(); // 无法正常工作 //return $this->hasOne(Bid::class, 'auction_id')->approved()->ofMany('price','max'); // 无法正常工作 //return $this->hasOne(Bid::class, 'auction_id')->ofMany('price', 'max'); // 可运行但不符合预期 } }
class Bid extends Model { //... public function scopeApproved(Builder $query): Builder { return $query->where('state', BidState::STATE_APPROVED); } //... }
我需要实现topBid()关联,从已审核的出价中获取最高出价的单条记录,但尝试的几种写法均无法正常满足需求。
可行解决方案
方案一:直接整合筛选与ofMany关联
先调用approved作用域过滤已审核出价,再通过ofMany指定取价格最高的记录:
public function topBid(): HasOne { return $this->hasOne(Bid::class, 'auction_id') ->approved() ->ofMany( ['price' => 'max'], // 可选:同价时取最新创建的出价 fn($query) => $query->orderBy('created_at', 'desc') ); }
注意顺序:必须先调用筛选作用域,再使用ofMany。如果反过来,筛选条件会被加到外层查询而非聚合子查询中,导致无法正确过滤已审核出价。
方案二:复用已有approvedBids关联逻辑
如果想完全复用approvedBids()的筛选规则,可通过mergeConstraintsFrom合并查询条件:
public function topBid(): HasOne { // 获取approvedBids的查询约束 $approvedQuery = $this->approvedBids()->getQuery(); return $this->hasOne(Bid::class, 'auction_id') ->mergeConstraintsFrom($approvedQuery) ->ofMany('price', 'max'); }
这种方式能确保topBid()和approvedBids()使用完全一致的筛选逻辑,后续修改approvedBids时无需同步修改topBid。
原有写法失败原因
$this->topBids()->firstOfMany():topBids()返回的是HasMany实例,firstOfMany只能用于HasOne关联,类型不匹配导致报错。ofMany放在approved()之前:ofMany会生成聚合子查询,此时调用approved()会把筛选条件加到外层查询,无法过滤聚合子查询中的数据,导致结果包含未审核出价。- 仅用
ofMany('price', 'max'):缺少approved筛选,会返回所有出价中的最高价,不符合需求。
内容的提问来源于stack exchange,提问作者Pejman
相关产品推荐
相关产品推荐

