n_osennij's avatar

Order by related table field and paginate

I have Articles -> Parts tabels

Article.php model

public function scopePublished($query)
{
    $query->where('posted_at', '<=', Carbon::now());
}

public function scopeNewest($query)
{
    $query->orderBy('posted_at', 'desc');
}

public function parts()
{
    return $this->hasMany('App\Part');
}

Part.php model

public function article()
{
    return $this->belongsTo('App\Article');
}

Article and Part have posted_at column. Article can have many Part or can have zero.

I try to get all Articles with all its Parts and sort it by posted_at desc from now and paginate it.

For example Articles

id - posted_at
1 - 2018-01-01
2 - 2018-02-01
3 - 2018-03-01

Parts

id - article_id - posted_at
1 - 1 - 2018-04-01
2 - 1 - 2018-04-05

So order of Articles must by next (because Post 1 have newest Part, so it must by on top)

1 - 2018-01-01
3 - 2018-03-01
2 - 2018-02-01

I try to do next

$articles = Article::with('parts')
    ->published()
    ->newest()
    ->paginate(2);

$articles = $news->sortByDesc(function ($item, $key) {
    if (count($item->parts) > 0){
        return $item->parts->last()->posted_at;
    }
    return  $item->posted_at;
});

But after sortByDesc() I can't show on page pagination buttons with {{ $articles ->links() }}. Pagination works. But there are no buttons. What can I do?

0 likes
2 replies
Cronix's avatar

I think you need to do the sorting before you call paginate().

FYI, Eloquent has a ->latest() method that you could use instead of your scopeNewest() scope. It defaults to the created_at field unless you specify one, like ->latest('posted_at')

n_osennij's avatar

@Cronix but how can I do something before paginate? I san use paginate() only with Eloquent query.

About ->latest('posted_at') - it is good idea. Thanks. I modified my code

$news = Article::with('parts')
        ->published()
        ->latest('posted_at')
        ->get();

Please or to participate in this conversation.