Weave 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

Laravel Scout Bulk Actions Laravel Package

mozex/laravel-scout-bulk-actions

Laravel Scout's commands handle one model at a time. This package auto-discovers every model using the Searchable trait and lets you import, flush, or refresh them all with a single command, plus queued bulk imports for faster indexing.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This is a thin orchestration layer, not a runtime library. It adds one service provider and a set of Artisan commands; there is no footprint in the request path, no model trait to add, no schema change, no service binding, and no event hooks. That makes it architecturally cheap to adopt and equally cheap to remove — a meaningful de-risking property for a TPM, because the exit cost is one composer remove plus deleting a config file.

The mechanism is straightforward and inspectable: Symfony Finder walks model_directories, file paths are converted to FQCNs, Reflection confirms each class is a concrete, non-abstract Eloquent model, the Searchable trait is verified, and Scout's native scout:import / scout:flush / scout:queue-import is then invoked per model behind a progress bar. Because it delegates rather than reimplements, engine behavior (Algolia, Meilisearch, Typesense, database, collection drivers) is inherited from Scout — the package stays engine-agnostic and Scout upgrades carry most of the compatibility burden.

Fit is strongest in two scenarios: applications with roughly ten or more searchable models where per-model scout:import calls have become a deploy-script ritual, and platform teams that currently own a hand-rolled version of exactly this wrapper. Below ~3 searchable models the package adds a dependency to solve a problem that doesn't exist yet.

Integration feasibility. Low. composer require, auto-discovery, and a single published config file whose only real decision is model_directories. No application code changes. A developer can validate the discovery set in an afternoon on a staging branch.

Technical risk.

  1. Fail-fast with no resume — the dominant risk. The README states that if any single model fails, the command stops immediately. In a scout:refresh that means a partially flushed and partially imported index with no checkpoint, no per-model isolation, and no restart-from-here. Recovery is a full re-run, which for large datasets may be hours.
  2. Silent discovery omissions. Only models that use Scout's Searchable trait directly are detected. Models inheriting searchability from a base class, or living outside configured directories, will be skipped — and the command still exits 0. A green pipeline with a stale index is the worst failure class here, because nothing signals it.
  3. Destructive defaults. scout:flush-all and the no-argument scout:refresh are full search-outage operations. --fresh narrows the gap to per-model import duration, which is a genuine improvement, but the package offers no alias-swap or shadow-index rebuild. Any zero-downtime search requirement must be solved at the engine layer, outside this package's scope.
  4. Weak machine-readability. A progress bar and exit codes are the only output. No --dry-run, no JSON summary, no structured logging. CI and orchestration wrappers will need to be written in-house.
  5. Bus factor. 14 stars, 0 dependents, single maintainer. Counterweights: MIT license, small auditable surface, disciplined changelog/release cadence, published docs site, and a Laravel Boost skill — all signals of competent maintenance rather than abandonment. Fork cost is low.

Key questions.

  • How many searchable models do we actually have, and do any inherit Searchable through a base class or trait composition rather than declaring it directly?
  • Is search availability during reindex a business requirement? If yes, this package cannot satisfy it alone — what is the engine-level strategy?
  • What is our recovery story for a mid-rebuild failure: full re-run, or do we need resumability we don't have?
  • Are our models all under app/Models, or do we need glob patterns for a modular/domain layout?
  • Is laravel/scout at ^10.18 or ^11? Version 1.8.0's --fresh and --order depend on the lower bound.
  • Do we accept a single-maintainer dependency for a production deploy path, and if not, are we prepared to vendor/fork?

Integration Approach

Stack fit. Requires PHP 8.2+, Laravel 11–13, and laravel/scout ^10.18 || ^11. Version 1.3.1 dropped PHP 8.1 and Laravel 10, so any application still on Laravel 10 must pin to ^1.2.4 and forgo --fresh, --order, and the queued bulk command (introduced in 1.5.0). This is a real fork in the support matrix worth confirming before scoping.

Because the package shells out to Scout rather than talking to an engine, it is driver-agnostic — the same integration works for Algolia, Meilisearch, Typesense, and the database driver. That is a genuine compatibility asset and means engine choice does not gate adoption.

Migration path. Three viable shapes, ordered by effort:

  • Replace a shell script — the common case. Existing Makefile targets, deploy hooks, or bin/reindex.sh collapse into one scout:refresh --force. Lowest risk, immediate payoff.
  • Replace an in-house Artisan command — the package becomes the maintained version of something internal, and the internal command plus its tests are deleted. Requires confirming behavior parity, especially around failure semantics.
  • Supplement existing calls — leave targeted per-model reindexing in place for hot paths and adopt the bulk commands only for full rebuilds and environment provisioning.

No data migration is involved; index contents are reconstructed from the database. Rollback is reverting the deploy script and removing the package.

Compatibility considerations. Config caching (config:clear after changing model_directories in production) is a documented gotcha that will bite in cached-config pipelines. Multi-tenant applications get no tenant scoping — a bulk import indexes every tenant at once, which may be fine or may be a rate-limit problem. Octane is irrelevant since everything is CLI. scout:queue-import-all depends on your queue worker topology; the --queue=indexing option lets you isolate indexing from user-facing jobs, which should be used.

Sequencing.

  1. Inventory. Enumerate searchable models and compare against what the package's discovery would find (verify direct Searchable usage, confirm directory coverage).
  2. Local/staging install. composer require, publish config, run scout:flush-all and scout:import-all against a non-production index. Confirm the discovered model list matches the inventory.
  3. Engine validation. Run a full scout:refresh against a staging index of production-like volume; measure wall-clock time, memory, and engine throttling behavior. This produces the numbers that justify or kill the queued path.
  4. Pipeline wiring. Add --force to any non-interactive context, since every command prompts for confirmation under APP_ENV=production. Wrap the command to capture exit codes and emit a structured summary, compensating for the missing --dry-run.
  5. Move to queued path if needed. Introduce scout:queue-import-all --queue=indexing --order=desc once volume justifies it, with monitoring on queue depth and job failure rate.

Operational Impact

Maintenance. Small dependency surface (Symfony Finder, laravel/prompts, Scout) and a maintainer who ships regularly — fourteen tagged releases with dependabot-driven version bumps. Composer updates should be routine, though the laravel/prompts constraint has churned across three major ranges (0.1 → 0.2 → 0.3), which historically caused a patch release (1.2.3 "Fix laravel/prompts dependency"). Budget for occasional transitive-constraint friction. The package should be pinned to a minor version range and upgraded deliberately, not floated.

Support. No SLA, no commercial backing, one maintainer, sponsor-funded. Security reports go to a personal email rather than a private advisory process. For a package on the deploy path this is acceptable because the blast radius is bounded and MIT + small code means you can fork in a day, but it should be an explicit, recorded acceptance rather than an oversight. The changelog discipline substantially reduces triage cost when something breaks.

Scaling. Two regimes. Synchronous commands run in a single PHP process: wall-clock time scales with total row count across all models, memory is bounded by chunk size but iteration is serial, and the command holds the terminal for the duration. That is fine to roughly a few hundred thousand documents and painful beyond it. The queued path (scout:queue-import-all) splits each model by ID range and dispatches jobs, so throughput scales horizontally with worker count and the operator is decoupled from the run. --order=desc is a genuinely thoughtful detail: on a multi-hour rebuild it puts recent content back into search first instead of last, which materially improves perceived quality during a long reindex.

The unaddressed scaling dimension is the search engine itself — chunk sizes, queue concurrency, and engine rate limits are three dials that interact, and the package only exposes the first.

Failure modes. Ranked by operational severity:

  • Partial rebuild with no resume. Fail-fast mid-refresh leaves some models flushed and unimported. Mitigation: run --fresh per model instead of a global flush, keep a pre-run snapshot, and treat any non-zero exit as "search is degraded" in the incident runbook.
  • Silent discovery gaps. A model outside model_directories is invisible and the command exits 0. Mitigation: assert the discovered model count against a hard-coded expected list in CI.
  • Confirmation prompt in automation. Without --force, production runs block on an interactive prompt and hang the pipeline. Trivial but a classic.
  • Stale config cache. Changing model_directories without config:clear silently scans the old paths.
  • Queue backlog and job failure. The queued path can saturate workers or flood the engine; failed chunk jobs need a dead-letter review process, and partial completion is not surfaced by the dispatched command, which exits after dispatching.
  • Search outage window. Inherent to flush-then-import; --fresh minimizes but does not eliminate it.

Ramp-up. Near zero. Any Laravel developer understands php artisan scout:import-all --force from the command name alone, and the README is unusually good — options, the distinction between --fresh and refresh, the --order semantics, and production-safety behavior are all documented with rationale rather than just syntax. The Laravel Boost skill reduces AI-assistant hallucination risk during onboarding, including flagging the direct-trait-use pitfall.

The realistic ramp-up cost is not learning the package; it is building the surrounding discipline the package doesn't provide — a model inventory assertion in CI, a captured exit-code wrapper, and an incident runbook entry for "index is partial." Budget a day for adoption and a sprint for the guardrails, and treat the guardrails as the actual deliverable.

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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core