LaravelとDataTable.jsをAjaxで連携させる方法

さてさて、最近はプログラムを使った様々な「企画」のような記事を重点的に公開してきていましたが、たまにはそういったものとは違った「基本的なプログラム」も記事にしたいなということで、いろいろとアイデアを出している最中です。

そして、その中で以前から「気になっていたものの忘れてしまっていたもの」に気がつきました。

それは、

LaravelとDataTable.jsをAjaxを使って連携させること

です。

DataTable.jsというのは、通常のテーブルに検索やソート、ページリンクなどを一括で提供してくれる有名なjQueryのプラグインのことでAjaxを使う場合、データ取得は以下2つのパターンがあります。

  1. 最初に全データを取得しておいて、あとは全て “DataTable” にまかせる
  2. ページが切り替わるごとにサーバーサイド(PHPなど)からデータを取得する

もちろんデータが少なければ1番のシンプルな方法で問題はないのですが、これが何千、何万件となってくるとページ表示が目に見えて遅くなったりもします😫

そこで登場するのが2番なのですが、この場合だと検索やソートなどは自前で実装する必要があります。

そこで!

今回は、この「ちょっと複雑だけど快適」な2番めの方法でLaravelDataTableを連携させる方法をご紹介します。

ぜひ、皆さんのお役に立てると嬉しいです😊✨

開発環境: 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パラメータとして現在のページ番号を送信してくれませんので、こちらもstartlengthを使って自前で計算する必要があります。

なお、このコードの中では、パラメータ名の変更をしてないことに注目してください。本来は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を使って日本語化することもできます。

テストしてみる

では、実際にテストしてみましょう!
まずは静止画から。

はい!
うまく表示されました。

では動画の方でも見てみましょう。

はい!
こちらもうまくいきました。

お疲れ様でした😊✨

おわりに

ということで、今回はLaravelDataTableAjaxで連携させるサンプルを紹介しました。

最近のJavaScript業界では、特にAngularReactが登場したあたりからjQueryは徐々に使われなくなってきているようですが、それでもやはりjQueryは便利ですし、何より今回のDataTableのような有能なプラグインがインターネットにはいくつも転がっていることを考えると、利用する選択肢としては優先的に考えていいのではないでしょうか。

特にBootstrapCSSフレームワークとして利用する場合はjQueryが必要な機能も多いですし、なによりたった一文字$と書くだけで要素にアクセスできるってのは、やはりすばらしい発明だと思います。(たしか、もともとはprototype.jsとかだった気がします😅)

とにかく、DataTableってとても便利です。
ぜひ皆さんも挑戦してみてくださいね。

ではでは〜♪

この記事が役立ちましたらシェアお願いします😊✨