mdiyakov/doctrine-solr-bundle
Symfony bundle that integrates Apache Solr with Doctrine ORM entities, letting you index and search your database records through Solr. Provides entity mapping, automatic indexing, and query building for fast full-text search in Symfony applications.
Reality check first. The bundle still targets Symfony 2/3 and its dependency graph is frozen in the 2018 era, despite the v1.1.1 patch (rollback wrapper, clean command, multi-EM support, manager unit tests). That patch is a maintenance bump, not a modernization — it does not add Symfony 4+ flex support, attribute mapping, or a current Solarium constraint. If you're on Symfony 4+/PHP 7.4+/modern Solr, assume it will not install cleanly and budget for a fork. If you're maintaining a legacy Symfony 2.8/3.x app talking to an older Solr, it remains a pragmatic way to get entity-backed search working — and v1.1.1 removes a couple of real sharp edges, so it's worth pinning to that tag rather than an older one.
Minimal path:
mdiyakov/doctrine-solr-bundle at v1.1.1, and pin symfony/* and solarium/solarium to versions that existed in 2018. Verify the transitive dependency graph before letting Composer update anything else. If you were on an earlier tag, read the v1.1.1 diff — it touches the entity manager wiring, so your service definitions may need adjusting.app/AppKernel.php (or config/bundles.php if you're on 3.4+) under the dev/prod environments you need.DependencyInjection/Configuration.php first; the config tree is the source of truth. v1.1.1 added multi-entity-manager support through Doctrine Registry, so expect a config key that lets you name which EM(s) to index rather than assuming doctrine.orm.default_entity_manager.$em->flush() throws. Resolve EMs from the bundle's wrapper (or the Registry service) in your own code rather than the raw doctrine.orm.entity_manager alias — otherwise you lose the rollback behaviour.Annotation/ for the exact names (@Solr\Document, @Solr\Id, @Solr\Field, and likely a type/transformer attribute). Start with one entity and 3–5 fields.Command/). v1.1.1 ships a clean-all-Solr-data command alongside the index command — useful for a clean rebuild. Verify in the Solr admin UI (/solr/#/<core>/query) that documents landed.Annotation-driven mapping on entities. Mark an entity as a document, its ID field, then searchable/stored fields with their Solr type. Keeping mapping on the entity travels with the model but couples domain objects to a search concern; if that offends you, map a dedicated read-model/DTO entity instead.
Automatic sync via Doctrine events. The bundle registers a Doctrine event subscriber hooking postPersist, postUpdate, postRemove. This is the "it just works" path — but only for changes made through the ORM. Bulk DQL updates, raw SQL, and direct DB writes bypass it entirely.
Rollback-safe flush (new in v1.1.1). The new EM wrapper listens for exceptions thrown during $em->flush() — including from other EntityListeners — and rolls back the corresponding Solr mutations so the index doesn't drift from the DB when a transaction fails. Lean on it: inject your own services with the wrapped EM where indexing matters, and don't catch-and-swallow flush exceptions above it. Note it protects the index for that flush, not across requests; if Solr itself is down, behaviour is still whatever the listener does on transport failure (check EventListener/).
Multiple entity managers (new in v1.1.1). If you have more than one EM (e.g. a separate read/legacy connection), you can now register all of them via Doctrine Registry and index across them, rather than the bundle picking up only default. Bind each document type to an explicit EM + client name in config.
Manual indexing for bulk operations. For imports and seed data, disable auto-sync and run the console reindex in batches. A clean-then-rebuild cycle is now cleaner thanks to the clean command:
# destructive: wipes the core, then chunked rebuild
app/console doctrine:solr:clean --client=default
app/console doctrine:solr:index --entity=AppBundle:Product --offset=0 --limit=5000
Confirm whether the clean command prompts before deleting — treat it as a production hazard unless it does.
Search side: two-step query. Query Solr for IDs + scores, hydrate with findBy(['id' => $ids]), then re-sort in PHP to match Solr order. The bundle doesn't provide ODM-style entity hydration.
Related entities / denormalization. Foreign keys are useless in Solr. Use the field transformer/mapping hook to flatten related data (product.category.name) at index time; eager-join to avoid N+1 during reindex.
Multi-core setups. One client per core, each document type bound to its core. Keeps product and content search independent, and commit/reindex on one doesn't disturb the other.
Wrap search in a service. Introduce ProductSearchService owning query construction, pagination, facets, and ID→entity hydration. That's your seam for swapping the bundle out.
doctrine.orm.entity_manager directly, or using a third-party EM decorator, bypasses it. Audit your service definitions.cache:clear — stale metadata is the #1 cause of "my new field isn't in Solr."UPDATE, INSERT ... SELECT, and migrations silently desync the index. Add a post-deploy reindex or a reconciliation job comparing DB and Solr counts.commit isn't immediate and looping commits is CPU-heavy. Batch add operations, commit once per batch.pdate field and you get 400s at index time or silent filter failure. Align your schema with the bundle's field mappings before declaring success.EventListener/ and the new EM wrapper. Most bugs are Solr-side.default binding is easy to mis-bind; reference explicit names everywhere rather than relying on default.How can I help you explore Laravel packages today?