Laravel Scout Bulk Actions
Import, flush, and queue-import all your Laravel Scout searchable models at once. Auto-discovers models, runs in bulk, tracks progress.
composer require mozex/laravel-scout-bulk-actions
Laravel Scout's built-in commands work on one model at a time. If your project has ten searchable models, that's ten separate scout:import calls every time you need to rebuild your indexes. This package fixes that.
Scout Bulk Actions auto-discovers every model that uses the Searchable trait and lets you import, flush, or refresh all of them with a single command. It also supports queued bulk imports for projects where synchronous indexing is too slow.
Installation
Requires PHP 8.2+ - see all version requirements
Install the package via Composer:
composer require mozex/laravel-scout-bulk-actions
That's it. The package auto-registers its service provider via Laravel's package discovery.
Configuration
Publish the config file:
php artisan vendor:publish --tag="scout-bulk-actions-config"
This creates config/scout-bulk-actions.php:
return [
'model_directories' => [
app_path('Models'),
// base_path('Modules/*/Models'),
],
];
The model_directories array tells the package where to look for your searchable models. By default it scans app/Models, which covers most Laravel projects.
Glob patterns work here too. If you're using a modular architecture, something like base_path('Modules/*/Models') will scan the Models directory inside every module at once.
After changing the config in production, run php artisan config:clear to pick up the new values.
Commands
scout:import-all
Imports all discovered searchable models into the search index:
php artisan scout:import-all
You can control the chunk size (how many records are sent per batch) with the --chunk option:
php artisan scout:import-all --chunk=200
If omitted, it falls back to the scout.chunk.searchable config value.
Pass --fresh to flush each model from the index right before that model is imported:
php artisan scout:import-all --fresh
This isn't the same as scout:refresh, which empties every index first and only then starts importing. With --fresh, a model is missing from the index for the length of its own import and no longer, so the rest of your search keeps working while the rebuild runs.
scout:flush-all
Removes all records from the search index for every discovered model:
php artisan scout:flush-all
scout:queue-import-all
For large datasets, synchronous imports can be slow. This command dispatches queued jobs that split each model's records into chunks by ID range, the same approach Scout's native scout:queue-import uses, but applied across all your models at once:
php artisan scout:queue-import-all
Options:
# Set the chunk size per job
php artisan scout:queue-import-all --chunk=500
# Specify which queue to dispatch jobs to
php artisan scout:queue-import-all --queue=indexing
# Queue the highest IDs first
php artisan scout:queue-import-all --order=desc
By default the jobs are queued from the lowest ID upward, which means your oldest rows get indexed first. --order=desc flips that. On a rebuild that takes hours, this puts recent content back into search early instead of last. The value has to be asc or desc, and the option requires Laravel Scout 11.4 or newer.
This is the fastest way to rebuild indexes for projects with many models and millions of rows.
scout:refresh
Flushes then imports, in one step. Useful when you need a clean re-index:
php artisan scout:refresh
You can also target a single model:
php artisan scout:refresh "App\Models\Post"
When no model is specified, it runs scout:flush-all followed by scout:import-all under the hood. The --chunk option works here too.
Production Safety
All commands ask for confirmation when APP_ENV is production. To skip the prompt (for CI pipelines or automated scripts), pass --force:
php artisan scout:import-all --force
php artisan scout:flush-all --force
php artisan scout:queue-import-all --force
php artisan scout:refresh --force
How It Works
The package scans the directories you've configured using Symfony's Finder component. For each PHP file it finds, it:
- Converts the file path to a fully qualified class name.
- Checks via Reflection that the class is a concrete (non-abstract) Eloquent model.
- Verifies the class uses Laravel Scout's
Searchabletrait.
Models that pass all three checks are collected, and the chosen Scout command (scout:import, scout:flush, or scout:queue-import) runs against each one. A progress bar tracks the operation so you can see where things stand.
If any single model fails during the operation, the command stops immediately and returns a failure exit code.