codewithkyrian/chromadb-php
PHP client for ChromaDB, making it easy to create collections, add and query embeddings, and manage documents/metadata from your Laravel or PHP apps. Lightweight API wrapper to integrate vector search and retrieval workflows without leaving PHP.
## Getting Started
### **Minimal Setup**
1. **Installation**
```bash
composer require codewithkyrian/chromadb-php:^1.0
Ensure your ChromaDB server (v1.0+) is running (locally or on Chroma Cloud).
First Connection
use ChromaDB\ChromaDB;
// Local instance
$client = ChromaDB::local()->connect();
// Chroma Cloud
$client = ChromaDB::cloud()
->withHeader('X-Chroma-Token', 'your-api-key')
->connect();
Basic CRUD with Records
// Create a record
$record = \ChromaDB\Record::make('doc1')
->withDocument('Sample document')
->withMetadata(['author' => 'John Doe'])
->withEmbeddings([0.1, 0.2, 0.3]);
// Add to collection
$collection = $client->getOrCreateCollection('my_documents');
$collection->add($record);
// Query with embeddings
$results = $collection->query([0.15, 0.25, 0.35], 3)->asRecords();
Structured Record Creation
$record = \ChromaDB\Record::make('doc2')
->withDocument('Another document')
->withMetadata(['tags' => ['php', 'laravel']])
->withEmbeddings($embeddingModel->embed("user query"));
Batch Operations with Records
$records = [
\ChromaDB\Record::make('doc3')->withDocument('Doc 3')->withEmbeddings($embedding1),
\ChromaDB\Record::make('doc4')->withDocument('Doc 4')->withEmbeddings($embedding2),
];
$collection->add($records);
Advanced Filtering with Where
// Metadata filtering
$filtered = $collection->get(
\ChromaDB\Where::field('author')->eq('John Doe')
);
// Document content filtering
$filtered = $collection->get(
\ChromaDB\Where::document()->contains('laravel')
);
// Combined filters
$filtered = $collection->get(
\ChromaDB\Where::all([
\ChromaDB\Where::field('category')->eq('news'),
\ChromaDB\Where::document()->contains('update'),
])
);
Hybrid Search with Laravel Scout
// 1. Vector search (ChromaDB)
$vectorResults = $collection->query($embedding, 5)->asRecords();
// 2. Keyword search (Scout)
$keywordResults = Article::search('laravel')->get();
// Merge results (e.g., by relevance)
$merged = array_merge($vectorResults, $keywordResults);
Chroma Cloud Forking
$originalCollection = $client->getCollection('original');
$forkedCollection = $originalCollection->fork('forked_collection_name');
Laravel Service Provider Bind the client to the container with auto-discovery:
$this->app->singleton(\ChromaDB\ChromaDB::class, fn() => ChromaDB::local()->connect());
Configure in config/chromadb.php:
'url' => env('CHROMADB_URL', 'http://localhost:8000'),
'cloud_token' => env('CHROMADB_CLOUD_TOKEN'),
Event-Driven Updates with Records
public function saved(Article $article)
{
$record = \ChromaDB\Record::make($article->id)
->withDocument($article->content)
->withEmbeddings($this->generateEmbedding($article->content));
$collection->upsert($record);
}
Partial Embeddings Handling
$record = \ChromaDB\Record::make('doc5')
->withDocument('Partial embedding example')
->withEmbeddings(null); // Will be auto-generated if collection allows
Response Field Selection
$results = $collection->get(
includes: \ChromaDB\Includes::DOCUMENTS_AND_METADATA
);
Breaking Changes in v1.0
ChromaNotFoundException → NotFoundException).
Fix: Update imports and exception handling.ChromaDB::client() is deprecated. Use ChromaDB::local()->connect().symfony/http-client) is installed.Collection objects (no CollectionResource wrapper).Embedding Dimension Validation
$expectedDim = $collection->getConfig()['dimensions'];
if (count($record->embeddings) !== $expectedDim) {
throw new \InvalidArgumentException("Embedding dimension mismatch");
}
Cloud-Specific Features
fork()) and cloud authentication are Chroma Cloud-only.Metadata Serialization
'metadata' => ['tags' => json_encode(['laravel', 'php'])]
Rate Limiting
try {
$collection->add($record);
} catch (\ChromaDB\Exceptions\RateLimitException $e) {
sleep(2 ** $retryCount);
retry();
}
Enable Verbose Logging
$client = ChromaDB::local()->withDebug(true)->connect();
Logs will show raw API requests/responses.
Check API Response Codes
404: Collection not found.429: Rate limited.500: Server error (check ChromaDB logs).Validate Records Before Submission
if (!$record->isValid()) {
logger()->error('Invalid record:', $record->errors());
}
Use asRecords() for Debugging
Convert raw responses to structured Record objects:
$results = $collection->query($embedding, 3)->asRecords();
Custom HTTP Client Auto-discovery works with PSR-18 clients (e.g., Symfony HTTP Client):
composer require symfony/http-client
No manual configuration needed.
Event Listeners
Extend the SDK by listening to ChromaDB events (e.g., collection.created):
$client->on('collection.created', fn($collectionName) => {
logger()->info("New collection: {$collectionName}");
});
Batch Processing with Records For large datasets, use chunked writes:
$batchSize = 100;
foreach (array_chunk($records, $batchSize) as $chunk) {
$collection->add($chunk);
}
Local Development with Docker Spin up ChromaDB locally:
docker run -p 8000:8000 chromadb/chroma:latest
Chroma Cloud CLI Integration Manage collections via CLI:
chroma collections list
chroma collections delete my_collection
How can I help you explore Laravel packages today?