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

Elasticsearch Bundle Laravel Package

mitru/elasticsearch-bundle

mitru/elasticsearch-bundle is a PHP package that simplifies integrating Elasticsearch into your application, offering configuration and service wiring for indexing and querying data. A lightweight starting point for adding search with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

First, calibrate expectations: mitru/elasticsearch-bundle is a Symfony bundle, not a Laravel package. It will not auto-register in Laravel — there's no bundle kernel, no config/bundles.php, and no DependencyInjection compiler pass to hook into. With 0 stars and 0 dependents, treat it as unvetted third-party code you are adopting, not a library you are consuming.

Minimal path in a Laravel app:

  1. composer require mitru/elasticsearch-bundle — then immediately inspect composer.json for two things: the PHP version constraint and, critically, the elasticsearch/elasticsearch (elasticsearch-php) constraint. That determines which client API you're coding against (7.x $client->index(['index' => ..., 'body' => ...]) vs 8.x named-argument style).
  2. Read src/ in this order: the *Bundle class → DependencyInjection/*Extension.php → the service definition file (services.xml/services.yaml) → any ClientFactory/ClientBuilder wrapper. Those four files tell you 90% of what the bundle actually does. Most bundles of this shape are a thin factory around elasticsearch-php plus a config tree.
  3. Skip the bundle machinery entirely. In Laravel you almost certainly want the underlying client, not the Symfony service wiring:
// config/services.php or a dedicated config/elasticsearch.php
'elasticsearch' => [
    'hosts' => [env('ELASTIC_HOST', 'http://localhost:9200')],
],
// App\Providers\ElasticsearchServiceProvider
$this->app->singleton(Client::class, fn () => ClientBuilder::create()
    ->setHosts(config('elasticsearch.hosts'))
    ->build());
  1. First use case: index one Eloquent model and search it. Don't start with the bundle's repository/mapping layer — start with a raw index() and a match query so you learn the client contract before layering abstractions.

If the bundle's value proposition turns out to be document mapping + repositories (the FOSElasticaBundle/ONGR pattern), decide early whether to reimplement that thin layer yourself rather than fight the DI mismatch. It's usually ~100 lines.

Implementation Patterns

The Symfony-native pattern (for reference, or if you actually are on Symfony): autowire the client service, inject it into a repository/service class, and keep queries in dedicated query-builder classes rather than scattered through controllers. Config lives in config/packages/mitru_elasticsearch.yaml. If the bundle exposes a document-manager abstraction, use it for mapping and drop to the raw client for anything the abstraction doesn't cover — do not contort your query into the bundle's DSL.

The Laravel-native pattern (what you'll actually do):

Indexing via model events. Keep it out of the request cycle:

class Product extends Model {
    protected static function booted(): void {
        static::saved(fn ($p) => IndexProduct::dispatch($p)->onQueue('search'));
        static::deleted(fn ($p) => RemoveProduct::dispatch($p->id)->onQueue('search'));
    }
}

Make jobs idempotent (index with an explicit id, not a blind create) so retries and out-of-order delivery are harmless.

Bulk for backfills, never per-document in a loop. Use the bulk API with batches of 500–1000 and refresh left default during the fill, then a single refresh at the end. This is the single biggest performance lever.

Alias-based reindexing. Never point code at a concrete index name. Write to products_v2, then atomically swap the products alias. This makes schema changes a deploy step rather than an outage:

$client->indices()->updateAliases(['body' => ['actions' => [
    ['remove' => ['index' => 'products_v1', 'alias' => 'products']],
    ['add'    => ['index' => 'products_v2', 'alias' => 'products']],
]]]);

Configuration over magic. Keep index names environment-prefixed (staging_products) so a misconfigured .env can't corrupt production. One config file, one place to read index names from — no string literals in services.

Testing. Bind a fake client in tests or, better, run against a real container in CI via Testcontainers/Docker Compose. Assertions on "did we send the right bulk payload" are cheap and catch most mapping bugs; assertions on search relevance are not — don't try.

Gotchas and Tips

  • Bus factor is the headline risk. Zero stars, zero dependents, no issue history. Pin the exact version in composer.json, and if the package is load-bearing, vendor the source into your repo or fork it. Assume no upstream security patches and no answers to your questions.
  • elasticsearch-php major versions are not compatible with each other. The 8.x client changes constructor and method signatures (named args, no body wrapping in places). Whatever constraint the bundle declares, verify it matches the server version you're running — an 8.x client against a 7.x cluster fails in confusing, non-obvious ways.
  • The Symfony DI container will not help you in Laravel. If you try to use the bundle's services, you'll be hand-instantiating classes with constructor args the bundle expected the container to supply. Read the service definition file as documentation of dependencies, then wire them yourself.
  • Config key names drift. Watch for hosts vs connections, index_prefix vs prefix, and whether the config tree is strict (->cannotBeEmpty()) or silently ignores typos. Symfony config components often ignore unknown keys unless the tree is strict — a typo'd key can mean the default silently wins.
  • Mapping: prefer explicit over dynamic. Dynamic mapping will happily turn your sku: "0012" into a number-like type or explode on a mixed-type field. Define mappings up front, and remember you cannot change a field's type in place — you need the alias reindex dance.
  • refresh will bite you in tests and in read-after-write UX. Default refresh interval is 1s. Use refresh: 'wait_for' on writes you immediately read back in tests; use refresh: true only in tests, never in production bulk paths.
  • Debugging: attach a logger to the client (PSR-3) and dump the request/response; then verify the same query by hand with curl against _search and _cat/indices?v. Most "the bundle is broken" issues are a mapping problem or a document that never got indexed. Check document count first, query second.
  • Extension points, in order of preference: (1) your own wrapper service around the client; (2) decorating the injected client service (Symfony) / rebinding the singleton (Laravel); (3) Symfony event subscribers if and only if you're genuinely on Symfony. Reach for the bundle's own extension hooks last — undocumented hooks in a 0-star package are liabilities, not APIs.
  • Timezone and serialization. Eloquent Carbon instances and null fields serialize inconsistently. Normalize to ISO-8601 strings and decide explicitly whether null means "remove from index" or "store as null" before you write your first document — it's much harder to fix retroactively.
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.
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
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect