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

Elastica Bundle Laravel Package

fos-gregooz/elastica-bundle

Symfony bundle that integrates Elasticsearch via the Elastica client, letting you define indexes and mappings in configuration and keep them in sync with Doctrine entities through automatic listeners. Provides repository services so you can run search queries without touching the low-level client.

View on GitHub
Deep Wiki
Context7

Getting Started

Read the composer.json before anything else. The package name is fos-gregooz/elastica-bundle but the namespace is FOS\ElasticaBundle — it's a Symfony Bundle subclass, a fork of friendsofsymfony/elastica-bundle. On a Laravel project, composer require fos-gregooz/elastica-bundle installs the code, then nothing happens: no service provider auto-discovery, no config/elastica.php to publish, no artisan commands registered, no facade. The composer.json will not declare extra.laravel.providers, and even if it did, the bundle boots through Symfony's Kernel/bundle config pipeline, not Laravel's container.

The minimal path for a Laravel developer, which is what any competent reader should do first, is not this package at all:

  1. composer require laravel/scout babenkoivan/elastic-scout-driver
  2. Set SCOUT_DRIVER=elastic and ELASTICSEARCH_HOST in .env.
  3. php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider" and php artisan vendor:publish --provider="Babenkoivan\Scout\Elasticsearch\ElasticsearchServiceProvider".
  4. Add use Laravel\Scout\Searchable; to the model you want to index.
  5. php artisan scout:import "App\Models\Product".
  6. Product::search('blue widget')->take(20)->get().

That is the equivalent day-to-day workflow the FOSElasticaBundle represents in Symfony (fos_elastica YAML mapping + fos:elastica:populate + a configured repository service). If search is on the roadmap, this is the path — not the bundle.

Where to look first when the framework question is unresolved:

  • If your service is actually Symfony, use friendsofsymfony/elastica-bundle upstream, not this fork. Zero stars and zero dependents means no maintainer, no release discipline, no CVE path.
  • If your service is Laravel, look at laravel/scout and the Elasticsearch driver first, then the official elasticsearch/elasticsearch client if Scout is too opinionated.
  • Only look at this repo if someone is specifically debugging a patch the fork carries that upstream does not — and then diff it against upstream before reading any more.

First use case: index App\Models\Product and search by name + description. If you follow Scout, this is a half-day. If you try to follow the bundle's documentation, every step lands on Symfony concepts (Kernel, config/packages/fos_elastica.yaml, fos_elastica.index.* services) that do not exist in a Laravel tree.

Implementation Patterns

Pattern 1 — Scout + Elasticsearch driver (the default).

The model uses the Searchable trait; custom index mapping goes on the driver via config/scout.php. Index shape comes from searchableAs() (the alias-friendly index name) and toSearchableArray() (the document body). The two extension points a developer actually uses day-to-day are searchableAs() to control index naming (and to support products_v1 / products_v2 alias swaps later) and toSearchableArray() to flatten relations before they hit ES. For custom query DSL that Scout's fluent builder does not expose, override the searchableUsing() builder or drop to the driver's getClient() directly.

Pattern 2 — thin repository over the official client.

For anything beyond CRUD search (facets, search_after pagination, custom analyzers, ingest pipelines), bind Elastic\Elasticsearch\Client as a singleton in AppServiceProvider and wrap it in a ProductIndex class with index(), bulk(), delete(), search() methods. Bulk reindexing uses $client->bulk(['body' => $rows]) where each pair is ['index' => [...]] then the doc — inspect $response['errors'] on every call. Alias-based cutover is two calls: indices()->create(['index' => 'products_v2', 'body' => $mapping]), load data, then indices()->updateAliases(['body' => [['remove' => ...], ['add' => ['index' => 'products_v2', 'alias' => 'products']]]]). This is the pattern to reach for the moment the bundle's Symfony config starts feeling like a cage — which, on Laravel, is immediately.

Pattern 3 — what the bundle actually gives its Symfony users (for parity).

A fos_elastica: config tree with clients, indexes, types, and Doctrine listener wiring, plus a fos:elastica:populate command. If you're evaluating this fork specifically, the only reason to keep reading is to extract that YAML mapping shape as a reference for the equivalent raw JSON mapping you'd write against the official client. The translation is near 1:1: mappings.properties becomes the ES mapping body verbatim.

Integration tips.

  • Queue the indexing. Set SCOUT_QUEUE=true in .env and run php artisan queue:work, or dispatch a ReindexModel job on created/updated/deleted events if you're using Pattern 2. Never index synchronously inside an Eloquent observer in production.
  • Use model observers to invalidate a searchable cache if you cache search results; ES's refresh delay means a "search immediately after write" flow will return stale data unless you ->refresh('wait_for'), which Scout does not expose — so design for eventual consistency instead of trying to defeat it.
  • For migrations, use php artisan scout:import "App\Models\Product" --chunk=500 and monitor worker memory. Scout's importer is chunkById-based but each document is serialized in full; large models OOM around chunk sizes of a few thousand.
  • When you need the bundle's concepts — declarative mapping, populate command, listener-based sync — replicate the concept, not the machinery: a config/elasticsearch.php config file, a ReindexCommand artisan command, and an observer. That's a day of work and it stays inside Laravel idioms.

Gotchas and Tips

  • Do not try to bootstrap Symfony inside Laravel. The DI compiler pass pipeline and the fos_elastica config tree require symfony/config, symfony/dependency-injection, and a Kernel to compile. Wiring them manually is multi-day work with zero reusable output. If you're on Laravel, drop the package from composer.json and use Scout.
  • Provenance. Zero stars, zero dependents, personal namespace. composer install on a fresh machine breaks the day the fork is deleted. If you must depend on it (you shouldn't), pin it via a vcs or path repository pointing at your own mirror, and diff every update against upstream before merging.
  • Elastica lags the official client. ES 7 removed mapping types; ES 8 mandates TLS and dropped many legacy defaults. Elastica's supported matrix trails both. If you're choosing a client today (any framework), the official elasticsearch/elasticsearch client should be the default — the bundle's abstraction is a maintenance tax you inherit.
  • Silent bulk failures. $response['errors'] === true only tells you some item failed. Iterate $response['items'], check each item.index.error, and fail the batch explicitly. This is the single most common cause of "our index is quietly missing documents" tickets with any of these tools.
  • Refresh delay. Default 1s. Tests that assert search results right after save() flake for this reason — sleep(2) in tests or mock the index. In production, don't claim "real-time search" in a UI that isn't.
  • 10k result window. from + size is capped at 10,000 by default. Scout does not abstract this. Any UI with "page N of results" needs search_after or scroll — plan for it before users hit page 100.
  • Mapping drift is the silent killer. Changing toSearchableArray() does not change the ES mapping. The next document with the new shape will be rejected by ES (or silently coerced). The only fix is scout:flush + scout:import (or, better, the alias-swap from day one). Wire the alias before the first mapping change ships; retrofitting it after an incident is painful.
  • Debugging. The official client exposes setLogger() — point it at Laravel's Log in AppServiceProvider::boot(). Elastica's failure path surfaces errors through two abstraction layers (bundle → Elastica → official client) with less context; another reason the abstraction is a net cost for a Laravel team.
  • Extension point that matters. On Symfony with the bundle, custom search lives in fos_elastica.index.<name>.<type> repository services. On Laravel, the equivalent is your own ProductIndex class. Both are the place a team will spend 80% of its time — invest in making that one class good (typed methods, logged queries, a debug() helper that dumps the raw DSL) regardless of which path you take.
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.
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk