見出し画像

Larabelのcolumn-sortable使い方Tip

お疲れ様です。新人エンジニアのtelluruです。技術記事第一弾はLarabelの実装でお世話になったcolumn-sortableの使い方のメモを記します。

導入

まずはcomposerからcolumn-sortableをインストール。

    composer require kyslik/column-sortable

次にコンフィグファイルを追加。

php artisan vendor:publish --provider="Kyslik\ColumnSortable\ColumnSortableServiceProvider" --tag="config"

実装

基本的な使い方。

Model

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Kyslik\ColumnSortable\Sortable; //追加

class Staff extends Authenticatable
{
	use Sortable; //追加
	public $sortable = ['staff_name']; //ソート対象指定
}

Controller

class JobListController extends Controller
{
   public function index(Request $request)
   {
            $joblist = Staff::select([
               'staff.staff_id'
               'staff.staff_name'])
           ->sortable() //これを挟むだけ
           ->orderBy('staff.staff_id', 'desc')
           ->paginate(20);
    }

}

この時sortableを挟む位置はjoinの後、条件式(where)やソート(orderBy)の前に入れる。場所を間違えるとうまく動作してくれない。ソートのSQLを見るとsortableの位置にorderBy句を入れて再検索するようだ。

View

<th class="back" scope="col" style="white-space:nowrap;">
     @sortablelink('staff_name', '登録者') //追加
</th>

@sortablelink('取得カラム名','表示する名前')でソートリンクを作ってくれる。

//HTMLのすがた
<th class="back1" scope="col" style="white-space:nowrap;">
     <a href="http://localhost:3306/hoge/jobList?sort=staff_name&amp;direction=desc">登録者</a>
     <i class="fa fa-sort-asc"></i>
</th>

別名を付けたカラムでSorting

As句で名前を付けると基本の使い方ではカラムを認識してくれない。joinで別名を付けたテーブルを使用する場合も同様。なので別名をモデルに宣言する必要がある。宣言にはsortableの代わりにsortableAsを使う。


public $sortableAs = ['sm_name']; //staff_name as sm_name

joinしたテーブルのカラムでSorting

上記の別名カラムソートを使うとjoinした先のカラムにソートを付けることができる。

Model

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Kyslik\ColumnSortable\Sortable;
class Job extends Model
{

   use Sortable;
   public $sortable = ['job_id', 'job_name', 'job_kind', 'in_id', 'in_date'];
   public $sortableAs = ['sm_name'];

       public function staffNameSortable($query, $direction)
   {
       return $query->leftjoin('staff', 'job.in_id', 'staff.staff_id')
       ->orderBy('sm_name', $direction);
   }
}

結合される側のモデルに結合するjoin句とorderBy句、カラムの別名を記述する。例の場合JobテーブルにStaffテーブルを左結合するのでJob側のモデルにjoin句を記述することになる。join句とorderBy句は’(任意の英数字)Sortable’という名前でメソッドを作ればsortableをオーバーライドできるので、その中に記述。

Controller

$joblist = JobMaster::select([
   'job_id',
   'job_name',
   'job_kind',
   'in_id',
   'job.in_date',
   'sm.staff_name as sm_name'])
->leftjoin('staff as sm', 'job.in_id', 'sm.staff_id')
->sortable('sm_name')
->orderBy('job.job_id', 'desc')
->paginate(20);

sortableの中に配列で名前を変えたカラムを列挙する。複数ある場合は配列にする。
【2020/01/31追記】
上記をしなくてもソーティング機能は実装できる。上記をした場合初期表示でソートがかかる。

View

<th class="back1 " scope="col" style="white-space:nowrap;">
   @sortablelink('job_id', 'ID')
</th>
<th class="back1" scope="col" style="white-space:nowrap;">
   @sortablelink('job_name', 'ジョブ名')
</th>
<th class="back1" scope="col" style="white-space:nowrap;">
   @sortablelink('job_kind', '種別')
</th>
<th class="back1" scope="col" style="white-space:nowrap;">
   メモ
</th>
<th class="back1" scope="col" style="white-space:nowrap;">
   @sortablelink('sm_name', '登録者')
</th>
<th class="back1" scope="col" style="white-space:nowrap;">
   @sortablelink('in_date', '登録日時')
</th>

変えた名前でカラム指定する。

複雑なクエリのカラムをSorting

上記の応用を使用すると複雑なクエリを発行したときもソート機能を付けられる。

Model

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Kyslik\ColumnSortable\Sortable;
class OutList extends Model
{
    use Sortable;

   public $sortableAs = ['co_id', 'w_cnt', 'output_cnt', 'co_name','jm_id','jm_name'];

   public function companySortable($query, $direction)
   {
       return $query->orderBy('co_id', $direction);
   }
   public function wSortable($query, $direction)
   {
       return $query->orderBy('w_cnt', $direction);
   }
   public function companyNameSortable($query, $direction)
   {
       return $query->leftjoin('company as cm', 'out_list.company_id', 'cm.company_id')
       ->orderBy('co_name', $direction);
   }
   public function jobIdSortable($query, $direction)
   {
       return $query->leftjoin('job as jm', 'out_list.job_id', 'jm.job_id')
       ->orderBy('jm_id', $direction);
   }
   public function jobNameSortable($query, $direction)
   {
       return $query->leftjoin('job as jm', 'out_list.job_id', 'jm.job_id')
       ->orderBy('jm_name', $direction);
   }
}

Controller

$child_jobs = OutList::select(
   'otl.company_id as co_id',
   'cm.company_name as co_name',
   'jm.job_id as jm_id',
   'jm.job_name as jm_name',
)
->selectSub(OutList::selectRaw('count(*)')
   ->fromSub(OutList::select('member_id', 'company_id', 'job_id')
       ->where('parent_job_id', $parent_job_id)
       ->where('output_flg', 1)
       ->groupBy('member_id', 'company_id', 'job_id'), 'otl_s2')
   ->whereColumn('otl.company_id', 'otl_s2.company_id'), 'w_cnt')
->fromSub(OutList::select('member_id', 'company_id', 'job_id')
       ->where('parent_job_id', $parent_job_id), 'otl')
->leftjoin('job_master as jm', 'otl.job_id', 'jm.job_id')
->leftjoin('company as cm', 'otl.company_id', 'cm.company_id')
->sortable(['co_id', 'w_cnt', 'co_name', 'jm_id', 'jm_name'])
->groupby('jm.job_id') 
->paginate(20);

※distinctはLarabelのpagenationと相性が悪いらしく、totalが重複排除されずカウントされてしまうので代わりにgroupByを使用している。

View

<th class="back1" scope="col" style="white-space:nowrap;">
   @sortablelink('co_id', '企業ID')
</th>
<th class="back1" scope="col" style="white-space:nowrap;">
   @sortablelink('co_name', '企業名')
</th>
<th class="back1" scope="col" style="white-space:nowrap;">
   @sortablelink('w_cnt', '件数')
</th>
<th class="back1" scope="col" style="white-space:nowrap;">
   @sortablelink('jm_id', 'ジョブID')
</th>
<th class="back1" scope="col" style="white-space:nowrap;">
   @sortablelink('jm_name', 'ジョブ名')
</th>

こんな感じでCountしたカラムにソートを付けることもできる。


この記事が気に入ったらサポートをしてみませんか?