acts/sphinx-realtime-bundle
Symfony2 bundle that keeps Doctrine entities automatically synced with a Sphinx real-time index. Inspired by FOQElasticaBundle, it helps integrate Sphinx RT indexing into your app so changes in entities are reflected in search results with minimal setup.
Installation
Add the bundle to your composer.json:
composer require acts/sphinx-realtime-bundle
Register the bundle in config/bundles.php:
return [
// ...
Acts\SphinxRealtimeBundle\ActsSphinxRealtimeBundle::class => ['all' => true],
];
Configuration
Define Sphinx connection in config/packages/acts_sphinx_realtime.yaml:
acts_sphinx_realtime:
client:
host: '127.0.0.1'
port: 9312
path: '/var/run/sphinxsearch/sphinx.sock' # Optional Unix socket
indexer:
index_name: 'your_index_name'
delta_index_name: 'your_delta_index_name'
First Use Case Annotate a Doctrine entity to enable real-time indexing:
use Acts\SphinxRealtimeBundle\Annotation\SphinxRealtime;
/**
* @SphinxRealtime(
* index="your_index_name",
* deltaIndex="your_delta_index_name",
* attributes={
* "id", "title", "content"
* }
* )
*/
class Article
{
// ...
}
Trigger Initial Sync Run the command to populate the index:
php bin/console acts:sphinx:realtime:sync
Entity Lifecycle Hooks
Leverage Doctrine lifecycle events (prePersist, preUpdate, preRemove) to auto-sync changes:
use Acts\SphinxRealtimeBundle\Event\SphinxRealtimeEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class SphinxSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
SphinxRealtimeEvent::PRE_PERSIST,
SphinxRealtimeEvent::PRE_UPDATE,
SphinxRealtimeEvent::PRE_REMOVE,
];
}
public function onPrePersist(SphinxRealtimeEvent $event)
{
$event->getEntityManager()->flush(); // Force sync
}
}
Bulk Operations
Use the sync command for batch updates (e.g., after migrations):
php bin/console acts:sphinx:realtime:sync --entity=Article --limit=1000
Querying with Sphinx
Integrate with a Sphinx client (e.g., SphinxQL) for searches:
use SphinxQL\Client;
$client = new Client('unix:///var/run/sphinxsearch/sphinx.sock');
$results = $client->query('SELECT * FROM your_index_name WHERE MATCH(\'@title keyword\')');
Custom Indexing Logic
Override default behavior via a custom Indexer service:
# config/services.yaml
services:
App\Service\CustomSphinxIndexer:
arguments:
- '@acts_sphinx_realtime.indexer'
tags: ['acts_sphinx_realtime.indexer']
Delta Index Mismatch
delta_index_name in annotations matches the config. Mismatches cause silent failures.php bin/console debug:container acts_sphinx_realtime.indexer.Attribute Mapping Issues
sphinx.conf). Missing attributes throw SphinxException.acts:sphinx:realtime:schema:dump to verify schema alignment.Performance Bottlenecks
flush(). For high-traffic apps, batch updates:
$em->getConnection()->getConfiguration()->setSQLLogger(null); // Disable logging
$em->flush(); // Sync in bulk
Event Dispatching Order
// Avoid this anti-pattern:
$event->getEntityManager()->persist($event->getEntity()); // Recursive sync!
Enable Verbose Logging
# config/packages/monolog.yaml
handlers:
sphinx:
type: stream
path: "%kernel.logs_dir%/sphinx.log"
level: debug
channels: ["acts_sphinx"]
Check Index Status
php bin/console acts:sphinx:realtime:status
Schema Validation
Compare your sphinx.conf with the generated schema:
php bin/console acts:sphinx:realtime:schema:dump > schema.sql
Custom Indexers
Implement Acts\SphinxRealtimeBundle\Indexer\IndexerInterface for non-Doctrine data sources.
Event Listeners
Extend SphinxRealtimeEvent to add pre/post-processing:
$event->setData(['custom_field' => $value]); // Inject dynamic data
Async Indexing Offload sync to a queue (e.g., Symfony Messenger) for large datasets:
use Symfony\Component\Messenger\MessageBusInterface;
class AsyncSphinxSync
{
public function __construct(private MessageBusInterface $bus) {}
public function sync(EntityManagerInterface $em, string $entityClass)
{
$this->bus->dispatch(new SyncSphinxMessage($em, $entityClass));
}
}
How can I help you explore Laravel packages today?