Laravel 5.4中如何基于关联子表字段排序关联数据?
问题
现有三层关联关系(Trial -> Subject -> Reaction -> Account),当前控制器查询代码如下:
Trial::with('subjects')->where('source_id', $sourceId)->get()->toArray()
需要按照subject.reactions关联的accounts表的nb_followers字段对subject.reactions进行降序排序。之前尝试在关联中使用orderBy仅对Account排序,并未实现对Reaction的排序,且必须保留现有关联结构来维持所需数据结构。
相关模型代码如下:
Trial模型
class Trial extends Model { use HasFactory; public $table = 'trials'; public function subjects() { return $this->hasMany(Subject::class, 'trial_id')->with(['reactions', 'news'])->withCount('reactions'); } }
Subject模型
class Subject extends Model { use HasFactory; public $table = 'subjects'; public function reactions() { return $this->hasMany(Reaction::class, 'subject_id', 'id')->with(['accounts' => function ($q) {$q->orderBy('nb_followers', 'DESC');}])->where('twitter_error', 0)->where('active', 1)->orderby('key_reaction', 'DESC'); } public function news() { return $this->hasone(News::class, 'id', 'news_item_id'); } }
Reaction模型
class Reaction extends Model { use HasFactory; public $table = 'reactions'; public function accounts() { return $this->belongsTo(Account::class, 'account_id', 'id')->where('name', '!=', ''); } }
解决方案
要实现基于关联Account表的nb_followers字段对Reaction排序,需要在Reaction的关联查询中join关联的accounts表,直接基于该表字段排序,而非仅在预加载Account时排序。
修改Subject模型中的reactions关联方法:
public function reactions() { return $this->hasMany(Reaction::class, 'subject_id', 'id') ->with(['accounts' => function ($q) { $q->where('name', '!=', ''); }]) ->where('twitter_error', 0) ->where('active', 1) // 关联accounts表,建立关联条件 ->join('accounts', 'reactions.account_id', '=', 'accounts.id') // 基于accounts.nb_followers降序排序 ->orderBy('accounts.nb_followers', 'DESC') // 指定查询reactions表所有字段,避免join后字段覆盖 ->select('reactions.*'); }
补充说明
- 必须添加
select('reactions.*'),否则join操作可能导致reactions表的字段被accounts表同名字段覆盖; - 若需保留原有的
key_reaction排序规则,可调整排序顺序:
->orderBy('accounts.nb_followers', 'DESC') ->orderBy('reactions.key_reaction', 'DESC')
内容的提问来源于stack exchange,提问作者Bhimani Rutvik
相关产品推荐
相关产品推荐

