Awesome
[UNMAINTAINED] Laravel Algolia Search
This package is unmaintained and deprecated, we recommend using Laravel Scout, which requires Laravel 5.4+.
This PHP package integrates the Algolia Search API to the Laravel Eloquent ORM. It's based on the algoliasearch-client-php package. PHP 5.4+ is supported.
Table of Content
- Install
- Configuration
- Quick Start
- Ranking & Relevance
- Options
- Indexing
- Master/Slave
- Target multiple indexes
Install
Add algolia/algoliasearch-laravel
to your composer.json
file:
composer require algolia/algoliasearch-laravel-4
Add the service provider to config/app.php
in the providers
array.
AlgoliaSearch\Laravel\AlgoliaServiceProvider::class
Configuration
Laravel Algolia requires a configuration. To get started, you'll need to create a algolia.php
config file containing:
<?php
return array(
'id' => 'APP_ID',
'key' => 'SECRET_KEY'
);
You need to modify it to include your credentials.
Quick Start
The following code adds search capabilities to your Contact
model creating a Contact
index:
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
use AlgoliaEloquentTrait;
}
By default all visible attributes are sent. If you want to send specific attributes you can do something like:
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
use AlgoliaEloquentTrait;
public function getAlgoliaRecord()
{
return array_merge($this->toArray(), [
'custom_name' => 'Custom Name'
]);
}
}
Ranking & Relevance
We provide many ways to configure your index settings to tune the overall relevancy but the most important ones are the searchable attributes and the attributes reflecting the record popularity. You can configure them with the following code:
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
use AlgoliaEloquentTrait;
public $algoliaSettings = [
'attributesToIndex' => [
'id',
'name',
],
'customRanking' => [
'desc(popularity)',
'asc(name)',
],
];
}
Synonyms
Synonyms are used to tell the engine about words or expressions that should be considered equal in regard to the textual relevance.
Our synonyms API has been designed to manage as easily as possible a large set of synonyms for an index and its slaves.
You can use the synonyms API by adding a synonyms
in $algoliaSettings
class property like this:
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
use AlgoliaEloquentTrait;
public $algoliaSettings = [
'synonyms' => [
[
'objectID' => 'red-color',
'type' => 'synonym',
'synonyms' => ['red', 'another red', 'yet another red']
]
]
];
}
You can propagate (save) the settings to algolia using the setSetting
method:
Contact::setSettings();
Frontend Search (realtime experience)
Traditional search implementations tend to have search logic and functionality on the backend. This made sense when the search experience consisted of a user entering a search query, executing that search, and then being redirected to a search result page.
Implementing search on the backend is no longer necessary. In fact, in most cases it is harmful to performance because of the extra network and processing latency. We highly recommend the usage of our JavaScript API Client issuing all search requests directly from the end user's browser, mobile device, or client. It will reduce the overall search latency while offloading your servers at the same time.
In your JavaScript code you can do:
var client = algoliasearch('ApplicationID', 'Search-Only-API-Key');
var index = client.initIndex('YourIndexName');
index.search('something', function(success, hits) {
console.log(success, hits)
}, { hitsPerPage: 10, page: 0 });
Backend Search
You could also use the search
method but it's not recommended to implement instant/realtime search experience:
Contact::search('jon doe');
You can also pass additional parameters to the search function:
Contact::search('jon doe', array('hitsPerPage' => 5));
Options
Auto-indexing & Asynchronism
Each time a record is saved; it will be - asynchronously - indexed. On the other hand, each time a record is destroyed, it will be - asynchronously - removed from the index.
You can disable the auto-indexing and auto-removing setting the following options:
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
use AlgoliaEloquentTrait;
public static $autoIndex = false;
public static $autoDelete = false;
}
You can temporary disable auto-indexing. This is often used for performance reason.
Contact::$autoIndex = false;
Contact::clearIndices();
for ($i = 0; $i < 10000; $i++) {
$contact = Contact::firstOrCreate(['name' => 'Jean']);
}
Contact::reindex(); // Will use batch operations.
Custom Index Name
By default, the index name will be the pluralized class name, e.g. "Contacts". You can customize the index name by using the $indices
option:
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
use AlgoliaEloquentTrait;
public $indices = ['contact_all'];
}
Per-environment Indexes
You can suffix the index name with the current App environment using the following option:
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
use AlgoliaEloquentTrait;
public static $perEnvironment = true; // Index name will be 'Contacts_{\App::environnement()}';
}
Custom objectID
By default, the objectID
is based on your record's keyName
(id
by default). You can change this behavior specifying the objectIdKey
option (be sure to use a uniq field).
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
use AlgoliaEloquentTrait;
public static $objectIdKey = 'new_key';
}
Restrict Indexing to a Subset of Your Data
You can add constraints controlling if a record must be indexed by defining the indexOnly()
method.
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
use AlgoliaEloquentTrait;
public function indexOnly($index_name)
{
return (bool) $condition;
}
}
Relationships
By default the Algolia package will fetch the loaded relationships.
If you want to index records that didn't yet load any relations you can do it by loading them in the getAlgoliaRecord
that you can create in your model.
It will look like:
public function getAlgoliaRecord()
{
/**
* Load the categories relation so that it's available
* in the laravel toArray method
*/
$this->categories;
return $this->toArray();
}
In the resulted object you will have categories converted to array by Laravel. If you want a custom relation structure you will instead do something like:
public function getAlgoliaRecord()
{
/**
* Load the categories relation so that it's available
* in the laravel toArray method
*/
$extra_data = [];
$extra_data['categories'] = array_map(function ($data) {
return $data['name'];
}, $this->categories->toArray();
return array_merge($this->toArray(), $extra_data);
}
Indexing
Manual Indexing
You can trigger indexing using the pushToIndex
instance method.
$contact = Contact::firstOrCreate(['name' => 'Jean']);
$contact->pushToIndex();
Manual Removal
And trigger the removing using the removeFromIndex
instance method.
$contact = Contact::firstOrCreate(['name' => 'Jean']);
$contact->removeFromIndex();
Reindexing
To safely reindex all your records (index to a temporary index + move the temporary index to the current one atomically), use the reindex
class method:
Contact::reindex();
To reindex all your records (in place, without deleting out-dated records):
Contact::reindex(false);
Clearing an Index
To clear an index, use the clearIndices
class method:
Contact::clearIndices();
Master/Slave
You can define slave indexes using the $algolia_settings
variable:
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
use AlgoliaEloquentTrait;
public $algoliaSettings = [
'attributesToIndex' => [
'id',
'name',
],
'customRanking' => [
'desc(popularity)',
'asc(name)',
],
'slaves' => [
'contacts_desc',
],
];
public $slavesSettings = [
'contacts_desc' => [
'ranking' => [
'desc(name)',
'typo',
'geo',
'words',
'proximity',
'attribute',
'exact',
'custom'
]
]
];
}
To search using a slave use the following code:
Book::search('foo bar', ['index' => 'contacts_desc']);
Target Multiple Indexes
You can index a record in several indexes using the <code>$indices</code> property:
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
use AlgoliaEloquentTrait;
public $indices = [
'contact_public',
'contact_private',
];
public function indexOnly($indexName)
{
if ($indexName == 'contact_public')
return true;
return $this->private;
}
}
To search using an extra index, use the following code:
Book::search('foo bar', ['index' => 'contacts_private']);
Eloquent compatibility
Doing:
Ad::where('id', $id)->update($attributes);
will not trigger anything in the model (so no update will happen in Algolia). This is because this is not an Eloquent call, it is just a convenient way to generate the query hidden behind the model
To make this query work with Algolia you need to do it like that:
Ad::find($id)->update($attributes);
Compatibility
Compatible with 5.x applications
License
Laravel Algolia Search is licensed under The MIT License (MIT).