簡體   English   中英

Laravel的Eloquent ORM中如何通過pivot表數據進行排序

[英]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

這會起作用,因為withPivotpivot_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模型, belongsToManyJob模式:

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()

https://github.com/laravel/framework/releases/tag/v8.17.2

在你的刀片中試試這個:

$top->articles()->orderBy('pivot_range','asc')->get();

如果打印出belongsToMany關系的SQL 查詢,你會發現數據透視表的列名使用了pivot_前綴作為新的別名。

例如,數據透視表中的created_atupdated_atpivot_created_atpivot_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_atpivot_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM