![](/img/trans.png)
[英]Use order by in pivot table data in Laravel's Eloquent ORM
[英]How to order by pivot table data in Laravel's Eloquent ORM
在我的數據庫中,我有:
tops
表posts
表tops_has_posts
表。 當我在tops
表上檢索 top 時,我還會檢索與 top 相關的posts
。 但是,如果我想按特定順序檢索這些帖子怎么辦? 所以我在我的 pivot 表中添加了一個range
字段tops_has_posts
我嘗試使用 Eloquent 按結果排序,但它不起作用。
我試試這個:
$top->articles()->whereHas('articles', function($q) {
$q->orderBy('range', 'ASC');
})->get()->toArray();
和這個:
$top->articles()->orderBy('range', 'ASC')->get()->toArray();
兩者都是絕望的嘗試。
先感謝您。
有兩種方法 - 一種是指定table.field
,另pivot_field
是使用withPivot('field')
別名pivot_field
如果您使用withPivot('field')
:
// if you use withPivot
public function articles()
{
return $this->belongsToMany('Article', 'tops_has_posts')->withPivot('range');
}
// then: (with not whereHas)
$top = Top::with(['articles' => function ($q) {
$q->orderBy('pivot_range', 'asc');
}])->first(); // or get() or whatever
這會起作用,因為withPivot
將pivot_field_name
提供的所有字段別名為pivot_field_name
。
現在,通用解決方案:
$top = Top::with(['articles' => function ($q) {
$q->orderBy('tops_has_posts.range', 'asc');
}])->first(); // or get() or whatever
// or:
$top = Top::first();
$articles = $top->articles()->orderBy('tops_has_posts.range', 'asc')->get();
這將對相關查詢進行排序。
注意:不要以這種方式命名事物,這會讓您的生活變得艱難。 posts
不一定是articles
,我會使用一個或另一個名稱,除非確實需要這樣做。
在 Laravel 5.6+(不確定舊版本)中,使用這個很方便:
public function articles()
{
return $this->belongsToMany('Article', 'tops_has_posts')->withPivot('range')->orderBy('tops_has_posts.range');
}
在這種情況下,每當您調用articles
,它們都會按range
屬性自動排序。
在Laravel 5.4我有以下關系,在正常工作Set
模型, belongsToMany
的Job
模式:
public function jobs()
{
return $this->belongsToMany(Job::class, 'eqtype_jobs')
->withPivot(['created_at','updated_at','id'])
->orderBy('pivot_created_at','desc');
}
上述關系返回指定Set
已按數據透視表 ( eqtype_jobs
) 字段created_at
DESC 排序的所有jobs
。
$set->jobs()->paginate(20)
的 SQL 打印輸出如下所示:
select
`jobs`.*, `eqtype_jobs`.`set_id` as `pivot_set_id`,
`eqtype_jobs`.`job_id` as `pivot_job_id`,
`eqtype_jobs`.`created_at` as `pivot_created_at`,
`eqtype_jobs`.`updated_at` as `pivot_updated_at`,
`eqtype_jobs`.`id` as `pivot_id`
from `jobs`
inner join `eqtype_jobs` on `jobs`.`id` = `eqtype_jobs`.`job_id`
where `eqtype_jobs`.`set_id` = 56
order by `pivot_created_at` desc
limit 20
offset 0
對於Laravel 8.17.2+,您可以使用::orderByPivot()
。
在你的刀片中試試這個:
$top->articles()->orderBy('pivot_range','asc')->get();
如果打印出belongsToMany
關系的SQL 查詢,你會發現數據透視表的列名使用了pivot_
前綴作為新的別名。
例如,數據透視表中的created_at
、 updated_at
有pivot_created_at
、 pivot_updated_at
別名。 所以orderBy
方法應該使用這些別名。
這是一個如何做到這一點的示例。
class User {
...
public function posts(): BelongsToMany {
return $this->belongsToMany(
Post::class,
'post_user',
'user_id',
'post_id')
->withTimestamps()
->latest('pivot_created_at');
}
...
}
如果您願意,您可以使用orderBy
而不是使用latest
方法。 在上面的例子中, post_user
是數據透視表,你可以看到排序的列名現在是pivot_created_at
或pivot_updated_at
。
你可以使用這個:
public function keywords() {
return $this->morphToMany(\App\Models\Keyword::class, "keywordable")->withPivot('order');
}
public function getKeywordOrderAttribute() {
return $this->keywords()->first()->pivot->order;
}
和 append 關鍵字 attribiute 到 model 后得到並使用 sortby
$courses->get()->append('keyword_order')->sortBy('keyword_order');
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.