SupportWriter space ↗
← Back to the journal
Laravel

Preserve Search Filters During Laravel Pagination

Build an article list with title search, stable ordering, and pagination links that preserve the query.

DAdministrator · 20 Sep 2026 · 1 min read

You are reading a translated version.

A reader searches for an article, opens page two, and loses the filter. A common cause is pagination links that omit the search parameter.

This example uses a q title filter and includes only published articles. Build the query before calling paginate. Adapt the view and route names to your application.

Implementation example

public function index(\Illuminate\Http\Request $request)
{
    $data = $request->validate(['q' => ['nullable', 'string', 'max:100']]);
    $query = trim($data['q'] ?? '');

    $posts = \App\Models\Post::query()
        ->whereNotNull('published_at')
        ->where('published_at', '<=', now())
        ->when($query !== '', fn ($builder) =>
            $builder->where('title', 'like', '%'.$query.'%'))
        ->orderByDesc('published_at')
        ->orderByDesc('id')
        ->paginate(10)
        ->appends(['q' => $query]);

    return view('articles.index', compact('posts', 'query'));
}
<form method="get">
    <label for="query">Search articles</label>
    <input id="query" name="q" value="{{ $query }}">
    <button>Search</button>
</form>
@foreach ($posts as $post)
    <h2>{{ $post->title }}</h2>
@endforeach
{{ $posts->links() }}

Check the result

Create more than ten articles matching the keyword. Open page two and confirm the URL retains q. Submit a new search: because the form has no page field, it starts on page one.

The secondary ID ordering resolves equal publication timestamps. This example uses SQL LIKE semantics, so % and _ in input act as wildcards. Add database-appropriate escaping if literal matching is required. For large datasets, evaluate indexing or a search engine instead of assuming %term% will scale.

Reference

Official documentation

← Explore more notes