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

Search Indexer Laravel Package

nramos/search-indexer

A Laravel package for adding search indexing to Eloquent models. Define indexable data, keep indexes synchronized with model events, and run flexible search queries through a simple, configurable API.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a plain Composer library (not a Laravel package), so the first step is simply:

composer require nramos/search-indexer

Because it targets Doctrine entities rather than Eloquent models, it drops naturally into a Symfony app or a Laravel app using laravel-doctrine/orm. If you are on stock Eloquent you'll get little from it — use Laravel Scout instead.

Where to look first, in order:

  1. src/ top level and README.md — with 3 stars and 0 dependents, the source is the documentation. Read the interfaces (IndexerInterface, driver/engine contracts) before the README examples; the extension contract tells you more about intent than the usage snippet does.
  2. The Meilisearch driver — it's the only first-class engine, so it encodes most of the package's assumptions (document IDs, filterable attributes, batch semantics).
  3. Any Doctrine event subscriber/listener classes — this is where the auto-indexing magic (or lack of it) lives.

Minimal first use case: index a single, small, read-mostly entity (a Product or Article) with only scalar fields, run the package's indexing command, and hit Meilisearch directly (curl or the Meilisearch dashboard) to confirm documents exist before wiring up search UI. Verify the round-trip end to end on one entity before touching a second.

Implementation Patterns

Attribute/interface marking per entity. Expect to opt entities in individually — either by PHP attribute or by implementing an indexer contract. Keep the marked entity a plain data object; anything requiring joins should be denormalized into the indexed document rather than traversed at index time.

Doctrine lifecycle wiring. The core pattern is a Doctrine event subscriber on postPersist/postUpdate/postRemove (or postFlush for batched writes) that dispatches to the indexer. Confirm from source whether the package registers this automatically or whether you must hook it yourself — this is the single biggest determinant of how much glue you write.

Indexer-per-entity-type. Define one indexer per entity rather than a generic one. Each indexer owns:

  • the index/collection name,
  • the document shape (toSearchableArray-style method),
  • the primary key used as document ID.

Custom engine via the driver contract. If you need Typesense/Elasticsearch/OpenSearch, implement the driver interface and register it. This is the package's main selling point — lean on it rather than forking. Keep the driver thin: transform Indexer → document[] into engine calls, and let the indexer own the mapping.

Batch/backfill command. For anything beyond a demo, run a console command that pages through entities in chunks (->toIterable() / ->batch()) and pushes to Meilisearch. Full reindex after every schema change is the normal workflow; treat the index as disposable.

Search → hydrate pattern. The engine returns IDs + highlights; hydrate through Doctrine by ID. Do not attempt to reconstruct entities from Meilisearch documents — you lose referential integrity and get stale data.

Gotchas and Tips

  • Doctrine proxies and lazy relations. Serializing an entity that touches a lazy collection inside an event listener will trigger extra queries or return uninitialized proxies. Build the document array explicitly, field by field.
  • postPersist vs postFlush. postPersist fires per entity inside the unit of work; a loop inserting 1,000 rows will fire 1,000 index calls. For bulk work either switch to a postFlush collector or use the batch command and disable auto-indexing for that operation.
  • Meilisearch needs schema declared up front. filterableAttributes, sortableAttributes, and searchableAttributes are index settings, not per-document hints. If filtering/sorting silently does nothing, you almost certainly didn't declare the attribute before indexing.
  • Transactions vs external index. Doctrine transactions roll back; Meilisearch calls don't. Indexing inside a transaction can leave orphaned documents. Prefer indexing after commit, and make the indexer idempotent (upsert-by-ID) so re-runs are safe.
  • Abandonment risk. 3 stars, 0 dependents, single maintainer. Pin the version in composer.json, and wrap calls behind your own thin service so you can swap engines without touching domain code. Read the changelog before composer update.
  • Laravel friction. The package doesn't know about queues, service providers, or config/ publishing conventions. Budget time for a provider, a config wrapper, and queueing index writes — don't index synchronously in request handlers.
  • Debugging: when documents silently don't appear, check in this order — (1) is the Doctrine event actually firing? (2) is the document ID stable and non-null? (3) does Meilisearch return 200 with a taskUid that you never awaited? Meilisearch indexing is asynchronous; the HTTP 200 means “queued,” not “indexed.”
  • Extension point worth using: the driver interface, for a NullIndexer in tests and in local env. Indexing during PHPUnit runs is a common source of flaky, slow tests.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource