【Laravel11】Laravel-AdminLTEでDataTablesを利用する

## はじめに

DataTables（[https://datatables.net/](https://datatables.net/)）は、HTMLテーブルを拡張するjQueryプラグインで、以下の機能を提供します：

- ページネーション：大量データの分割表示
- 検索・フィルタリング：リアルタイム検索と列別フィルター
- ソート：複数列対応の並べ替え
- レスポンシブデザイン対応
- 高度なカスタマイズ性（CSS/JavaScript/多言語対応）
- 様々なデータソースに対応（HTML/Ajax/JavaScript配列）

Laravel-AdminLTEでこれらの機能を簡単に実装する方法を解説します。

Laravel11とLaravel-AdminLTEのセットアップ方法はこちらを参照ください。

https://qiita.com/jagaaa/items/82c47a36b17faea20d3f

## ⚠️ パフォーマンスに関する重要な注意点

この記事では基本的な実装方法として、一括でデータを取得する処理になっていますが、以下の理由により大規模データでは推奨されません：

- メモリ使用量の増大：全データを一度にメモリに読み込むため、大量のメモリを消費
- 初期ロード時間の増加：大量データの取得と処理に時間がかかる
- サーバーへの負荷：データベースから全レコードを取得するため、サーバーリソースを大量に消費

大規模データセットを扱う場合は、後述するサーバーサイドプロセッシングの実装を強く推奨します。

## 基本的な実装手順

### 1. プラグインのインストール

必要なプラグインをインストールします：

```bash
php artisan adminlte:plugins install --plugin=datatables --plugin=datatablesPlugins
```

### 2. プラグインの有効化

`config/adminlte.php`に以下の設定を追加します：

```php
'plugins' => [
    'Datatables' => [
        'active' => true,
        'files' => [
            [
                'type' => 'js',
                'asset' => true,
                'location' => 'vendor/datatables/js/jquery.dataTables.min.js',
            ],
            [
                'type' => 'js',
                'asset' => true,
                'location' => 'vendor/datatables/js/dataTables.bootstrap4.min.js',
            ],
            [
                'type' => 'css',
                'asset' => true,
                'location' => 'vendor/datatables/css/dataTables.bootstrap4.min.css',
            ],
        ],
    ],
    'DatatablesPlugins' => [
        'active' => true,
        'files' => [
            [
                'type' => 'js',
                'asset' => true,
                'location' => 'vendor/datatables-plugins/buttons/js/dataTables.buttons.min.js',
            ],
            [
                'type' => 'js',
                'asset' => true,
                'location' => 'vendor/datatables-plugins/buttons/js/buttons.bootstrap4.min.js',
            ],
            [
                'type' => 'js',
                'asset' => true,
                'location' => 'vendor/datatables-plugins/buttons/js/buttons.html5.min.js',
            ],
            [
                'type' => 'js',
                'asset' => true,
                'location' => 'vendor/datatables-plugins/buttons/js/buttons.print.min.js',
            ],
            [
                'type' => 'js',
                'asset' => true,
                'location' => 'vendor/datatables-plugins/jszip/jszip.min.js',
            ],
            [
                'type' => 'js',
                'asset' => true,
                'location' => 'vendor/datatables-plugins/pdfmake/pdfmake.min.js',
            ],
            [
                'type' => 'js',
                'asset' => true,
                'location' => 'vendor/datatables-plugins/pdfmake/vfs_fonts.js',
            ],
            [
                'type' => 'css',
                'asset' => true,
                'location' => 'vendor/datatables-plugins/buttons/css/buttons.bootstrap4.min.css',
            ],
        ],
    ],
],
```

### 3. コントローラーの作成

ユーザー一覧を表示するコントローラーを作成します：

```bash
php artisan make:controller UserController
```

```php
<?php

namespace App\Http\Controllers;

use App\Models\User;

class UserController extends Controller
{
    public function index()
    {
        $users = User::select(['id', 'name', 'email', 'created_at', 'updated_at'])->get();

        // テーブルヘッダーの定義
        $heads = [
            'ID',
            '名前',
            'Eメール',
            '更新日',
            '作成日',
            ['label' => '操作', 'no-export' => true, 'width' => 15],
        ];

        // 操作ボタンの定義
        $btnEdit = '<button class="btn btn-xs btn-default text-primary mx-1 shadow" title="Edit">
            <i class="fa fa-lg fa-fw fa-pen"></i>
        </button>';
        $btnDelete = '<button class="btn btn-xs btn-default text-danger mx-1 shadow" title="Delete">
            <i class="fa fa-lg fa-fw fa-trash"></i>
        </button>';
        $btnDetails = '<button class="btn btn-xs btn-default text-teal mx-1 shadow" title="Details">
            <i class="fa fa-lg fa-fw fa-eye"></i>
        </button>';

        // DataTablesの設定
        $config = [
            'data' => $users->map(function ($user) use ($btnEdit, $btnDelete, $btnDetails) {
                return [
                    $user->id,
                    $user->name,
                    $user->email,
                    $user->updated_at->format('Y-m-d H:i:s'),
                    $user->created_at->format('Y-m-d H:i:s'),
                    '<nobr>' . $btnEdit . $btnDelete . $btnDetails . '</nobr>'
                ];
            })->toArray(),
            'order' => [[0, 'asc']],
            'columns' => [null, null, null, null, null, ['orderable' => false]],
            'language' => [
                'url' => "//cdn.datatables.net/plug-ins/1.10.24/i18n/Japanese.json"
            ]
        ];

        return view('user.index', compact('heads', 'config'));
    }
}
```

### 4. ビューの作成

`resources/views/user/index.blade.php`を作成します：

```php
@extends('layouts.admin')

@section('title', 'アカウント一覧')

@section('content_header')
<h1>アカウント一覧</h1>
@stop

@section('content')
<div class="card">
    <div class="card-body">
        <x-adminlte-datatable id="table1" :heads="$heads" :config="$config" />
    </div>
</div>
@stop
```

### 5. ルーティングの設定

`routes/web.php`に以下を追加：

```php
use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index'])->name('users.index');
```

### 6. テストデータの作成

```php
<?php

namespace Database\Seeders;

use App\Models\User;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        User::factory(100)->create();
    }
}
```

### 7.画面確認
開発サーバーを起動
```bash
php artisan serve
```
以下のURLにアクセスします。
http://127.0.0.1:8000/users

絞りこみ検索、ソート、ページング機能が実装されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526782/2a6279eb-9439-6ee2-e14c-e96fb0d8f35f.png)


## サーバーサイドプロセッシングの実装

大規模データセットを扱う場合は、以下のサーバーサイドプロセッシングの実装を推奨します。

### 1. ライブラリのインストール
[yajra/laravel-datatables-oracle](https://yajrabox.com/docs/laravel-datatables/11.0)をインストールします。

```bash
composer require yajra/laravel-datatables-oracle
```

### 2. コントローラーの実装

```php
use Yajra\DataTables\Facades\DataTables;

class UserController extends Controller
{
    public function index()
    {
        $heads = [
            'ID',
            '名前',
            'Eメール',
            '更新日',
            '作成日',
            ['label' => '操作', 'no-export' => true, 'width' => 15],
        ];

        // DataTablesの設定
        $config = [
            'processing' => true,
            'serverSide' => true,
            'ajax' => route('users.data'), // データ取得用のルート
            'columns' => [
                ['data' => 'id'],
                ['data' => 'name'],
                ['data' => 'email'],
                ['data' => 'updated_at'],
                ['data' => 'created_at'],
                ['data' => 'action', 'orderable' => false, 'searchable' => false],
            ],
            'language' => [
                'url' => "//cdn.datatables.net/plug-ins/1.10.24/i18n/Japanese.json"
            ]
        ];

        return view('user.index', compact('heads', 'config'));
    }

    public function getData()
    {
        return DataTables::of(User::query())
            ->addColumn('action', function ($user) {
                $btnEdit = '<button class="btn btn-xs btn-default text-primary mx-1 shadow" title="Edit">
                    <i class="fa fa-lg fa-fw fa-pen"></i>
                </button>';
                $btnDelete = '<button class="btn btn-xs btn-default text-danger mx-1 shadow" title="Delete">
                    <i class="fa fa-lg fa-fw fa-trash"></i>
                </button>';
                $btnDetails = '<button class="btn btn-xs btn-default text-teal mx-1 shadow" title="Details">
                    <i class="fa fa-lg fa-fw fa-eye"></i>
                </button>';
                
                return '<nobr>' . $btnEdit . $btnDelete . $btnDetails . '</nobr>';
            })
            ->rawColumns(['action'])
            ->make(true);
    }
}
```

### 3. ルーティングの追加

```php
Route::get('/users', [UserController::class, 'index'])->name('users.index');
Route::get('/users/data', [UserController::class, 'getData'])->name('users.data');
```

## サーバーサイドプロセッシングのメリット

- 必要なデータのみを取得するため、メモリ使用量が削減されます
- ページング処理がサーバー側で行われるため、大規模データセットでも高速に動作します
- 検索やソートの処理がデータベース側で実行されるため、効率的です

↓Chrome デベロッパーツールで確認。
ページングを切り替えるたびに取得しているのが確認できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526782/b90fc58e-a296-708d-6537-5ad0812fda36.png)


## まとめ

Laravel-AdminLTEとDataTablesを組み合わせることで、高機能な管理画面のテーブル表示を実装できます。小規模なデータセットであれば基本的な実装で十分ですが、大規模データを扱う場合は、[yajra/laravel-datatables-oracle](https://yajrabox.com/docs/laravel-datatables/11.0)を使用したサーバーサイドプロセッシングの実装をおすすめします。