Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Scout Laravel Package

laravel/scout

Laravel Scout adds driver-based full-text search to Eloquent models, automatically syncing model changes to search indexes. Supports Algolia, Meilisearch, and Typesense, with easy configuration via Laravel’s Scout integration.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require laravel/scout

For a specific driver (e.g., Algolia, Meilisearch, or Typesense), install its corresponding package:

composer require algolia/algoliasearch-client-php  # Example for Algolia
  1. Configuration: Publish the Scout config file:

    php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider" --tag="scout-config"
    

    Update .env with your driver-specific credentials (e.g., ALGOLIA_APP_ID, ALGOLIA_SECRET).

  2. Enable Scout on a Model: Use the Searchable trait in your Eloquent model:

    use Laravel\Scout\Searchable;
    
    class Post extends Model
    {
        use Searchable;
    }
    
  3. First Search:

    $results = Post::search('laravel')->get();
    
  4. Indexing: Scout automatically syncs model changes to the search index. For initial setup, run:

    php artisan scout:import "App\Models\Post"
    

First Use Case: Basic Search

// Search for posts containing "laravel"
$posts = Post::search('laravel')->get();

// Paginate results
$posts = Post::search('laravel')->paginate(10);

// Filter results (e.g., published posts)
$posts = Post::search('laravel')
             ->where('published', true)
             ->get();

Implementation Patterns

1. Driver-Specific Workflows

Algolia

  • Configuration:
    SCOUT_DRIVER=algolia
    ALGOLIA_APP_ID=your_app_id
    ALGOLIA_SECRET=your_secret
    ALGOLIA_SEARCH=your_search_engine
    
  • Custom Settings:
    public function toSearchableArray()
    {
        return [
            'title' => $this->title,
            'content' => $this->content,
            'custom_ranking' => ['asc' => 'published_at'],
        ];
    }
    

Meilisearch

  • Configuration:
    SCOUT_DRIVER=meilisearch
    MEILI_HOST=http://localhost:7700
    MEILI_MASTER_KEY=your_master_key
    
  • Filtering:
    $posts = Post::search('laravel')
                 ->where('category', 'tutorial')
                 ->get();
    

Typesense

  • Configuration:
    SCOUT_DRIVER=typesense
    TYPESENSE_HOST=http://localhost:8108
    TYPESENSE_API_KEY=your_api_key
    TYPESENSE_COLLECTION=posts
    
  • Custom Index:
    public function getScoutKey()
    {
        return "custom_prefix_{$this->id}";
    }
    

2. Query Customization

Custom Search Logic

// Use a closure for complex queries
$results = Post::search(function ($query) {
    $query->where('title', 'like', '%laravel%')
          ->where('published_at', '>', now()->subYear());
})->get();

Sorting

$results = Post::search('laravel')
               ->sortBy('published_at')
               ->get();

Pagination

$results = Post::search('laravel')->paginate(15);

3. Bulk Operations

Import All Records

php artisan scout:import "App\Models\Post"
  • Queue Large Imports:
    php artisan scout:queue "App\Models\Post"
    

Delete All Records

php artisan scout:flush "App\Models\Post"

4. Advanced: Custom Engines

Extend the base engine for custom drivers:

use Laravel\Scout\Engines\Engine;

class CustomEngine extends Engine
{
    public function search($query)
    {
        // Custom search logic
    }

    public function paginate($query, $perPage, $page)
    {
        // Custom pagination logic
    }

    public function map($results)
    {
        // Map raw results to Eloquent models
    }
}

Register the engine in config/scout.php:

'driver' => CustomEngine::class,

5. Observers for Sync Control

Override default sync behavior:

use Laravel\Scout\Events\Searching;

class PostObserver
{
    public function saving($model)
    {
        if (!$model->shouldBeSearchable()) {
            $model->unsearchable();
        }
    }

    public function saved($model)
    {
        if ($model->shouldBeSearchable()) {
            $model->searchable();
        }
    }
}

Gotchas and Tips

1. Common Pitfalls

Driver-Specific Quirks

  • Algolia:
    • Numeric filters (e.g., where('price', '>', 100)) may require explicit casting in toSearchableArray.
    • Silent failures with whereNotIn for numeric values (fixed in v10.23.1). Use strings or explicit casting.
  • Meilisearch:
    • Filtering null values requires explicit handling:
      $query->where('field', null); // May not work as expected; use raw queries if needed.
      
    • Escape double quotes in filter strings to avoid syntax errors.
  • Typesense:
    • Pagination issues with large datasets (fixed in v10.14.2). Ensure perPage and page are integers.
    • Race conditions during collection creation (resolved in v10.13.1). Use scout:import cautiously in high-concurrency environments.

Indexing Delays

  • Scout uses queues for async indexing. If results are stale:
    • Manually trigger sync:
      $model->searchable(); // Force sync
      
    • Check queue workers:
      php artisan queue:work
      

Case Sensitivity

  • Meilisearch/Typesense: Search is case-insensitive by default.
  • Algolia: Respects case sensitivity unless configured otherwise in settings.

2. Debugging Tips

Log Raw Queries

Enable Scout logging in config/scout.php:

'debug' => env('SCOUT_DEBUG', false),

Check logs for raw driver queries during searches.

Inspect Index Contents

  • Algolia:
    php artisan scout:dump "App\Models\Post"
    
  • Meilisearch/Typesense: Use their respective admin APIs to inspect collections/indexes.

Handle Missing Collections

  • Typesense: Ensure the collection exists before searching:
    if (!Typesense::collectionExists('posts')) {
        Typesense::createCollection('posts');
    }
    

3. Performance Optimization

Batch Indexing

For large datasets, use chunking:

Post::chunk(100, function ($posts) {
    foreach ($posts as $post) {
        $post->searchable();
    }
});

Disable Indexing Temporarily

$model->unsearchable(); // Opt out of indexing

Use scout:queue for Large Imports

php artisan scout:queue "App\Models\Post" --queue=scout

4. Configuration Quirks

Default Driver

  • Changed in v10.19.1: Default driver is now collection (in-memory) instead of algolia. Update .env if relying on defaults:
    SCOUT_DRIVER=collection
    

Prefix Handling

  • Typesense/Meilisearch: Use scout_prefix by default. Disable with:
    TYPESENSE_PREFIX=
    MEILI_PREFIX=
    

Queue Retries

Configure retry logic in config/scout.php:

'queue' => [
    'retry_after' => 60, // Retry after 60 seconds
],

5. Extension Points

Custom Searchable Attributes

Override toSearchableArray for dynamic fields:

public function toSearchableArray()
{
    return [
        'title' => $this->title,
        'content' => $this->content,
        'tags' => $this->tags->pluck('name'), // Relationship data
    ];
}

Post-Processing Results

Use afterRawSearch callback:

public function afterRawSearch($query)
{
    return $query->filter(function ($hit) {
        return $hit['published'] === true;
    });
}

Custom Sorting

Extend the Builder for custom sort methods:

use Laravel\Scout\Builder;

class CustomBuilder extends Builder
{
    public function sortByRelevance()
    {
        return $this->
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4