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

Solarium Bundle Laravel Package

nelmio/solarium-bundle

NelmioSolariumBundle integrates the Solarium PHP client with Symfony, providing a preconfigured Solr client as a service, simple configuration for your Solr endpoints, and convenient querying of Apache Solr from any Symfony application.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle that wires the solarium/solarium Solr client into a Symfony container. It is not a Laravel package: there is no service provider, no config/solr.php, and no package discovery. If you are working in Laravel, the realistic options are:

  1. Use solarium/solarium directly (recommended for Laravel-only projects) and write a small service provider that mirrors this bundle's config shape.
  2. Use this bundle only if the service lives in a Symfony app — e.g. a shared search service, an admin app, or a mixed stack where Laravel calls a Symfony/Solr-facing service.

Minimal Symfony setup (bundle ^6.1, which supports both Solarium 6 and 7):

composer require nelmio/solarium-bundle:^6.1 solarium/solarium:^7.0
// config/bundles.php
Nelmio\SolariumBundle\NelmioSolariumBundle::class => ['all' => true],
# config/packages/nelmio_solarium.yaml
nelmio_solarium:
    endpoints:
        default:
            scheme: http
            host: '%env(SOLR_HOST)%'
            port: 8983
            path: /solr
            core: movies
    clients:
        default:
            endpoints: [default]
            adapter_timeout: 5

Then inject the client and run your first query:

use Solarium\Core\Client\ClientInterface;

final class MovieSearch
{
    public function __construct(private ClientInterface $client) {}

    public function search(string $q): array
    {
        $select = $this->client->createSelect();
        $select->setQuery($q === '' ? '*:*' : $q);
        $select->setRows(20);

        return $this->client->select($select)->getData()['response']['docs'] ?? [];
    }
}

Where to look first:

  • The bundle README's configuration reference for your installed major version — the YAML schema has changed between releases. Nothing in the config schema changed in 6.1.0, so an existing 6.0 config file carries over untouched.
  • The solarium/solarium UPGRADE notes for the major you install (6 vs 7); this bundle contributes configuration and DI, not query abstraction.
  • Your Solr admin UI (/solr/#/movies/schema) to confirm field names before writing any query code.

First useful use case: a search endpoint over one core, backed by a small console command or job that indexes records. Get read and write paths working against a real Solr container before adding facets or highlighting.

Implementation Patterns

Configuration-first client wiring. Define endpoints and named clients in config, then inject the default client or a named one. Keep host/port/core in env vars; do not hardcode cores in query classes. For multiple cores, define multiple clients and inject by service ID rather than switching cores at runtime.

Type-hint the interface, not Solarium\Client. With 6.1 spanning Solarium 6 and 7, depend on Solarium\Core\Client\ClientInterface and the query/result interfaces (QueryInterface, SelectQueryInterface). That keeps your application code compiling across the Solarium major boundary and lets you swap in a decorator or fake in tests.

Mirror the config shape in Laravel. If you are not using Symfony, recreate the same two-level structure: an endpoints array and a clients map, with one default. Bind ClientInterface as a singleton in a service provider and resolve it via constructor injection. This keeps the mental model identical to the bundle and makes a later migration to Symfony trivial.

Indexing as queued jobs. The common day-to-day workflow is: Eloquent model saved → dispatch IndexDocument job → build an UpdateQuery with add/delete → execute. Batch with the buffered-add plugin for bulk imports rather than one update per row. Keep indexing idempotent so retries are safe.

$update = $client->createUpdate();
$doc = $update->createDocument();
$doc->id = (string) $movie->id;
$doc->title = $movie->title;
$doc->setField('genre', $movie->genres->pluck('name')->all());

$update->addDocument($doc);
$update->addCommitWithin(5000); // avoid hard commits in the request path
$client->update($update);

Deletes before re-index. For updates where fields can disappear, delete by ID then add, or use atomic updates deliberately. Solr merges documents, so stale fields survive plain add calls.

Query objects per use case. Build a small MovieQuery class per screen or endpoint that returns a select query object, then a single executor that applies pagination, facets, and hydration. This keeps controllers thin and makes it easy to add highlighting or spellcheck later.

Hydration. Solarium returns arrays, not models. Map $result->getData()['response']['docs'] into DTOs or re-fetch Eloquent models by ID for detail views. Do not hydrate full models from Solr alone unless you accept eventual consistency.

Testing. Do not mock Solarium's internals. Either run a real Solr via Docker in CI, or wrap the client behind your own SearchClient interface and fake that. This also gives you a seam to swap in a different engine later.

Health and observability. Add a ping check to your health endpoint and log query time plus responseHeader.QTime. Solr failures are usually timeouts or config drift, and both are easier to diagnose with the raw query string logged.

Gotchas and Tips

  • It is not a Laravel package. Installing it in Laravel gets you the library plus Symfony DI expectations; the bundle will not register itself. Budget for a thin provider or use Solarium directly.
  • Version alignment is the main failure mode — and 6.1 widens the matrix. Bundle 6.1.0 accepts solarium/solarium ^6.0 || ^7.0. Pin the bundle and Solarium together in composer.json, and read the README section matching your installed tag — config keys like endpoints (map vs. DSN list) and adapter options differ across majors. Note the bundle's own constraint did not change its config schema; only the supported Solarium range moved.
  • Upgrading Solarium 6 → 7 is your decision, not the bundle's. 6.1.0 makes 7 installable, it does not force it. Bumping Solarium is a separate composer require step, and 7 drops APIs deprecated through the 6.x line — grep for deprecated constructors, adapter wiring, and removed helper methods before you flip the constraint. If you want a no-code-change release, take 6.1.0 and stay on Solarium 6.
  • No new config keys in 6.1.0. Treat it as a compatibility release: no migration, no YAML edits, no service-ID changes. If a deploy "needs" a config change after upgrading, you have accidentally also moved a major elsewhere.
  • Default client resolution. If you define multiple clients and nothing sets a default, injection by type can be ambiguous. Set the default explicitly, or inject named services.
  • Commit semantics. addCommit() in a request path will wreck latency on a busy index. Prefer commitWithin, auto-commit, or a scheduled commit. Hard commits are expensive; soft commits trade durability for speed.
  • Deletes are not free. deleteByQuery on a large index can be slow and is not transactional. For reindexing, consider a second core plus an alias swap instead of deleting in place.
  • Schema drift is silent. Solr will accept fields that exist and reject or ignore others depending on schema mode. Check responseHeader.status and error bodies; Solarium throws on HTTP errors but partial failures can be subtle. Validate field names against the live schema in tests.
  • Adapter timeouts and TLS. Tune adapter_timeout and connection timeout for both reads and indexing. If Solr sits behind auth or a proxy, configure that at the endpoint/adapter level rather than patching requests. The default curl adapter bypasses Laravel's HTTP client, so Http::fake() will not intercept anything.
  • No ORM, no pagination helper. You get start/rows and numFound. Build pagination yourself and cap deep paging; Solr's start costs grow with offset.
  • Dynamic fields need deliberate naming. *_s, *_i, *_t suffixes are schema conventions. Getting them wrong yields either type errors or fields that never match a query.
  • Extension points worth knowing. Custom plugins (Solarium\Core\Plugin\AbstractPlugin) for logging or request decoration, custom adapters, and Solarium's event dispatcher for pre/post request hooks. This is the clean way to add tracing without touching call sites — and plugin/event signatures are exactly the kind of thing that shifts between Solarium majors, so check them when you cross to 7.
  • Debugging tips. Log the fully built query string and endpoint URL before execution — most "empty results" bugs are a wrong core path or a filter query on a mismatched type. Compare against the Solr admin UI's query tab with the same parameters.
  • Operational quirks. Managed resources and the Config API are often disabled in production; do not build deployment logic around them. Also check whether your host allows the /solr path — some managed providers require a different base path and a core name embedded in the URL.
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.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment