Installation
composer require acseo/typesense-bundle
Enable in config/bundles.php:
ACSEO\TypesenseBundle\ACSEOTypesenseBundle::class => ['all' => true],
Configure .env
TYPESENSE_URL=http://localhost:8108
TYPESENSE_KEY=your_api_key_here
Basic YAML Config
# config/packages/acseo_typesense.yml
acseo_typesense:
typesense:
url: '%env(resolve:TYPESENSE_URL)%'
key: '%env(resolve:TYPESENSE_KEY)%'
collections:
books:
entity: App\Entity\Book
fields:
id: id
First Use Case
Inject the TypesenseManager service and search:
use ACSEO\TypesenseBundle\Service\TypesenseManager;
public function __construct(private TypesenseManager $typesense)
{
}
public function searchBooks(string $query): array
{
return $this->typesense->search('books', $query);
}
Workflow: Configure listeners to sync Doctrine entities to Typesense on postPersist, postUpdate, and postRemove.
acseo_typesense:
collections:
books:
entity: App\Entity\Book
fields:
id: id
title: title
author: author
sync_events: true # Enables automatic indexing
Custom Mapping: Override field mappings in config or via annotations:
fields:
custom_field: [property_path, typesense_field_name]
Basic Search:
$results = $this->typesense->search('books', 'Laravel', [
'query_by' => 'title,author',
'per_page' => 10,
]);
Filtered Search:
$results = $this->typesense->search('books', '', [
'filter_by' => 'author:"John Doe" AND year:2023',
]);
Bulk Indexing:
$this->typesense->bulkIndex('books', $doctrineEntities);
Collection Management:
$this->typesense->createCollection('books', $schema);
$this->typesense->deleteCollection('books');
use ACSEO\TypesenseBundle\Form\TypesenseSearchType;
$builder->add('search', TypesenseSearchType::class, [
'collection' => 'books',
'query_by' => 'title,author',
]);
Collection Prefix Conflicts
collection_prefix is set (e.g., test_), ensure your collection names in config match (e.g., test_books).Field Mapping Mismatches
fields are misconfigured (e.g., id: non_existent), indexing fails silently.$this->typesense->getCollectionSchema('books');
Doctrine Sync Race Conditions
sync_events: true) may conflict with manual bulk operations.$this->typesense->disableSync();
// Bulk operations...
$this->typesense->enableSync();
Environment-Specific Config
TYPESENSE_URL in config bypasses .env.%env(resolve:TYPESENSE_URL)% in YAML.acseo_typesense:
debug: true # Logs all Typesense operations to Symfony logger
$schema = $this->typesense->getCollectionSchema('books');
dump($schema);
$documents = $this->typesense->getDocuments('books', ['id:1']);
dump($documents);
Custom Transformers
ACSEO\TypesenseBundle\Transformer\DoctrineObjectTransformer to handle complex entity-to-document logic.class CustomBookTransformer extends DoctrineObjectTransformer
{
public function transform($entity, array $fields): array
{
$data = parent::transform($entity, $fields);
$data['formatted_title'] = strtoupper($entity->getTitle());
return $data;
}
}
services:
App\Transformer\CustomBookTransformer:
tags: [acseo_typesense.transformer, { alias: 'App\Entity\Book' }]
Event Listeners
TypesenseEvents for pre/post-indexing logic:
use ACSEO\TypesenseBundle\Event\TypesenseEvent;
$dispatcher->addListener(TypesenseEvent::PRE_INDEX, function (TypesenseEvent $event) {
$event->setData(['custom_field' => 'value']);
});
Async Indexing
$this->messageBus->dispatch(new IndexTypesenseMessage($entity, 'books'));
IndexTypesenseMessageHandler to process messages asynchronously.How can I help you explore Laravel packages today?