laravel/scout
Laravel Scout adds driver-based full-text search to Eloquent models, automatically syncing model changes to your search indexes. Supports Algolia, Meilisearch, and Typesense, with configuration and usage documented on laravel.com.
Installation:
composer require laravel/scout
For a specific driver (e.g., Algolia, Meilisearch, or Typesense), install its dedicated package:
composer require algolia/algoliasearch-client-php # or meilisearch/meilisearch-php, typesense/typesense-php
Configuration: Publish the config file:
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
Update .env with your driver-specific credentials (e.g., ALGOLIA_APP_ID, ALGOLIA_SECRET).
Enable Scout on a Model:
Add use Laravel\Scout\Searchable; and implement toSearchableArray():
use Laravel\Scout\Searchable;
class Post extends Model
{
use Searchable;
public function toSearchableArray()
{
return [
'title' => $this->title,
'body' => $this->body,
];
}
}
First Search:
$results = Post::search('laravel')->get();
php artisan scout:import "App\Models\Post"
php artisan scout:flush "App\Models\Post"
Searching:
$posts = Post::search('query')->get();
$posts = Post::search('query')->paginate(10);
$posts = Post::search('query')->where('title', 'like', '%Laravel%')->get();
Filtering:
where() for driver-specific filters:
$posts = Post::search('query')->where('category', 'news')->get();
callback():
$posts = Post::search('query')->where(function ($query) {
$query->where('author', 'John')->where('published', true);
})->get();
Sorting:
setSettings):
$posts = Post::search('query')->sortBy('created_at')->get();
callback():
$posts = Post::search('query')->callback(function ($query) {
return $query->sort(['created_at:desc']);
})->get();
Real-Time Updates:
shouldBeSearchable() to control this:
public function shouldBeSearchable()
{
return $this->isPublished();
}
Bulk Operations:
php artisan scout:import "App\Models\Post"
php artisan scout:queue "App\Models\Post"
Customizing Searchable Data:
public function toSearchableArray()
{
return $this->isAdmin()
? ['title' => $this->title, 'body' => $this->body, 'secret' => $this->secret]
: ['title' => $this->title, 'body' => $this->body];
}
Driver-Specific Features:
setSettings() for custom ranking:
Post::search('query')->setSettings(['customRanking' => ['desc(created_at)']])->get();
Post::search('query')->with(['facets' => ['categories']])->get();
Fallback to Database:
collection driver for local development/testing:SCOUT_DRIVER=collection
Testing:
public function testSearch()
{
Scout::shouldReceive('search')->andReturn([new Post]);
$results = Post::search('test')->get();
}
Performance Optimization:
public function shouldBeSearchable()
{
return !$this->trashed();
}
searchableSync() for manual syncs:
$post->searchableSync();
Driver Mismatches:
algolia/algoliasearch-client-php@4.x for Scout v11+).composer.json and update dependencies.Case Sensitivity:
typoTolerance or ignorePlurals in settings:
Post::search('query')->setSettings(['typoTolerance' => 'min']);
Soft Deletes:
shouldBeSearchable():
public function shouldBeSearchable()
{
return !$this->trashed();
}
Pagination Issues:
cursor() for large datasets:
$posts = Post::search('query')->cursor();
Filter Syntax Errors:
$posts = Post::search('query')->where('title', '!=', 'Special "Chars"')->get();
Queue Delays:
scout:queue:
php artisan scout:queue "App\Models\Post" --queue=search
Log Search Queries:
.env:
SCOUT_LOG_QUERIES=true
storage/logs/laravel.log for raw queries.Inspect Index:
http://localhost:7700/docshttp://localhost:8108Handle Missing Collections:
php artisan scout:import "App\Models\Post"
Callback Debugging:
dd() in callback() to inspect raw queries:
$posts = Post::search('query')->callback(function ($query) {
dd($query->getQuery()); // Inspect raw query
return $query;
})->get();
Custom Engines:
Laravel\Scout\Engines\Engine for new drivers. Example:
class CustomEngine extends Engine
{
public function update($model)
{
// Custom logic
}
}
Override Searchable Array:
appendingSearchableAttributes:
protected function appendingSearchableAttributes()
{
return ['slug' => $this->title];
}
Custom Query Builder:
Laravel\Scout\Builder for driver-specific methods:
class CustomBuilder extends Builder
{
public function customMethod()
{
return $this->applyCallback(function ($query) {
return $query->customDriverMethod();
});
}
}
Event Hooks:
scout.searching) to intercept queries:
Scout::searching(function ($query) {
if ($query->model === Post::class) {
$query->setSettings(['hitsPerPage' => 20]);
}
});
Batch Processing:
chunk() for large datasets:
Post::chunk(100, function ($posts) {
foreach ($posts as $post) {
$post->searchableSync();
}
});
How can I help you explore Laravel packages today?