typesense/typesense-php
Official PHP client for the Typesense search API. Install via Composer with an HTTPlug-compatible HTTP client, then manage collections, documents, and searches using the Typesense server API. Includes examples and safe filter string escaping.
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require php-http/curl-client typesense/typesense-php
(Use guzzlehttp/guzzle or another HTTPlug-compatible client if preferred.)
Initialize Client:
use Typesense\Client;
use Typesense\Connection;
use Typesense\TypesenseException;
$client = Client::fromOptions([
'nodes' => [
new Connection('http://localhost:8108'),
],
'api_key' => 'your-api-key',
'connection_timeout_seconds' => 2,
]);
First Use Case: Search
try {
$searchResults = $client->collections('products')
->documents()
->search('query=laptop', 10);
dd($searchResults->get('hits'));
} catch (TypesenseException $e) {
// Handle errors (e.g., network issues, invalid API key)
dd($e->getMessage());
}
$client->collections('collection_name')$client->collections('collection_name')->documents()$client->collections('collection_name')->schema()$client->aliases()Docs: Typesense API Reference | Examples
$searchResults = $client->collections('products')
->documents()
->search('query=wireless headphones&query_by=title,description', 20);
$searchResults = $client->collections('products')
->documents()
->search('query=headphones&filter_by=price:[100 TO *]');
$searchResults = $client->collections('products')
->documents()
->search('query=headphones&per_page=10&page=2');
$searchResults = $client->collections('products')
->documents()
->search('query=best headphones&nls=true');
$document = [
'title' => 'Wireless Headphones',
'price' => 199.99,
'description' => 'Noise-cancelling wireless headphones',
];
$client->collections('products')->documents()->upsert($document);
$documents = [
['title' => 'Product 1', 'price' => 100],
['title' => 'Product 2', 'price' => 200],
];
$client->collections('products')->documents()->upsert($documents);
$client->collections('products')->documents()->delete('document_id');
$schema = [
'name' => 'products',
'fields' => [
['name' => 'title', 'type' => 'string'],
['name' => 'price', 'type' => 'int32'],
],
];
$client->collections()->create($schema);
$updatedSchema = [
'fields' => [
['name' => 'title', 'type' => 'string', 'optional' => true],
],
];
$client->collections('products')->schema()->update($updatedSchema);
$searches = [
['collection' => 'products', 'query' => 'headphones'],
['collection' => 'electronics', 'query' => 'laptops'],
];
$results = $client->multiSearch()->search($searches);
$client->collections('products')->analytics()->events()->create([
'event_name' => 'product_view',
'document_id' => '123',
'properties' => ['user_id' => '456'],
]);
use Psr\Log\LoggerInterface;
$logger = new CustomLogger();
$client = Client::fromOptions([
'nodes' => [new Connection('http://localhost:8108')],
'api_key' => 'your-api-key',
'logger' => $logger, // Inject custom logger
]);
// app/Providers/TypesenseServiceProvider.php
use Illuminate\Support\ServiceProvider;
use Typesense\Client;
use Typesense\Connection;
class TypesenseServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton('typesense', function () {
return Client::fromOptions([
'nodes' => [new Connection(config('typesense.nodes.0'))],
'api_key' => config('typesense.api_key'),
]);
});
}
}
config/typesense.php)return [
'nodes' => [
'http://localhost:8108',
],
'api_key' => env('TYPESENSE_API_KEY'),
'connection_timeout_seconds' => 2,
];
use Illuminate\Support\Facades\Typesense;
public function search()
{
$results = Typesense::collections('products')
->documents()
->search('query=headphones');
return response()->json($results->get('hits'));
}
filter_by queries can break searches (e.g., &&, ||, %).FilterBy::escapeString():
use Typesense\FilterBy;
$filterValue = "The 17\" O'Conner && O`Series";
$escaped = FilterBy::escapeString($filterValue);
$search = $client->collections('products')
->documents()
->search("query=*&filter_by=tags:={$escaped}");
TypesenseException: Network issues, invalid API keys, or server errors.JsonException: Malformed JSON responses (handled in v6.1.0+).500/408 errors by default. Disable with:
$client = Client::fromOptions([
'nodes' => [new Connection('http://localhost:8108')],
'api_key' => 'your-api-key',
'retry_on_status_codes' => [], // Disable retries
]);
curl-client, guzzle) is HTTPlug-compatible./operations/schema_changes).upsert() with arrays for bulk inserts:
$client->collections('products')->documents()->upsert([$doc1, $doc2, $doc3]);
per_page to reduce payload size:
$searchResults = $client->collections('products')
->documents()
->search('query=*&per_page=50');
Cache::remember():
$results = Cache::remember('typesense_headphones', 3600, function () {
return $client->collections('products')
->documents()
->search('query=headphones');
});
$client = Client::fromOptions([
'nodes' => [new Connection('http://localhost:8108')],
'api_key' => 'your-api-key',
'logger' => new \Monolog\Logger('typesense', [
new \Monolog\Handler\StreamHandler(__DIR__.'/typesense.log', \Monolog\Logger::DEBUG),
]),
]);
getRawResponse() to inspect raw HTTP responses:How can I help you explore Laravel packages today?