leapt/elastica-bundle
Symfony bundle that integrates Elasticsearch into your app through the Elastica client. It handles index configuration and mapping, automatic persistence of Doctrine entities, and repository-style search, giving you a convenient service layer for indexing and querying documents.
First, calibrate: this is a Symfony bundle, not a Laravel package. It wires ruflin/elastica into Symfony’s DI container, config tree, and console. Do not expect config/elastica.php, service providers, facades, or Scout integration. In a Laravel app you either (a) use it inside a hybrid Symfony/Laravel setup, or (b) — far more likely — use ruflin/elastica (or elasticsearch/elasticsearch) directly and skip this bundle.
Release status has changed with v2.0.0. The package is no longer the frozen 2020-01-14 snapshot this assessment previously warned about: v2.0.0 drops Symfony < 4.4 and PHP < 7.2, adds phpstan / php-cs-fixer / Travis CI, and adds return types. That is a maintenance-resumption signal, not a feature release — read it as “someone is at the wheel again, still on the old Elastica line.” Treat the CI and static analysis as evidence of baseline hygiene, not as proof of PHP 8.2+ or Elasticsearch 8 support. The version floors are a minimum, and nothing in the notes raises the ceiling.
The practical question is therefore narrower than before: not “is this dead?” but “is a Symfony 4.4+ / PHP 7.2+ DI wrapper for Elastica 6/7 worth adopting in a Laravel shop?” Almost always no — but the floor is now credible for legacy Symfony work.
If you are genuinely starting:
composer require leapt/elastica-bundle:^2.0 ruflin/elastica:^6.0
Version alignment matters more than star counts here — a mismatched Elastica fails at container compile time, not runtime.composer why-not php 8.2 and composer why-not symfony/framework-bundle 6.0 and believe the output.config/packages/elastica.yaml):
elastica:
clients:
default:
host: '%env(ELASTICSEARCH_HOST)%'
port: 9200
indexes:
app:
client: default
index_name: app_%kernel.environment%
types:
product:
properties:
title: { type: text }
price: { type: float }
ElasticaBundle\Manager\RepositoryManager and the generated elastica.index.* / finder services — those are what you’ll inject day-to-day.type, run the populate command, then query via the finder. Don’t start with custom analyzers; start with a working index and a ->find() call.Repository/finder injection. The bundle exposes a finder per type. In a controller or service:
use Elastica\Query;
use Elastica\Query\MatchQuery;
$finder = $this->get('elastica.finder.app.product');
$query = new MatchQuery('title', 'widget');
$results = $finder->find($query); // hydrated entities if transformer configured
$paginated = $finder->findPaginated($query);
v2.0.0’s added return types are worth exploiting: finder, repository, and persister methods now carry signatures, so static analysis (phpstan, which the release itself introduced) can catch the classic find() vs findRaw() return-shape confusion at analysis time rather than in production. Wire phpstan into your own CI at a level that actually inspects vendor/ stubs if you depend on this.
Transformer-backed finders (the real payoff). Configure a model and the bundle hydrates Doctrine entities from ES hits:
types:
product:
model: App\Entity\Product
persistence:
driver: orm
model: App\Entity\Product
provider: { query_builder_method: createSearchQueryBuilder }
Then $finder->find($query) returns Product[], not raw arrays. This is the pattern worth stealing even outside Symfony — do the same ID-mapping in a Laravel repository.
Index lifecycle via console. The bundle’s commands are its day-to-day core:
bin/console elastica:index:populate app --batch-size=500
bin/console elastica:index:reset
bin/console elastica:index:populate app --no-reset # incremental
Pattern: populate on deploy, schedule incremental re-populates for changed rows, and keep a search_sync flag on models so a queued job (Symfony Messenger, or Laravel queue in a hybrid) pushes single-document updates instead of full reindexes.
Annotation/config hybrid. Older setups use @ES\Index/@ES\Type annotations plus @ES\Exclude. Prefer the YAML config path today — annotations are fragile across PHP/Doctrine upgrades, and v2.0.0 raised the PHP floor without touching annotation handling, so any annotation-based setup inherits an unverified upgrade path.
Cross-store consistency. For write-through behavior, use Doctrine listeners (postPersist/postUpdate) or an event subscriber that schedules an Elastica updateDocument after commit. Never index inside the transaction — ES and DB rollbacks diverge.
Laravel equivalent. If you’re translating this into Laravel: a singleton binding for Elastica\Client, a ProductIndexRepository wrapping Elastica\Index, and queued jobs for index/populate. That reproduces this bundle’s value in ~100 lines without tying yourself to a Symfony-DI-shaped dependency.
^1.0 if you genuinely cannot move, but understand you are pinning to the abandoned line — the CI/phpstan/return-type work landed only on 2.x.ObjectPersister, ProviderInterface, or any finder class, your overrides must now match the new signatures or you get fatal errors at class load — not at container compile. Audit custom subclasses before upgrading.bin/console cache:clear after every elastica.yaml change — Symfony caches the resolved config aggressively, and stale compiled metadata is a common “why is my mapping wrong?” culprit.--batch-size=500 and watch --sleep. No built-in parallelism.provider query returns rows that don’t exist in ES, find() hydrates fewer results than findRaw(). Always compare raw vs. hydrated hit counts when debugging missing results.app_%kernel.environment%) prevents the classic dev-indexes-over-prod-app accident, but means reset in the wrong env is instant data loss — guard the console command.findRaw() to inspect the ES response, and log $client->getLastRequest() / getLastResponse(); the bundle hides most transport detail.ElasticaBundle\Persister\ObjectPersister and ProviderInterface implementations are the intended seams for non-Doctrine data sources — that’s where you’d plug a Laravel Eloquent provider. Remember to update them for v2.0.0 signatures.elasticsearch/elasticsearch or laravel-scout + an ES driver. The patterns above (finders, transformers, populate commands) are transferable; the bundle itself remains unnecessary baggage in a Laravel app.How can I help you explore Laravel packages today?