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

Solr Laravel Package

ibexa/solr

Ibexa Solr search engine bundle for Ibexa DXP, providing the Solr search backend implementation. Includes unit and integration test setup instructions for contributors.

View on GitHub
Deep Wiki
Context7

Getting Started

This bundle is not a library you call directly — it plugs a Solr backend into Ibexa's SearchService abstraction (ibexa/core). Day-to-day you keep writing $searchService->findContent(new LocationQuery(...)) and only touch this package for configuration, indexing, and extending the translation layer.

Minimal path:

  1. Install Ibexa DXP first, then the engine and a Solr server:
    composer require ibexa/solr
    
    Register the bundle in config/bundles.php (Ibexa\Solr\IbexaSolrBundle) and load its routing/services if your install doesn't auto-wire it.
  2. Provision Solr. Use the official ibexa/solr image or your own Solr 9.8+ node. The core schema/config the bundle expects lives in this package under src/lib/Resources/config/solr/ (schema.xml, solrconfig.xml, stopwords/synonyms/protwords). Copy them into the Solr server's core config directory — do not hand-edit the vendor copy.
  3. Configure the connection (config/packages/ibexa_solr.yaml or via env):
    ibexa_solr:
        connections:
            default:
                # or use SOLR_DSN / SOLR_CORE env vars
                dsn: '%env(SOLR_DSN)%'   # e.g. http://solr:8983/solr
                core: '%env(SOLR_CORE)%' # e.g. collection1
        http_client:
            timeout: 30
            max_retries: 3
    
  4. Create the core and switch the engine for a siteaccess:
    php bin/console ibexa:solr:create-core
    
    ibexa:
        system:
            default:
                search:
                    engine: solr
    
  5. Reindex and verify:
    php bin/console ibexa:reindex --iteration-limit=500
    
    Then run any existing front-end query (a LocationQuery with Criterion\FullText and a facet) and diff results against the legacy engine.

Where to look first in the repo: DependencyInjection/ (all config keys and service tags), Resources/config/solr/schema.xml (field naming conventions such as *_txt, *_s, *_id, *_b, *_dt, *_l, *_geolocation), the criterion/sort-clause visitor directories, and the field-mapper directory. Those four areas answer 90% of "why is my query behaving differently" questions.

Implementation Patterns

Read path — stay inside the Search API. Criteria, sort clauses and facets you already use are translated to Solr syntax by visitors. Notable ones this bundle provides: FullText, ContentName, Image, IsBookmarked, IsUserEnabled, IsContainer, MapLocationDistance, plus date metadata variants. If a criterion works on the legacy engine but returns wrong results on Solr, the visitor is the first suspect, not your query.

Write path — event-driven indexing. Content publish/update/delete events are picked up by the indexer; there is no manual "add to index" step in normal code. For bulk loads, disable live indexing (defer via the indexer/--no-interaction style batching or your own queue), then run ibexa:reindex --iteration-limit=N in chunks so you don't blow memory or spam Solr commits.

Custom criterion pattern. This is the most common real extension:

final class MyFlag extends Criterion { public function __construct(public string $value) {} }

final class MyFlagVisitor extends CriterionVisitor
{
    public function canVisit(CriterionInterface $criterion): bool
    { return $criterion instanceof MyFlag; }

    public function visit(CriterionInterface $criterion, ?CriterionVisitor $subVisitor = null): string
    { return sprintf('my_flag_s:"%s"', addcslashes($criterion->value, '"\\')); }
}

Register with the criterion-visitor tag used by the bundle (since IBX-9650 these are collected through a tagged iterator — check Resources/config/*.yaml in the installed version for the exact tag name, which was rebranded in 5.x), then clear cache. Add a sort-clause visitor in the same way if you need ordering.

Custom field type pattern. Indexing, filtering, sorting, faceting and spellchecking all depend on the Solr field existing with the right dynamic-field suffix. Three coordinated changes:

  1. Map the value in a content field mapper (extend the provided content field mapper classes, tag it) — produces the document field.
  2. Add the field definition to schema.xml or rely on a matching dynamic field (e.g. *_txt, *_s) — safest is to mirror the naming convention so the dynamic rule applies.
  3. Recreate the core / reload config and full-reindex.

Facets and aggregations. Use the aggregation API (TermAggregation, RangeAggregation, CountryTermAggregation, field-relation variants) rather than deprecated Facets. Custom aggregations need their own visitor + result extractor, same registration pattern as criteria. Note the recent fix for CountryTermAggregation ISO/IDC code collisions — bump to ≥4.6.30/5.0.8 if you aggregate countries.

Embeddings / vector search. Newer releases add dense-vector dynamic fields keyed by dimension suffix and an embedding visitor, so you can index an embedding per content and query by vector. Treat as additive: it only works if your schema includes the vector field type and you control the embedding generation pipeline yourself.

Multi-core / SolrCloud. CORES_SETUP=single is the simple path. multi maps per-language cores via SOLR_CORE_<LANGUAGE>-style env vars and an endpoint resolver; searches are fanned out across cores and merged. Pick this only if you have genuine language-scale volume — it doubles your indexing and debugging cost.

CI pattern. Copy the integration-test recipe from the README: unit tests run with php vendor/bin/phpunit --bootstrap tests/bootstrap.php; integration tests need a live Solr with CORES_SETUP=single and run against vendor/ibexa/core/phpunit-integration-legacy-solr.xml. Make the host configurable (IBX-5133 added that) so it works in containers.

Local development. Run Solr in Docker alongside the app, mount the schema/config from the vendor path, and keep a second, throwaway core you can delete/recreate freely — you will be doing it often.

Gotchas and Tips

  • Schema changes require a full reindex, not a cache clear. Solr rejects or silently ignores fields that don't exist. Because schema.xml is full of dynamicField wildcards, a misnamed field often doesn't error — it just never matches. If a filter silently returns everything or nothing, inspect the generated query with debug=query in the Solr admin UI.
  • Visibility lag is usually commit configuration, not indexing. autoSoftCommit/autoCommit in solrconfig.xml govern how quickly new content appears. Don't add sleep() to your feature tests — tune commit settings or commit explicitly in tests.
  • Deep paging is capped. Solr's max_results/offset behaviour means large offset values throw or truncate. Keep pagination bounded or design around it; don't assume offset=50000 works because the legacy engine allowed it.
  • Location vs Content is a block-join. Locations are indexed as child documents of their content (_root_, [child] filters). Sorting or filtering on Location fields behaves differently from content fields, and "wrong count per location" bugs are nearly always a nesting issue.
  • Always set the language. _language_id and language-specific text fields are what make Criterion\LanguageCode and analysis work. A query without a language scope can return surprising or empty results across siteaccesses.
  • Escaping is your job for user input. Solr reserved characters (+ - && || ! ( ) { } [ ] ^ " ~ * ? : \ /) break queries. Use the provided full-text criterion for free text rather than concatenating raw strings; if you build a visitor, escape with addcslashes and quote phrases.
  • Custom visitors "not firing" is almost always one of: stale container cache, the service tag not applied, or a canVisit() that never matches because you checked against an interface instead of the concrete criterion. The bundle itself moved from Criterion type hints to CriterionInterface (IBX-8534) — follow that.
  • Connection and auth quirks. DSN path and core name are separate concerns; a wrong SOLR_CORE yields 404s that surface as generic search exceptions. Basic-auth credentials are now redacted from error output (IBX-11617) — so if you were relying on seeing them in logs, you won't; check the connection config instead. Timeouts/retries are configurable per connection (IBX-3863); raise retries for bulk reindex, lower them for web requests.
  • Version matrix is tight. PHP 8.3, Symfony 7.x, Solr 9.8+ in current branches. The 4.6.x and 5.0.x lines diverge — pick the branch matching your DXP version, and check release notes for behavioural fixes rather than assuming parity.
  • Licensing. Dual-licensed: Ibexa Business Use License (needs a DXP subscription) or GPLv2. Verify which applies before vendoring or forking — NOASSERTION in metadata is not "public domain".
  • Small ecosystem. ~5 stars and essentially zero independent dependents means no Stack Overflow safety net; the authoritative docs are on doc.ibexa.co, and upstream issue trackers are behind the Ibexa support portal. Budget time to read DependencyInjection/Configuration.php and the service YAMLs directly when something is undocumented.
  • Debugging toolkit: ibexa:reindex --verbose for indexing failures, Solr admin UI → Analysis for analyzer/stopword/synonym problems (these live in Solr config files, not PHP, so they need a core reload), and Solr debug=query to see the exact translated query. When a query is wrong, log both the Ibexa Criterion tree and the emitted Solr string — the gap between them is always a visitor.
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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator