Laravel order by relationship column with pagination
Laravel的Eloquent中,orderBy column並無法提供relationship table column,因此通常需要使用relationship表單中的欄位來排序時我們會使用sortBy 或者sortByDESC來處理,但是如果今天遇上了分頁,我們將無法透過pagination的結果來做sort
概念
概念上來說,如果遇到需要透過relationship column來做排序的狀況我們先透過get()將資料取出,再經由sortBy或者sortByDESC來排序,這時候會得到一個排序完成的collection,最後再將這個collection做pagination即可
因此本篇的重點將會是如何將collection做pagination
參考資料
https://gist.github.com/simonhamp/549e8821946e2c40a617c85d2cf5af5e
https://stackoverflow.com/questions/72287090/how-to-paginate-laravel-collection
pagination注入
AppServiceProvider.php boot function中加入以下,讓collection支援pagination
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/** * Paginate a standard Laravel Collection. * * @param int $perPage * @param int $total * @param int $page * @param string $pageName * @return array */ Collection::macro('paginate', function($perPage, $total = null, $page = null, $pageName = 'page') { $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName); return new LengthAwarePaginator( $this->forPage($page, $perPage), $total ?: $this->count(), $perPage, $page, [ 'path' => LengthAwarePaginator::resolveCurrentPath(), 'pageName' => $pageName, ] ); }); |
因此AppServiceProvider.php將會是以下的內容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Collection; use Illuminate\Pagination\LengthAwarePaginator; class AppServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { // } /** * Bootstrap any application services. * * @return void */ public function boot() { // /** * Paginate a standard Laravel Collection. * * @param int $perPage * @param int $total * @param int $page * @param string $pageName * @return array */ Collection::macro('paginate', function($perPage, $total = null, $page = null, $pageName = 'page') { $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName); return new LengthAwarePaginator( $this->forPage($page, $perPage), $total ?: $this->count(), $perPage, $page, [ 'path' => LengthAwarePaginator::resolveCurrentPath(), 'pageName' => $pageName, ] ); }); } } |
範例
接著我們來看一下範例
1 2 3 |
$articles = Article::with('writer')->get()->sortBy(function($query){ return $query->writer->name; })->pagination(15); |
先將Article中的資料用get()取出後透過sortBy依照writer relationship中的name來排序,最後得到collection再透過上一步驟增加的pagination function來替collection分頁