九保すこひ@フリーランスエンジニア|累計300万PVのブログ運営中
さてさて、最近はプログラムを使った様々な「企画」のような記事を重点的に公開してきていましたが、たまにはそういったものとは違った「基本的なプログラム」も記事にしたいなということで、いろいろとアイデアを出している最中です。
そして、その中で以前から「気になっていたものの忘れてしまっていたもの」に気がつきました。
それは、
LaravelとDataTable.jsをAjaxを使って連携させること
です。
DataTable.jsというのは、通常のテーブルに検索やソート、ページリンクなどを一括で提供してくれる有名なjQuery
のプラグインのことで、Ajax
を使う場合、データ取得は以下2つのパターンがあります。
- 最初に全データを取得しておいて、あとは全て “DataTable” にまかせる
- ページが切り替わるごとにサーバーサイド(PHPなど)からデータを取得する
もちろんデータが少なければ1番のシンプルな方法で問題はないのですが、これが何千、何万件となってくるとページ表示が目に見えて遅くなったりもします😫
そこで登場するのが2番なのですが、この場合だと検索やソートなどは自前で実装する必要があります。
そこで!
今回は、この「ちょっと複雑だけど快適」な2番めの方法でLaravel
とDataTable
を連携させる方法をご紹介します。
ぜひ、皆さんのお役に立てると嬉しいです😊✨
開発環境: Laravel 5.8、jQuery 3.4、DataTable 1.10
目次
ルートをつくる
まずはじめに、ブラウザからアクセスするためのルートを作ります。routes/web.php
に以下を追加してください。
Route::get('datatable', 'DataTableController@index'); Route::get('datatable/ajax', 'DataTableController@ajax');
上のルートが実際に目にするページで、下のものはAjaxでデータを取得するものになります。
モデル、マイグレーション、テストデータをつくる
では、DataTable
で表示するためのデータを用意するためにモデル、マイグレーション、テストデータが必要になりますが、こちらは以前投稿した記事の内容と同じですのでそちらを参照してください。
コントローラーをつくる
また、先ほどルートで指定したコントローラーは存在していないので、以下のコマンドで作成します。
php artisan make:controller DataTableController
すると、app/Http/Controllers/DataTableController.php
が作成されるので中身を以下のように変更します。
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class DataTableController extends Controller { public function index() { return view('datatable'); } public function ajax(Request $request) { $query = \App\Product::query(); // 検索 if($request->filled('search.value')) { $search_value = trim( mb_convert_kana($request->input('search.value'), 's') ); $keywords = explode(' ', $search_value); foreach($keywords as $keyword) { $query->where('name', 'LIKE', '%'. $keyword .'%'); } } // ソート if($request->filled('order.0.column')) { $order_column_index = $request->input('order.0.column'); $order_column = $request->input('columns.'. $order_column_index .'.data'); $order_direction = $request->input('order.0.dir'); $query->orderBy($order_column, $order_direction); } $start = intval($request->start); $per_page = intval($request->length); $columns = [ 'code', 'name', 'created_at' ]; $current_page = ($per_page === 0) ? 1 : $start / $per_page + 1; return $query->paginate($per_page, $columns, '', $current_page); } }
【追記:2019.8.27】mb_convert_kana()
の引数が足りなかったので追加しました。すみません😫
ここで重要なのが、ajax()
です。
このメソッドはAjaxを通してDataTable
のデータを用意するものですが、記事の冒頭でも書いたとおり、「検索」や「ソート」は自前で実装する必要があります。
そのため、どちらもDataTable
が送信してくるあるデータが存在していれば、検索、もしくはソートを実行するコードを用意しています。(検索はAnd検索になっていますので、お好みで改変してください)
また、DataTable
はパラメータとして現在のページ番号を送信してくれませんので、こちらもstart
とlength
を使って自前で計算する必要があります。
なお、このコードの中では、パラメータ名の変更をしてないことに注目してください。本来はDataTable
が指定するパラメータでデータを用意すべきですが、今回はDataTable
側でパラメータを加工して実装します。
ビューをつくる
では、最後にビューをつくります。
resources/views/datatable.blade.php
にファイルを作成して、中身を以下のようにしてください。
※ jQuery、DataTableはCDNを使って呼び出しています。
<html> <head> <link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet"> </head> <body> <table id="table"></table> <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script> <script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script> <script> $(() => { $('#table').DataTable({ searching: true, // 検索する?? ordering: true, // 並べ替えする?? lengthChange: true, // ページごとに何件表示する?? serverSide: true, // サーバーサイドを使う?? ajax: { url: '/datatable/ajax', // データ取得するURL dataFilter(data) { // 取得したデータを加工する let json = JSON.parse(data); json.recordsTotal = json.total; json.recordsFiltered = json.total; return JSON.stringify(json); } }, columns: [ { data: 'code', title: '商品コード' }, { data: 'name', title: '名前' }, { data: 'created_at', title: '登録日時', orderable: false // ここの項目は並べ替えしない } ], order: [[ 0, 'asc' ]], // 並べ替え項目を指定, language: { // 日本語対応 url: 'https://cdn.datatables.net/plug-ins/1.10.19/i18n/Japanese.json' } }); }); </script> </body> </html>
まず、DataTable
の基本的な使い方は、以下のように<table></table>
タグを作ってjQuery
セレクタで専用メソッドを実行します。
<!-- HTML --> <table id="table"></table>
// JavaScript $('#table').DataTable();
そして、そのメソッドには各種オプション値を指定することができます。
今回の例では何を指定したのかを見ていきましょう。
searching
以下のような検索ボックスを表示するかどうかを決めるオプションです。
true
or false
で指定します。
ordering
ソート(並べ替え)をするかどうかのオプション。
true
or false
で指定します。
有効にすると、以下のようにテーブルヘッダーに以下のような三角マークが表示されます。
lengthChange
ページごとに何件表示するかを指定できるようにするオプション。
true
or false
で指定します。
有効にすると、以下のようなセレクトボックスが表示されます。
serverSide
このオプションが今回必ず指定しないといけないオプションで、これをtrue
にすることで、「ページごとにデータを用意する」設定になります。
ajax
データ取得するAjaxの設定をするオプションです。
今回は、Ajax
でアクセスするURL
と、取得してデータを加工するdataFilter()
を用意しています。Laravel
側で特にパラメータ名の変更をしなかったのは、dataFilter()
を準備するつもりだったからです。
columns
カラム(テーブルの項目)を指定するオプションです。
中身は以下のようになります。
- data ・・・ データのオブジェクト・キー(つまり今回の場合だと
products
テーブルのカラム名) - title ・・・ テーブルヘッダーに表示される項目名
language
DataTable
を多言語化するオプション。
URLを指定することでCDN
を使って日本語化することもできます。
テストしてみる
では、実際にテストしてみましょう!
まずは静止画から。
はい!
うまく表示されました。
では動画の方でも見てみましょう。
はい!
こちらもうまくいきました。
お疲れ様でした😊✨
おわりに
ということで、今回はLaravel
とDataTable
をAjax
で連携させるサンプルを紹介しました。
最近のJavaScript
業界では、特にAngular
やReact
が登場したあたりからjQuery
は徐々に使われなくなってきているようですが、それでもやはりjQuery
は便利ですし、何より今回のDataTable
のような有能なプラグインがインターネットにはいくつも転がっていることを考えると、利用する選択肢としては優先的に考えていいのではないでしょうか。
特にBootstrap
をCSS
フレームワークとして利用する場合はjQuery
が必要な機能も多いですし、なによりたった一文字$
と書くだけで要素にアクセスできるってのは、やはりすばらしい発明だと思います。(たしか、もともとはprototype.js
とかだった気がします😅)
とにかく、DataTable
ってとても便利です。
ぜひ皆さんも挑戦してみてくださいね。
ではでは〜♪