<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index(Request $request)
{
// Standard pagination
$posts = Post::query()
->with('author')
->when($request->search, fn ($q, $search) =>
$q->where('title', 'like', "%{$search}%")
)
->latest()
->paginate(20)
->withQueryString(); // Preserve search params
return view('posts.index', compact('posts'));
}
public function infinite(Request $request)
{
// Cursor pagination for infinite scroll
$posts = Post::query()
->latest('id')
->cursorPaginate(20);
return response()->json($posts);
}
public function simple()
{
// Simple pagination (next/prev only, no page numbers)
$posts = Post::latest()->simplePaginate(20);
return view('posts.simple', compact('posts'));
}
public function api(Request $request)
{
// API pagination with custom meta
$posts = Post::paginate(20);
return response()->json([
'data' => $posts->items(),
'meta' => [
'current_page' => $posts->currentPage(),
'last_page' => $posts->lastPage(),
'per_page' => $posts->perPage(),
'total' => $posts->total(),
],
'links' => [
'first' => $posts->url(1),
'last' => $posts->url($posts->lastPage()),
'prev' => $posts->previousPageUrl(),
'next' => $posts->nextPageUrl(),
],
]);
}
}
@foreach ($posts as $post)
<article>
<h2>{{ $post->title }}</h2>
<p>{{ $post->excerpt }}</p>
</article>
@endforeach
{{-- Default pagination links --}}
{{ $posts->links() }}
{{-- Custom pagination view --}}
{{ $posts->links('vendor.pagination.tailwind') }}
{{-- Bootstrap pagination --}}
{{ $posts->links('pagination::bootstrap-5') }}
{{-- Customize page range --}}
{{ $posts->onEachSide(2)->links() }}
{{-- Show pagination info --}}
<p>
Showing {{ $posts->firstItem() }} to {{ $posts->lastItem() }}
of {{ $posts->total() }} results
</p>
@if ($paginator->hasPages())
<nav>
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="disabled"><span>«</span></li>
@else
<li><a href="{{ $paginator->previousPageUrl() }}">«</a></li>
@endif
{{-- Pagination Elements --}}
@foreach ($elements as $element)
@if (is_string($element))
<li class="disabled"><span>{{ $element }}</span></li>
@endif
@if (is_array($element))
@foreach ($element as $page => $url)
@if ($page == $paginator->currentPage())
<li class="active"><span>{{ $page }}</span></li>
@else
<li><a href="{{ $url }}">{{ $page }}</a></li>
@endif
@endforeach
@endif
@endforeach
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<li><a href="{{ $paginator->nextPageUrl() }}">»</a></li>
@else
<li class="disabled"><span>»</span></li>
@endif
</ul>
</nav>
@endif
Pagination divides large datasets into pages, improving performance and UX. Eloquent's paginate() method returns a paginator with data and metadata. The links() method renders pagination UI. I customize per-page counts with paginate(50). Simple pagination uses simplePaginate() for next/prev only. Cursor pagination with cursorPaginate() handles infinite scrolling efficiently. Custom pagination views override default Blade templates. API pagination returns JSON with meta and links. The onEachSide() method controls visible page numbers. Pagination preserves query strings via withQueryString(). For complex queries, paginateResults() calculates totals manually. This handles millions of records efficiently.