Search & Pagination
LaravelLet's add a powerful search feature and proper pagination to our blog so readers can easily find content.
Search Controller
app/Http/Controllers/SearchController.php
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class SearchController extends Controller
{
public function __invoke(Request $request)
{
$query = $request->get('q', '');
$posts = collect(); // Empty collection by default
if (strlen($query) >= 3) {
$posts = Post::published()
->where(function($q) use ($query) {
$q->where('title', 'LIKE', "%{$query}%")
->orWhere('body', 'LIKE', "%{$query}%")
->orWhere('excerpt', 'LIKE', "%{$query}%")
->orWhereHas('tags', fn($t) => $t->where('name', 'LIKE', "%{$query}%"))
->orWhereHas('category', fn($c) => $c->where('name', 'LIKE', "%{$query}%"));
})
->with(['user', 'category'])
->latest()
->paginate(10)
->withQueryString(); // Keep ?q= in pagination links
}
return view('blog.search', compact('posts', 'query'));
}
}Search Route
routes/web.php
<?php
Route::get('/search', SearchController::class)->name('blog.search');Search View
resources/views/blog/search.blade.php
@extends('layouts.app')
@section('title', 'Search: ' . $query)
@section('content')
<div class="max-w-4xl mx-auto px-4 py-8">
<!-- Search Box -->
<form method="GET" action="{{ route('blog.search') }}" class="mb-8">
<div class="flex gap-2">
<input type="text"
name="q"
value="{{ $query }}"
placeholder="Search posts..."
class="flex-1 border rounded-lg px-4 py-3 text-lg focus:outline-none focus:ring-2 focus:ring-blue-500" />
<button type="submit"
class="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700">
Search
</button>
</div>
</form>
@if(strlen($query) < 3)
<p class="text-gray-400">Please enter at least 3 characters to search.</p>
@elseif($posts->isEmpty())
<div class="text-center py-12">
<div class="text-4xl mb-4">🔍</div>
<h2 class="text-xl font-bold mb-2">No results found</h2>
<p class="text-gray-400">No posts found for "{{ $query }}"</p>
</div>
@else
<p class="text-gray-500 mb-6">
{{ $posts->total() }} result(s) for "<strong>{{ $query }}</strong>"
</p>
@foreach($posts as $post)
<article class="bg-white rounded-lg shadow p-6 mb-4 hover:shadow-md transition">
<div class="flex justify-between items-start">
<div>
@if($post->category)
<span class="text-xs font-semibold uppercase tracking-wide text-blue-600">
{{ $post->category->name }}
</span>
@endif
<h2 class="text-lg font-bold mt-1">
<a href="{{ route('blog.show', $post) }}"
class="hover:text-blue-600">
{!! str_ireplace($query, '<mark class="bg-yellow-100">' . $query . '</mark>', e($post->title)) !!}
</a>
</h2>
<p class="text-gray-500 mt-2 text-sm">{{ $post->excerpt }}</p>
</div>
@if($post->image)
<img src="{{ Storage::url($post->image) }}"
class="w-24 h-16 object-cover rounded ml-4 flex-shrink-0" />
@endif
</div>
<div class="flex items-center gap-4 mt-4 text-xs text-gray-400">
<span>By {{ $post->user->name }}</span>
<span>{{ $post->published_at->format('M d, Y') }}</span>
<span>{{ $post->reading_time }}</span>
</div>
</article>
@endforeach
<div class="mt-6">{{ $posts->links() }}</div>
@endif
</div>
@endsectionSearch Bar in Layout
resources/views/layouts/app.blade.php (navbar)
<!-- Add to navbar -->
<form method="GET" action="{{ route('blog.search') }}" class="flex">
<input type="text" name="q" placeholder="Search..."
value="{{ request('q') }}"
class="border rounded-l px-3 py-1 text-sm focus:outline-none" />
<button type="submit"
class="bg-blue-600 text-white px-3 py-1 rounded-r text-sm">🔍</button>
</form>Custom Pagination Style
Terminal
# Publish pagination views to customize
php artisan vendor:publish --tag=laravel-pagination
# Files created in: resources/views/vendor/pagination/
# Edit tailwind.blade.php for Tailwind CSS styling💡
Highlight search terms! The
str_ireplace trick wraps the search term in a yellow <mark> tag in the results. This is a UX best practice used by Google and every major search engine.💡
Always use withQueryString()! Without it, pagination links lose the
?q=laravel parameter — users get taken to page 2 of ALL posts instead of page 2 of search results.Stuck? Need help?
Review the previous lessons or check the Laravel documentation.