概要
ページネーションは、データを自動的に分割し、シンプルなページリンクを生成するために使用されます。
【コントローラー】
$items = Item::paginate(件数);
【view】Tailwind CSS
{{ $items->links() }}
【view】Bootstrap 4
{{ $items->links('pagination::bootstrap-4') }}
【view】Bootstrap 5
{{ $items->links('pagination::bootstrap-5') }}
Tailwind CSSかBootstrapをインストールした方を使用
ソース例
【コマンド】Migration・Model・Factory・Seederファイル作成
php artisan make:model Item -mfs
【ファイル先】database/migrations/2024_01_01_065715_create_items_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->string('name'); // 追加
$table->text('description')->nullable(); // 追加
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('items');
}
};
【ファイル先】app/Models/Item.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Item extends Model
{
use HasFactory;
/**
* 複数代入を許可するカラム
*
* @var array<int, string>
*/
protected $fillable = ['name', 'description'];
}
【ファイル先】database/factories/ItemFactory.php
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class ItemFactory extends Factory
{
/**
* モデルに関連するデフォルトの状態を定義
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => $this->faker->word(), // 商品名としてランダムな単語を生成
'description' => $this->faker->sentence(), // 商品説明としてランダムな文章を生成
];
}
}
【ファイル先】database/seeders/ItemSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Item;
class ItemSeeder extends Seeder
{
/**
* データベースにダミーデータを挿入
*
* @return void
*/
public function run(): void
{
// 50件のダミーデータを生成
Item::factory()->count(50)->create();
}
}
【ファイル先】routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ItemController;
Route::get('/', function () {
return view('welcome');
});
Route::get('/items', [ItemController::class, 'index'])->name('items.index');
【ファイル先】resources/views/items/index.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Items List</title>
</head>
<body>
<h1>Items List</h1>
@foreach ($items as $item)
<div>
<h2>{{ $item->name }}</h2>
<p>{{ $item->description }}</p>
</div>
@endforeach
<!-- ページネーションリンク(Tailwind CSS) -->
{{ $items->links() }}
</body>
</html>
【コマンド】
// テーブル作成
php artisan migrate
// 仮データ50件投入
php artisan db:seed --class=ItemSeeder
http://localhost/itemsで確認してみましょう。
色々なページネーション
シンプル
シンプルな「前へ」「次へ」リンクのみを提供するページネーションを行います。
【コントローラー】
$items = Item::simplePaginate(件数);
カスタムページ
カスタムビューで表示する場合、links
メソッドにカスタムビューを指定します。
【コマンド】
php artisan vendor:publish --tag=laravel-pagination
【view】
{{ $items->links('vendor.pagination.custom') }}
【ページネーションのデザイン】
.pagination {
display: flex;
list-style: none;
padding: 0;
}
.pagination li {
margin: 0 5px;
}
.pagination li a {
padding: 8px 12px;
border: 1px solid #ddd;
text-decoration: none;
color: #007bff;
}
.pagination li a:hover {
background-color: #007bff;
color: white;
}
.pagination .active span {
background-color: #007bff;
color: white;
padding: 8px 12px;
border: 1px solid #007bff;
}
URLにクエリパラメータを追加
追加のクエリパラメータを付加したい場合、appends
メソッドを使用します。
※検索条件やソート順を保持
【view】
{{ $items->appends(request()->query())->links() }}
【ファイル先】app/Http/Controllers/ItemController.php
<?php
namespace App\Http\Controllers;
use App\Models\Item;
use Illuminate\Http\Request;
class ItemController extends Controller
{
/**
* 商品一覧を表示する
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\View\View
*/
public function index(Request $request)
{
// クエリビルダーを利用して、Itemモデルのデータを取得するための準備
$query = Item::query();
// 検索条件が入力されている場合、その条件でデータを絞り込む
if ($request->filled('search')) {
$search = $request->search;
// 検索条件を指定して、name か description にキーワードが含まれるデータを取得
$query->where(function ($query) use ($search) {
$query->where('name', 'like', '%' . $search . '%')
->orWhere('description', 'like', '%' . $search . '%');
});
}
// ソートの順番(昇順か降順か)を指定。デフォルトでは昇順(asc)
$sortOrder = $request->get('sort', 'asc');
// name列に基づいて指定された順序でデータを並べ替える
$query->orderBy('name', $sortOrder);
// ページネーションを適用して、1ページあたり10件のデータを取得
$items = $query->paginate(10);
// 取得したデータをビュー(items/index.blade.php)に渡して表示
return view('items.index', compact('items'));
}
}
【ファイル先】resources/views/items/index.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Items List</title>
</head>
<body>
<h1>Items List</h1>
<!-- 検索フォーム -->
<form action="{{ route('items.index') }}" method="GET">
<input type="text" name="search" value="{{ request('search') }}" placeholder="検索キーワード">
<!-- ソートの選択 (昇順・降順) -->
<select name="sort" onchange="this.form.submit()">
<option value="" disabled selected>ソート順を選択</option>
<option value="asc" {{ request('sort') == 'asc' ? 'selected' : '' }}>昇順</option>
<option value="desc" {{ request('sort') == 'desc' ? 'selected' : '' }}>降順</option>
</select>
<button type="submit">検索</button>
</form>
<!-- アイテムリスト -->
@foreach ($items as $item)
<div>
<h2>{{ $item->name }}</h2>
<p>{{ $item->description }}</p>
</div>
@endforeach
<!-- ページネーションリンク -->
{{ $items->appends(request()->query())->links() }}
</body>
</html>
ページ番号の周辺リンク数調整
中央時のページリンクの前後リンクをonEachSide
メソッドで調整できます。
※デフォルトでは前後に3つずつのリンク
【view】
{{ $items->onEachSide(数値)->links() }}
データを配列取得
ページネーション結果を配列として取得するには、toArray
メソッドを使用します。
※カスタムビューやAPIレスポンスに使用
【コントローラー】
$paginationData = $items->paginate(10)->toArray();
名前付きページネーション
複数のページネーションを同じ画面で使う際、それぞれ独立したクエリパラメータ名を付ける方法です。
※withQueryString
は、現在のクエリパラメータをページネーションリンクに引き継ぐ
【コントローラー】
// 商品一覧のページネーション
$items = Item::paginate(10, ['*'], 'items_page');
// ユーザー一覧のページネーション
$users = User::paginate(5, ['*'], 'users_page');
【view】
@foreach ($items as $item)
<div>
<h2>{{ $item->name }}</h2>
<p>{{ $item->description }}</p>
</div>
@endforeach
<!-- 商品一覧のページネーション -->
{{ $items->withQueryString()->links() }}
@foreach ($users as $user)
<div>
<h2>{{ $user->name }}</h2>
<p>{{ $user->email }}</p>
</div>
@endforeach
<!-- ユーザー一覧のページネーション -->
{{ $users->withQueryString()->links() }}