laravel5.5のCRUDで、テーブルヘッダをクリックしたら並び替え&CSV出力をしてくれる実装をしてみた。
laravelではCRUDそのものは簡単に作れるけど、実用的な並び替え&CSV出力のサンプルがないので書いてみた
1, こんな感じで、テーブルヘッダの日付をクリックしたら、submitで検索するようにする。
1 2 3 4 5 6 7 8 9 10 |
<form method="GET" action="" accept-charset="UTF-8" id="search_form"> キーワード: <input name="search_keyword" type="text"> <button type='submit' name='action' class='btn' value='search'>検索</button> <button type='button' name='action' id='csv_button' class='btn' value='csv'>CSV</button> </form> <th style="cursor : pointer;" class="submit_button" data-action="search" data-column="created_at">日時</th> <th style="cursor : pointer;" class="submit_button" data-action="search" data-column="upload">アップロードファイル数</th> |
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 |
<script> $(function(){ // テーブルヘッダをクリックされたら、 $('.submit_button').on('click', function(){ // submitするフォームを取得 var form = $('#search_form'); //URLからソート順(asc, desc)を取得して、逆にする var sort_order = ''; var match = location.search.match(/sort_order=(.*?)(&|$)/); if(match) { sort_order = decodeURIComponent(match[1]); } if(sort_order == 'asc'){ sort_order = 'desc'; }else if(sort_order == 'desc'){ sort_order = 'asc'; }else{ sort_order = 'asc'; } // controllerにカラム名とソート順(asc, desc)を投げる var column = $(this).data('column'); $('<input>').attr({ 'type': 'hidden', 'name': 'sort_kind', 'value': column }).appendTo(form); $('<input>').attr({ 'type': 'hidden', 'name': 'sort_order', 'value': sort_order }).appendTo(form); // 検索する form.submit(); }); }) </script> |
2, UserController & Users(モデル)に検索の記述を書く
UserController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public function index() { // GET引数を取得 $input = \Request::all(); $search_keyword = empty($input['search_keyword']) ? '' : $input['search_keyword']; $sord_kind = empty($input['sort_kind']) ? '' : $input['sort_kind']; $sort_order = empty($input['sort_order']) ? '' : $input['sort_order']; // 押されたボタンによって、処理の振り分け $pushed_button = empty($input['action']) ? '' : $input['action']; // 検索キーワードにより、チャットルーム検索(検索条件無しもあり) if($pushed_button == 'search' || $pushed_button == ''){ $reports = Report::search_chatroom($company_id, $search_keyword, $sord_kind, $sort_order); return view('company_admin.report.index', compact('reports','company_name', 'company_admin_name')); // CSV出力 }elseif($pushed_button == 'csv'){ return Report::csv_chatroom($company_id, $search_keyword, $sord_kind, $sort_order); } } |
Users(モデル)
画像掲示板で、画像を
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 |
// チャットルーム検索 public static function search($search_keyword, $sord_kind, $sort_order) { // 表示順のデフォルトは、日付降順(新しいチャットルームが上に来るようにする) $sord_kind = empty($sord_kind) ? 'created_at' : $sord_kind; $sort_order = empty($sort_order) ? 'desc' : $sort_order; $query = User::query(); // 検索キーワードが入っていたらwhere条件に追加 if(!empty($search_keyword)){ // Where句の A and (B or C)みたいな時には、クロージャーを使って表現する // クロージャー内で呼び出し元の関数を使いたい時は、use文を使う $query->where(function ($query) use ($search_keyword) { $query->Where('tag' , "like", "%". $search_keyword . "%") ->orWhere('nickname' , "like", "%". $search_keyword . "%") ->orWhere('email' , "like", "%". $search_keyword . "%"); }); } // 表示する順を決める。 // アップロードファイルはリレーション先(Posts)で保持しているので、単純にカラム名を指定してもエラーになる // 無名関数でupload_fileカラムがnullじゃないpostsレコード数をカウント(withCountを使う、has_postsがリレーション名で、_countで紐付いているリレーション数を返してくれるので、それでorder byする) if($sord_kind == 'upload_file'){ $query->withCount([ 'has_posts' => function ($query) { $query->whereNotNull('upload_file'); }])->orderBy('has_posts_count', $sort_order); }else{ $query->orderBy($sord_kind, $sort_order); } $users = $query->get(); return $users; } |
withCount(リレーション先のレコード数)は、laravel5.2で実装されたらしい。
https://readouble.com/laravel/5.5/ja/eloquent-relationships.html
3, CSV出力ボタンの実装
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 |
// CSVボタンをクリックされたら、 $('#csv_button').on('click', function(){ // submitするフォームを取得 var form = $('#search_form'); // CSVボタンが押された事を表す //form.attr('action', 'csv'); //URLからソートするカラムを取得 var sort_kind = ''; var match = location.search.match(/sort_kind=(.*?)(&|$)/); if(match) { sort_kind = decodeURIComponent(match[1]); } //URLからソート順を取得 var sort_order = ''; var match = location.search.match(/sort_order=(.*?)(&|$)/); if(match) { sort_order = decodeURIComponent(match[1]); } // controllerにカラム名とソート順(asc, desc)を投げる var column = $(this).data('column'); $('<input>').attr({ 'type': 'hidden', 'name': 'sort_kind', 'value': column }).appendTo(form); $('<input>').attr({ 'type': 'hidden', 'name': 'sort_order', 'value': sort_order }).appendTo(form); $('<input>').attr({ 'type': 'hidden', 'name': 'action', 'value': 'csv' }).appendTo(form); // 検索する form.submit(); }); |
CSV出力はライブラリを使ってもいいけど、単純なのでべた書き。
エクセルで開けるようにutf-8からsjis-winに文字コードを変換しておく
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 |
// CSV出力 public static function csv($search_keyword, $sord_kind, $sort_order) { // 画面の条件で再検索 $users = self::search($search_keyword, $sord_kind, $sort_order); // CSVヘッダ $output_csv = '"日時","ユーザー名", ....'. "\n"; foreach($users as $user){ $output_csv .= '"'. $user->created_at->format('Y/m/d H:i:s') .'","'. //日時 $user->name .'","'. //名前 $report->email; //email $output_csv .= "\"\n"; } //文字コード変換(utf-8 -> sjis-win) $csv = mb_convert_encoding(str_replace(PHP_EOL, "\r\n", $output_csv), 'sjis-win', 'UTF-8'); //CSVファイル名 $filename = "csv_" . date('Ymd').".csv"; $filename = mb_convert_encoding($filename, "SJIS", "auto"); //header $headers = array( 'Content-Type' => 'application/octet-stream', 'Content-Disposition' => 'attachment; filename="' . $filename . '"' ); // http response return \Response::make($csv, 200, $headers); } |