Implementing Full-Text Search with Laravel Scout
The Problem with Manual Database Queries
Standard database queries fail when your data scales. You might start with a simple where('title', 'like', "%$query%") clause, but requirements quickly snowball. Soon, you need to search descriptions, genres, and metadata. Coding these chainable queries manually creates bloated, unreadable controllers. Performance hits become inevitable as your database struggles to scan every string across multiple columns.
Prerequisites and Setup
Before you begin, ensure you have a
Making Models Searchable
To enable search, you must prepare your model. Add the Searchable trait to your class definition. This trait hooks into Eloquent's model observers to keep your search index synced with your database.
namespace App\Models;
use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;
class Movie extends Model
{
use Searchable;
public function toSearchableArray(): array
{
return [
'title' => $this->title,
'description' => $this->description,
'rank' => $this->rank,
];
}
}
The toSearchableArray method is your control center. It defines exactly what data gets sent to the search engine. This prevents sensitive data from leaking into your public index and allows you to format relationships or calculated fields for better search relevance.
Clean Controller Integration
Once the model is ready, your controller code shrinks significantly. You can replace messy query builders with a single, expressive search method.
public function index(Request $request)
{
$movies = Movie::search($request->input('search'))->get();
return view('movies.index', compact('movies'));
}
Syncing Data and Using External Drivers
While the local database driver works for development, production environments require specialized tools. Services like
php artisan scout:import "App\Models\Movie"
Tips and Gotchas
Don't try to search relationships directly using the basic database driver; it will look for a column that doesn't exist on the table and throw an error. If you need to search through related data like Genres, use a more advanced driver. Always remember that Scout uses observers—if you use mass updates via Movie::query()->update(), the search index won't see those changes. Use standard Eloquent save() or update() calls to keep everything in sync.
