---
tags: PHP, Laravel, Backend
---
# Laravel 列排序以及分頁範例
## 安裝`kyslik/column-sortable`
==此包適用於Laravel 5/6/7/8==
### composer
`composer require kyslik/column-sortable`
### 手動安裝(laravel 5.5之前版本)
在`config/app.php`添加服務提供者
```php=
'providers' => [
App\Providers\RouteServiceProvider::class,
/*
* Third Party Service Providers...
*/
Kyslik\ColumnSortable\ColumnSortableServiceProvider::class,
],
```
### 發佈配置
`php artisan vendor:publish --provider="Kyslik\ColumnSortable\ColumnSortableServiceProvider" --tag="config"`
## 用法
### 在Model中使用
在你想使用排序的`model`使用`Sortable`
,將要使用排序的欄位定義在`$sortable`陣列當中
```php=
<?php
namespace App\Models;
use Kyslik\ColumnSortable\Sortable;
class Product extends Model
{
use Sortable;
public $sortable = ['id', 'name', 'created_at', 'updated_at'];
}
```
提醒: `Sortable trait` 為模型添加了 `Sortable` 範圍,因此您可以將其與分頁一起使用。
### 在Blade中
在`laravel Blade`中使用`@sortablelink()`
```php=
@sortablelink('column', 'Title', ['parameter' => 'smile'], ['rel' => 'nofollow'])
```
1. 第一個參數: 要排序的欄位名稱
1. 第二個參數: 在前端要顯示的名稱
1. 第三個參數: Http GET默認查詢字符串參數`?parameter=smile`
1. 第四個參數: 可以在第 4 個參數中使用自定義 URL 作為 'href' 屬性,查詢字符串將附加到它。此範例會將`rel="nofollow"`附加在`a tag`上
可以省略第二,第三,第四個參數
官方提供可能使用範例與情境
```php=
@sortablelink('name')
@sortablelink('name', 'Username')
@sortablelink('address', trans('fields.address'), ['filter' => 'active, visible'])
@sortablelink('address', trans('fields.address'), ['filter' => 'active, visible'], ['class' => 'btn btn-block', 'rel' => 'nofollow', 'href' => route('my.custom.route')])
```
:::info
可以設置應用於標題(第二個參數)的默認格式功能,默認情況下設置為[`ucfirst`](https://www.php.net/manual/en/function.ucfirst.php)。
:::
### 簡單的配置
`config > columnsortable.php`
表格中有為可排序連結區分類型(數字、數量和 `alpha`),並為每種類型應用不同的類,可以自行新增或修改對應的`icon`
```php=
'columns' => [
'numeric' => [
'rows' => ['created_at', 'updated_at', 'level', 'id'],
'class' => 'fa fa-sort-numeric'
],
'amount' => [
'rows' => ['price'],
'class' => 'fa fa-sort-amount'
],
'alpha' => [
'rows' => ['name', 'description', 'email', 'slug'],
'class' => 'fa fa-sort-alpha',
],
],
```
### Font Awesome(預設的字體類)
安裝[Font-Awesome](https://fontawesome.com/versions)
#### Font Awesome 5
更改正序倒序的`icon`,將配置文件中的後綴類分別從 `-asc/-desc (FA 4)` 更改為 `-up/-down (FA 5)`。
```php=
/* this is FA 5 compatible.
suffix class that is appended when ascending direction is applied */
'asc_suffix' => '-up',
/* suffix class that is appended when descending direction is applied */
'desc_suffix' => '-down',
```
:::info
如未發布配置文件請參考[發佈配置](#發佈配置)
:::
## 完整範例
### Routes
`Route::get('/products', 'App\Http\Controllers\ProductController@index');`
### Controller
```php=
public function index()
{
$products = Product::sortable()->paginate(2);
return view('products', compact('products'));
}
```
### View(包括分頁)
```blade=
@sortablelink('id', '產品ID')
@sortablelink('name', '名稱')
@sortablelink('created_at', '創建日期')
@foreach ($products as $product)
{{ $product->id }}
{{ $product->name }}
{{ $product->created_at }}
@endforeach
{{-- 此為分頁 --}}
{!! $users->appends(\Request::except('page'))->render() !!}
```
:::warning
注意:Blade 識別指令的能力取決於指令本身之前是否有空格 `<tr> @sortablelink('Name')`
:::
### 展示

## HasOne / BelongsTo關聯排序
### 定義hasOne關聯
要使用關聯排序,需要先在model定義`hasOne()`關聯
```php=
/**
* Get the user_detail record associated with the user.
*/
public function detail()
{
return $this->hasOne(App\UserDetail::class);
}
```
### 定義BelongsTo關聯
:::info
如果有自引用模型(如評論、類別等);父表將使用 parent_ 字符串作為別名,有關更多信息,請參閱[issue #60](https://github.com/Kyslik/column-sortable/issues/60)。
:::
```php=
/**
* Get the user that owns the phone.
*/
public function user()
{
return $this->belongsTo(App\User::class, parent_id, user_id);
}
```
### 定義`$sortable` 陣列
在兩個模型中定義 $sortable 數組(否則,package使用 Scheme::hasColumn() 這是一個額外的數據庫查詢)
User Model
`public $sortable = ['id', 'name', 'email', 'created_at', 'updated_at'];`
UserDetail Model
`public $sortable = ['address', 'phone_number'];`
### Blade的關聯排序
```php=
@sortablelink('detail.phone_number', 'phone')
@sortablelink('user.name', 'name')
```
:::info
這裡使用的是在模型中定義的關係“名稱”(方法)而不是使用表名稱。
:::
:::warning
不要同時使用兩個不同關係的組合,你會得到關係未定義的錯誤
:::
預設使用`.`做為關聯預設符號,如果`.`不是你想要的可以到配置文件中修改
```php=
'uri_relation_column_separator' => '.'
```
## ColumnSortable overriding (advanced)
可以覆蓋 ColumnSortable 關係功能,基本上您可以編寫自己的連接/查詢並手動應用 orderBy()
範例:
```php=
class User extends Model
{
use Sortable;
public $sortable = ['name'];
...
public function addressSortable($query, $direction)
{
return $query->join('user_details', 'users.id', '=', 'user_details.user_id')
->orderBy('address', $direction)
->select('users.*');
}
...
```
`controller`中一樣使用`$users = $user->sortable()->paginate(10);`
在`view`中`@sortablelink('address')`
## 捕捉異常try catch
`ColumnSortableException`使用三個代碼`(0、1、2)`拋出自定義異常 。
**代碼 0** 表示`explode()` 無法將URI 參數“排序”分解為兩個值。例如:`sort=detail..phone_number` - 生成大小為 3 的數組,這會導致package 拋出代碼為 0 的異常。
**代碼 1** 表示 `$query->getRelation()` 方法失敗,這意味著關聯名稱無效(不存在,未在模型中聲明)。
**代碼 2** 表示通過排序參數提供的關係不是 hasOne 的實例。
捕捉異常範例:
```php=
try {
$users = $user->with('detail')->sortable(['detail.phone_number'])->paginate(5);
} catch (\Kyslik\ColumnSortable\Exceptions\ColumnSortableException $e) {
dd($e);
}
```
[column-sortable](https://github.com/Kyslik/column-sortable)