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 Bundle Laravel Package

integrated/solr-bundle

A Symfony bundle for integrating Apache Solr into PHP applications. It provides configuration and services for indexing content and running fast, scalable full-text search queries, helping teams add Solr-powered search with less boilerplate and tighter framework integration.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you run anything, accept the framing reality: this is a Symfony bundle (integrated/solr-bundle), not a Laravel package. There is no ServiceProvider, no facade, no Eloquent bridge, and no Artisan commands in the artifact. The composer require you'd instinctively run will pull in symfony/framework-bundle and likely fail your Laravel dependency graph. So the "getting started" path for a Laravel developer is read first, port second, adopt never.

Where to look first (in this order):

  1. composer.json — the PHP constraint, the symfony/* hard requirements, and the transitive Solr client (almost certainly solarium/solarium). This single file tells you whether a direct port is even viable.
  2. DependencyInjection/Configuration.php — the bundle's config tree. This is the crown jewel: it defines index names, field mappings, types, and client settings. This is the part worth porting.
  3. DependencyInjection/IntegratedSolrExtension.php — shows how config becomes services, which classes get wired, and what the client factory looks like.
  4. Resources/config/services.* — the actual service definitions and their constructor dependencies.
  5. The indexing/query classes themselves — look for Indexer, Query, Client (or Solr), and any Doctrine event subscribers.

Minimal first use case — don't port yet. Spin up Solr locally and prove you can talk to it:

docker run -d -p 8983:8983 --name solr solr:9

Then read the bundle's config shape and sketch the equivalent Laravel config file by hand:

// config/solr.php — modeled on the bundle's tree, not copied
return [
    'client' => [
        'host' => env('SOLR_HOST', '127.0.0.1'),
        'port' => env('SOLR_PORT', 8983),
        'path' => '/solr',
        'core' => env('SOLR_CORE', 'app'),
    ],
    'indexes' => [
        'products' => [
            'fields' => [
                'id'        => ['type' => 'string', 'required' => true],
                'title'     => ['type' => 'text'],
                'category'  => ['type' => 'string', 'facet' => true],
                'price'     => ['type' => 'pfloat'],
            ],
        ],
    ],
];

Your first concrete use case should be the smallest possible proof: index a handful of Product records and run one filtered+facetted query. Do this before deciding whether to fork the bundle at all — you may discover Laravel Scout + a Solr driver or raw Solarium covers you in a day.

Implementation Patterns

Every pattern below assumes the bundle is a reference and config source, and the runtime you own is either Solarium directly or a Scout-based adapter. If you genuinely intend to fork, these are the seams to preserve.

1. Own the boundary with interfaces. Never let call sites touch Solr types. Define:

interface SearchIndex {
    public function name(): string;
    public function index(array $documents): void;
    public function delete(array $ids): void;
}

interface SearchQuery {
    public function where(string $field, mixed $value): static;
    public function facet(string $field): static;
    public function highlight(string $field): static;
    public function get(): array;
}

The value of the bundle — and its only durable lesson — is that it separates config (index/field schema) from execution (client, indexer, query builder). Mirror that separation. When you later swap Solr for Meilisearch or Typesense, only the implementations change.

2. Config-driven field mappings, evaluated once. The bundle's schema lives in config, not in Solr's managed-schema XML (verify this — see Gotchas). For Laravel, keep the mapping in config/solr.php and generate Solr schema fields from it via a single Artisan command (solr:schema:push). Do not hand-edit managed-schema if config is the source of truth; you'll drift.

3. Index via Eloquent observers → queued jobs, never synchronously. The bundle leans on Doctrine lifecycle events; that doesn't carry over. Replace with:

// ProductObserver — dispatch, don't write
public function saved(Product $product): void
{
    IndexProductJob::dispatch($product)->onQueue('search');
}

public function deleted(Product $product): void
{
    DeleteFromIndexJob::dispatch($product->getKey())->onQueue('search');
}

Wrap this in an outbox: write an index_outbox row in the same DB transaction as the model save, and have the job consume from it. This is the only reliable way to avoid the dual-write drift the bundle does nothing to prevent.

4. Batch reindex as an Artisan command modeling the bundle's chunking. Look at how the bundle batches — chunk size, commitWithin, and whether it calls softCommit. Port a solr:reindex {model?} {--chunk=500} command that reads chunks, pushes documents, and commits once at the end of each chunk. For large tables, run it as an on-demand queued job, not php artisan in a terminal, so retries and pauses work.

5. Use the pluggable client adapter for tests. The description explicitly mentions "pluggable client adapters for testing and custom transports." Whatever you build, define a FakeSolrClient implementing the same interface so feature tests assert documents without a Solr instance. The bundle's adapter seam is the pattern to steal.

6. Query building mirrors the bundle's fluent shape. The bundle advertises filters, facets, and highlighting. In your adapter, keep those as first-class methods on SearchQuery so relevance and faceting work stays inside one class you can tune — not scattered across call sites.

7. Instrument the index path from day one. This package has no observability. Add a metric for last successful index timestamp per core and alert on lag. Silent indexing failures are the dominant failure mode of every Solr wrapper.

Gotchas and Tips

  • The bundle is Symfony-only. symfony/framework-bundle is a hard requirement; the config tree, service wiring, and console commands won't instantiate outside Symfony's container. Don't attempt a drop-in. Either fork-and-strip or reimplement the config parsing — usually a day or two — and skip the bundle entirely.
  • Doctrine lifecycle ≠ Eloquent lifecycle. The bundle's indexing triggers hook Doctrine entity events. Eloquent observers are close but not equivalent (mass updates bypass them, saveQuietly skips them, queued deletes lose the model). Never assume the bundle's trigger semantics transfer — verify and replace.
  • Check who owns the schema. Confirm whether the bundle pushes docs into a pre-existing core or generates managed-schema. If it generates, a package/schema change requires a coordinated full reindex with no migration tooling implied. This is the highest-risk unknown; answer it before you write any code.
  • Commit behavior is a performance trap. Solr's default commit is expensive; every wrapper's commitWithin and soft-commit handling matters more than any other tuning knob. If the bundle hardcodes commits per document, indexing will be an order of magnitude slower than batching. Expose the knob in your own adapter.
  • Never index synchronously in the request cycle. If Solr is down, synchronous indexing takes your writes down. Queue it, always, with an outbox for durability.
  • Zero stars, zero dependents, zero upstream. Treat the repo as abandoned: no CVE response, no PHP 8.2+ guarantees, no Solr 9 fixes. You are the sole maintainer of any fork. Budget it as a recurring tax; prefer a thin Solarium layer you wrote.
  • Verify the transitive Solarium version. If it pins an old major, it may block your PHP/framework upgrades — the most expensive failure mode of an unmaintained dependency. Check composer.lock of a scratch install before committing.
  • Pin a concrete Solr version and test against it. Solr 8 vs 9 differ in schema and admin API; wrappers written for one often break silently on the other.
  • Reindex without downtime. Use a core alias swap or dual-core (products_v1 → build → products_v2 → swap alias) so a full reindex never causes a user-visible search outage. No bundle feature implies this; it's operational discipline.
  • Debugging a query: append debug=true&debug.explain.structured=true and inspect the parsed query in the Solr admin UI at /solr/#/<core>/query. Log the raw request your adapter sends — wrappers routinely hide the actual params, which is where 90% of relevance bugs live.
  • curl 'http://localhost:8983/solr/app/select?q=*:*&facet=true&facet.field=category&debug=true'
    
  • Extension point worth reusing: the pluggable client adapter interface is the one truly portable idea. Copy the seam, implement your own transport (PSR-18 or Laravel's Http), and route retries/timeouts/logging through it so failures surface in your observability stack instead of being swallowed.
  • Kill criterion: if, after a one-week spike, the bundle's core indexing classes can't be instantiated without Symfony's container, abandon the fork entirely and go direct to Solarium. The from-scratch adapter almost always wins on every axis except "someone wrote the config parser" — and that parser is a day's work.
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource