cmsig/seal-algolia-adapter
Algolia adapter for the SEAL search engine (cmsig/search). Writes SEAL documents to Algolia SaaS and can be configured via Algolia SearchClient or a simple DSN (algolia://APP_ID:ADMIN_KEY). Early-stage; feedback welcome.
Install Dependencies
composer require cmsig/seal cmsig/seal-algolia-adapter
Configure Algolia Client Use either direct instantiation or DSN-based configuration:
// Direct client
$client = SearchClient::create('APP_ID', 'ADMIN_API_KEY');
// Or via DSN (e.g., in .env)
$client = SearchClient::createFromEnv('algolia://APP_ID:ADMIN_API_KEY');
Initialize SEAL Engine
use CmsIg\Seal\Engine;
use CmsIg\Seal\Adapter\Algolia\AlgoliaAdapter;
$engine = new Engine(
new AlgoliaAdapter($client),
$schema // Your SEAL schema definition
);
First Use Case: Indexing Data
$engine->index('products', [
['id' => 1, 'name' => 'Laptop', 'price' => 999.99],
['id' => 2, 'name' 'Phone', 'price' => 699.99],
]);
Schema-Driven Indexing Leverage SEAL’s schema to enforce data structure consistency before indexing:
$schema = new \CmsIg\Seal\Schema\Builder()
->addField('id', 'integer', true)
->addField('name', 'string', true)
->addField('price', 'float', false);
Bulk Operations Use Algolia’s bulk API for efficiency:
$engine->bulkIndex('products', $dataArray);
Search Integration Combine with SEAL’s search abstraction:
$results = $engine->search('products', 'laptop', [
'hitsPerPage' => 10,
'attributesToRetrieve' => ['name', 'price'],
]);
Service Provider Binding
Bind the engine in AppServiceProvider:
$this->app->singleton('algolia.engine', function ($app) {
$client = SearchClient::createFromEnv('algolia://APP_ID:ADMIN_API_KEY');
return new Engine(new AlgoliaAdapter($client), $app['seal.schema']);
});
Query Builder Integration Extend Laravel’s query builder for Algolia-specific searches:
class AlgoliaQueryBuilder extends Builder {
public function algoliaSearch($query) {
return $this->engine->search($this->model, $query);
}
}
Event-Driven Indexing
Sync models with Algolia via Laravel events (e.g., saved, deleted):
Product::saved(function ($product) {
app('algolia.engine')->index('products', $product->toArray());
});
Schema Mismatches
AlgoliaAdapter::validateSchema() to catch mismatches early.Rate Limits
$client->getApiClient()->getUsage();
use Symfony\Component\Process\Exception\TimeoutException;
try {
$engine->index(...);
} catch (TimeoutException $e) {
sleep(2 ** $attempt); // Exponential backoff
retry();
}
DSN Security
.env is risky. Use Laravel’s vault or environment variables with restricted permissions:
ALGOLIA_APP_ID=your_app_id
ALGOLIA_API_KEY=${VAULT:algolia_key} # Using Laravel Vault
Enable Algolia Debug Mode
$client->setDebug(); // Logs all API requests/responses
Inspect Raw Algolia Responses Access the underlying client for debugging:
$response = $engine->getAdapter()->getClient()->search('products', 'query');
dd($response->getResults());
Handle Partial Failures Algolia’s bulk API may partially fail. Check for errors:
$result = $engine->bulkIndex('products', $data);
if ($result->hasErrors()) {
foreach ($result->getErrors() as $error) {
log::error("Algolia bulk index error: " . $error->getMessage());
}
}
Custom Index Settings Override default Algolia settings via the adapter:
$adapter = new AlgoliaAdapter($client, [
'settings' => [
'searchableAttributes' => ['name', 'description'],
'customRanking' => ['desc(price)'],
],
]);
Pre/Post-Index Hooks Extend the adapter to modify payloads:
class CustomAlgoliaAdapter extends AlgoliaAdapter {
public function index($index, $objects) {
$objects = $this->transformObjects($objects);
parent::index($index, $objects);
}
protected function transformObjects($objects) {
// Add custom fields (e.g., timestamps)
return array_map(function ($obj) {
$obj['_updatedAt'] = now()->toIso8601String();
return $obj;
}, $objects);
}
}
Fallback Strategies Implement a fallback to local search if Algolia fails:
$engine = new Engine(
new AlgoliaAdapter($client),
$schema,
new LocalSearchFallback() // Custom fallback adapter
);
How can I help you explore Laravel packages today?