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分頁