Install the Bundle
composer require daanbiesterbos/solr-bundle
Enable the Bundle
Add to config/bundles.php:
return [
// ...
DaanBiesterbos\SolrBundle\SolrBundle::class => ['all' => true],
];
Configure Solr Connection
Define Solr host in config/packages/solr.yaml:
solr:
client:
host: 'http://localhost:8983/solr'
core: 'your_core_name'
Annotate an Entity
Use @Solr\Document and @Solr\Field annotations on a model (e.g., Product):
use DaanBiesterbos\SolrBundle\Annotation as Solr;
/**
* @Solr\Document(index="products")
*/
class Product
{
/**
* @Solr\Field(type="text_general")
*/
private $name;
// ...
}
First Indexing Run a console command to index entities:
php bin/console solr:index --entity=App\Entity\Product
Inject the SolrClient and query:
use DaanBiesterbos\SolrBundle\Client\SolrClientInterface;
class ProductController
{
public function __construct(private SolrClientInterface $solrClient) {}
public function search(Request $request)
{
$query = $request->query->get('q');
$results = $this->solrClient->search($query, 'products');
return $this->render('product/search.html.twig', [
'results' => $results->getResults(),
]);
}
}
Indexing Entities
solr:index command for one-time syncs.Solr\IndexableInterface and trigger indexing in entity lifecycle events (e.g., postPersist):
use DaanBiesterbos\SolrBundle\Annotation as Solr;
/**
* @Solr\Document(index="products")
*/
class Product implements Solr\IndexableInterface
{
public function isIndexable(): bool
{
return true; // Always index this entity
}
}
SolrClient::indexEntities() for bulk operations:
$this->solrClient->indexEntities(Product::class, ['id' => [1, 2, 3]]);
Querying Data
$results = $this->solrClient->search('laptop', 'products');
$results = $this->solrClient->search('laptop', 'products', [
'fq' => ['price:[100 TO 1000]', 'category:electronics'],
]);
$results = $this->solrClient->search('laptop', 'products', [
'start' => 0,
'rows' => 10,
]);
Updating/Deleting
deleted_at field and filter queries:
$results = $this->solrClient->search('laptop', 'products', [
'fq' => ['deleted_at:[* TO *]'], // Exclude deleted
]);
SolrClient::deleteById():
$this->solrClient->deleteById('products', 123);
Symfony Forms Use Solr suggestions for autocomplete:
$suggestions = $this->solrClient->suggest('lapt', 'products');
Event Listeners
Listen for Solr\Event\IndexEvent to customize indexing logic:
use DaanBiesterbos\SolrBundle\Event\IndexEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class CustomIndexSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
'solr.index' => 'onIndex',
];
}
public function onIndex(IndexEvent $event)
{
$entity = $event->getEntity();
// Modify $entity->getData() before indexing
}
}
Doctrine Integration
Use Solr\IndexableInterface with Doctrine lifecycle callbacks:
// src/EventSubscriber/ProductSubscriber.php
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
class ProductSubscriber implements EventSubscriber
{
public function postPersist(Product $product, LifecycleEventArgs $args)
{
$this->solrClient->indexEntity($product);
}
}
Custom Fields Define dynamic fields in Solr schema and map them in your entity:
/**
* @Solr\Field(type="text_general")
*/
private $customField;
Performance Issues
indexEntities) and optimize Solr config (e.g., maxBooleanClauses, autoCommit)./solr/admin/cores?indexInfo=true) for slow queries.Schema Mismatches
@Solr\Field(type="...") matches your Solr schema.xml types (e.g., text_general, int, date).solr:schema:dump to inspect the schema:
php bin/console solr:schema:dump
Caching Queries
cache:app):
$cacheKey = md5($query . serialize($filters));
$results = $this->cache->get($cacheKey, function() use ($query, $filters) {
return $this->solrClient->search($query, 'products', $filters);
});
Entity Changes Not Reflected
postUpdate in Doctrine listeners:
public function postUpdate(Product $product, LifecycleEventArgs $args)
{
$this->solrClient->indexEntity($product);
}
Deprecated Annotations
DaanBiesterbos\SolrBundle\Annotation namespace explicitly.Enable Solr Logging
Add to config/packages/solr.yaml:
solr:
client:
debug: true
Logs will appear in var/log/dev.log.
Raw Solr Queries
Use SolrClient::createQuery() to inspect raw Solr requests:
$query = $this->solrClient->createQuery('laptop', 'products');
$rawQuery = $query->getQuery();
Solr Admin UI
Access http://localhost:8983/solr/#/~collections to:
Custom Query Builders
Extend Solr\Query\QueryBuilder to add domain-specific methods:
use DaanBiesterbos\SolrBundle\Query\QueryBuilder;
class ProductQueryBuilder extends QueryBuilder
{
public function inStock()
{
$this->addFilterQuery('stock:[1 TO *]');
return $this;
}
}
Register as a service:
services:
App\Solr\Query\ProductQueryBuilder:
tags: ['solr.query_builder']
Dynamic Field Mapping
Override Solr\Indexer\Indexer to handle dynamic fields:
use DaanBiesterbos\SolrBundle\Indexer\IndexerInterface;
class CustomIndexer implements IndexerInterface
{
public function indexEntity(object $entity, string $core)
{
$data = [];
foreach ($entity as $property =>
How can I help you explore Laravel packages today?