acseo/typesense-bundle
Symfony bundle integrating Typesense search. Configure Typesense host/key, map Doctrine entities to Typesense collections/fields, and keep indexes synced via Doctrine event listeners. Includes transformers and services for querying collections.
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
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
First Use Case
Inject the TypesenseSearchService and search:
use ACSEO\TypesenseBundle\Service\TypesenseSearchService;
public function searchBooks(TypesenseSearchService $searchService)
{
$results = $searchService->search('books', 'query');
return $this->json($results);
}
Automatic Indexing
acseo_typesense.yml:
collections:
books:
entity: App\Entity\Book
auto_index: true # Auto-index on Doctrine events
prePersist, preUpdate, preRemove.Manual Indexing
$searchService->indexEntity($bookEntity);
$searchService->deleteIndexedEntity($bookEntity);
Custom Field Mapping
collections:
books:
entity: App\Entity\Book
fields:
id: id
title: title
author: author.name # Nested property
published_at: publishedAt
Search with Filters
$results = $searchService->search(
'books',
'query',
['filter_by': 'published_at:[1900-01-01 TO NOW]']
);
Pagination
$results = $searchService->search('books', 'query', [], 10, 0); // limit, offset
ACSEO\TypesenseBundle\Form\TypesenseType for search-as-you-type fields.TypesenseSearchService to integrate with ApiPlatform\Metadata\Operation.TypesenseIndexEvent listeners.Collection Naming Conflicts
collection_prefix in config avoids clashes with existing Typesense collections.collection_prefix: 'app_' → Collection names become app_books.Field Mapping Errors
fields will throw exceptions. Validate with:
$this->get('validator')->validate($entity, ['Typesense']);
Auto-Indexing Overhead
auto_index for large entities or use @Typesense\Ignore annotations:
use ACSEO\TypesenseBundle\Annotation\Typesense;
/**
* @Typesense\Ignore()
*/
private $sensitiveData;
Rate Limiting
retry_after in responses to implement exponential backoff.acseo_typesense.yml:
debug: true
TypesenseAdminService to inspect collections:
$adminService->getCollection('books');
Custom Transformers
Override ACSEO\TypesenseBundle\Transformer\DoctrineTransformer to handle complex types (e.g., JSON fields):
$transformer = $this->get('acseo_typesense.transformer.doctrine');
$transformer->addCustomField('App\Entity\Book', 'tags', function ($book) {
return json_encode($book->getTags());
});
Event Listeners
Extend indexing logic via TypesenseIndexEvent:
public function onIndex(TypesenseIndexEvent $event) {
$event->setData(['custom_field' => 'value']);
}
Async Indexing Use Symfony Messenger to queue indexing tasks for performance:
acseo_typesense:
async: true
How can I help you explore Laravel packages today?