[Deprecated] We now recommend using Laravel Scout, see =>

Overview

[DEPRECATED] Algolia Search API Client for Laravel

Algolia Search is a hosted full-text, numerical, and faceted search engine capable of delivering realtime results from the first keystroke.


This package is deprecated, we recommend you to use Laravel Scout. If you want to extend Scout capabilities, please refer to our dedicated documentation


Build Status Latest Version License

This PHP package integrates the Algolia Search API into the Laravel Eloquent ORM. It's based on the algoliasearch-client-php package.

Note: If you're using Laravel 4, checkout the algoliasearch-laravel-4 repository.

API Documentation

You can find the full reference on Algolia's website.

Table of Contents

  1. Install

  2. Quick Start

  3. Options

  4. Relationships

  5. Indexing

  6. Manage indices

  7. Eloquent compatibility

Install

Install via composer

Add algolia/algoliasearch-laravel to your composer.json file:

composer require algolia/algoliasearch-laravel

Service provider

Add the service provider to config/app.php in the providers array.

AlgoliaSearch\Laravel\AlgoliaServiceProvider::class

Publish vendor

Laravel Algolia requires a connection configuration. To get started, you'll need to publish all vendor assets:

php artisan vendor:publish

You can add the --provider="Vinkla\Algolia\AlgoliaServiceProvider" option to only publish assets of the Algolia package.

This will create a config/algolia.php file in your app that you can modify to set your configuration. Also, make sure you check for changes compared to the original config file after an upgrade.

Quick Start

Quick Start

The following code adds search capabilities to your Contact model creating a Contact index:

use Illuminate\Database\Eloquent\Model;
use AlgoliaSearch\Laravel\AlgoliaEloquentTrait;

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'
        ]);
    }
}

After setting up your model, you need to manually do an initial import of your data. You can do this by calling reindex on your model class. Using our previous example, this would be:

Contact::reindex();

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 = [
        'searchableAttributes' => [
            'id',
            'name',
        ],
        'customRanking' => [
            'desc(popularity)',
            'asc(name)',
        ],
    ];
}

You can propagate (save) the settings to algolia by using the setSetting method:

Contact::setSettings();

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 replicas.

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 an instant/realtime search experience from the backend (having a frontend search gives a better user experience):

Contact::search('jon doe');

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 by 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 temporarily disable auto-indexing. This is often done for performance reasons.

Contact::$autoIndex = false;
Contact::clearIndices();

for ($i = 0; $i < 10000; $i++) {
    $contact = Contact::firstOrCreate(['name' => 'Jean']);
}

Contact::reindex(); // Will use batch operations.
Contact::$autoIndex = true;

You can also make a dynamic condition for those two parameters by creating an autoIndex and/or autoDelete method on your model

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
    use AlgoliaEloquentTrait;

    public function autoIndex()
    {
        if (\App::environment() === 'test') {
            return false;
        }

        return true;
    }

    public static autoDelete()
    {
        if (\App::environment() === 'test') {
            return false;
        }

        return true;
    }
}

Be careful to define those two methods in AlgoliaEloquentTrait. When putting those methods in a parent class they will be "erased" by AlgoliaEloquentTrait if used in a child class (because of php inheritance).

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

Relationships

By default the Algolia package will fetch the loaded relationships.

If you want to index records that haven't yet loaded 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

Visibility

By default, Algolia will only be able to access visible attributes of your model. So, for example, you will receive a No content in PUT request exception when using this example code, because invisible_attribute key returns an empty/null variable.

protected $visible = ['visible_attribute', 'other_visible_attribute'];

public function getAlgoliaRecord()
{
    return [
        'invisible_attribute' => $this->invisible_attribute
    ];
}

Before Indexing, be sure to have correctly listed your visible attributes. To bypass this safety mask imposed by Laravel, you may use $this->attributes['invisible_attribute'] to access directly to the attribute even if is not visible, but the recommendation is to avoid this type of access to attributes in your Model.

Manual Indexing

You can trigger indexing using the pushToIndex instance method.

$contact = Contact::firstOrCreate(['name' => 'Jean']);
$contact->pushToIndex();

Manual Removal

And trigger the removal 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 outdated records):

Contact::reindex(false);

To set settings during the reindexing process:

Contact::reindex(true, true);

To keep settings that you set on the Algolia dashboard when reindexing and changing settings:

Contact::reindex(true, true, true);

To implement a callback that gets called everytime a batch of entities is indexed:

Contact::reindex(true, true, false, function ($entities)
{
    foreach ($entities as $entity)
    {
        var_dump($entity->id); // Contact::$id
    }
});

Clearing an Index

To clear an index, use the clearIndices class method:

Contact::clearIndices();

Manage indices

Primary/Replica

You can define replica indexes using the $algolia_settings variable:

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
     use AlgoliaEloquentTrait;

     public $algoliaSettings = [
        'searchableAttributes' => [
            'id',
            'name',
        ],
        'customRanking' => [
            'desc(popularity)',
            'asc(name)',
        ],
        'replicas' => [
            'contacts_desc',
        ],
    ];

    public $replicasSettings = [
        'contacts_desc' => [
            'ranking' => [
                'desc(name)',
                'typo',
                'geo',
                'words',
                'proximity',
                'attribute',
                'exact',
                'custom'
            ]
        ]
    ];
}

To search using a replica, use the following code:

Book::search('foo bar', ['index' => 'contacts_desc']);

Target Multiple Indexes

You can index a record in several indexes using the $indices 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

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 it 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 this:

Ad::find($id)->update($attributes);

Compatibility

Compatible with 5.x applications

Comments
  • Hosts unreachable

    Hosts unreachable

    I've done a fresh install of Homestead, VirtualBox, freshly downloaded the Vagrant box and am using the latest version algoliasearch-laravel however for some reason I'm getting this error:

    AlgoliaException in Client.php line 748:
    Hosts unreachable: Could not resolve host: WWPOIMBJ3Z
.algolia.net,Could not resolve host: WWPOIMBJ3Z
-3.algolianet.com,Could not resolve host: WWPOIMBJ3Z
-1.algolianet.com,Could not resolve host: WWPOIMBJ3Z
-2.algolianet.com
    

    We've been using Algolia for 6 months and this is the first time I've had this issue and I'm stumped as to how to resolve it?

    opened by RyanHavoc 30
  • Laravel 5.4 Compatibility

    Laravel 5.4 Compatibility

    After moving over to Laravel 5.4 it seems their is as an exception which is being thrown:

      Type error: Argument 1 passed to AlgoliaSearch\Laravel\ModelHelper::isAutoI
      ndex() must be an instance of Illuminate\Database\Eloquent\Model, string gi
      ven, called in /home/vagrant/Development/UsedCars/vendor/algolia/algoliasea
      rch-laravel/src/EloquentSubscriber.php on line 16
    

    Not sure if this is directly related but any assistance would be appreciated.

    Cheers!

    opened by matthewmnewman 14
  • Drop PHP 5.4 and update to 5.5.9

    Drop PHP 5.4 and update to 5.5.9

    Also dropped the fork of @vinkla's Algolia package.

    opened by vinkla 11
  • _geoloc object can't be submitted via update method

    _geoloc object can't be submitted via update method

    When you attempt to update via the update() method, you can't send _geoloc. You can set it as an array, an object, whatever; it won't work. You get an error saying that _geoloc can't contain a string, and if you look at the body of the request in the logs, you can see it's sending _geoloc as blank.

    opened by stoicbuddha 10
  • Invalid argument supplied for foreach()

    Invalid argument supplied for foreach()

    Hello, I got this error "Invalid argument supplied for foreach()" when I am trying to foreach results this is a code

    $results = Cartalyst\Sentinel\Users\EloquentUser::search('arina');
    if (is_array($results)) {
        foreach ($results as $result) {
            foreach ($result as $a) {
                $name = $a['full_name'];
            }
        }
    } 
    
    opened by ZedanLab 9
  • Do a deep search when checking for traits

    Do a deep search when checking for traits

    Consider the following.

    I want all my models to have the $perEnvironment property set to true. To avoid redundancy, I create my own trait that uses the Algolia trait.

    <?php
    
    namespace App\Services;
    
    use AlgoliaSearch\Laravel\AlgoliaEloquentTrait;
    
    trait SearchIndexerTrait
    {
        use AlgoliaEloquentTrait;
    
        public static $perEnvironment = true;
    }
    

    And so now I can just use my custom trait in all my models.

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    use App\Services\SearchIndexerTrait;
    
    class Product extends Model
    {
        use SearchIndexerTrait;
    
        public $algoliaSettings = [
            'attributesToIndex' => [
                'name',
                'text',
            ],
            'attributesToRetrieve' => [
                'name',
                'text',
            ],
            'customRanking' => [
                'asc(name)',
            ],
        ];
    }
    
    

    However, my indices will no longer sync when I update or delete a model.

    This is because AlgoliaSearch\Laravel\EloquentSubscriber uses the php class_uses() helper method on the currently updated Model to check if it uses the AlgoliaEloquentTrait in order to determine whether or not the index should be updated. class_uses() only checks the "top level" traits that are used. It does not check the parents traits, or traits inside traits.

    To fix the problem, I used this handy fucntion.

    opened by Nikita240 8
  • Update relationships

    Update relationships

    Hello.

    How I update relationship data once that relationship has been updated?

    Eg. I have a car with a passenger relationship. I load the passenger into Algolia along with the car, but whenever the passenger is updated, nothing happens to the Car index where the passenger is also loaded.

    It cannot be correct that I have to reindex everything every time.

    opened by JapSeyz 7
  • Hosts unreachable:Resolving timed out after 2000 milliseconds

    Hosts unreachable:Resolving timed out after 2000 milliseconds

    i'm running algolia with laravel 5.1 using this package,but i got the erros when i try to index some data or setup a search.

    2015-11-08_17-36-32

    already went throught this issue,but i could not solved my problem

    running laravel 5.1 with homestead Laravel Homestead version 2.1.6, tried ls /etc/ssl/certs | grep -i comodo

    Comodo_AAA_Services_root.pem
    COMODO_Certification_Authority.pem
    COMODO_ECC_Certification_Authority.pem
    Comodo_Secure_Services_root.pem
    Comodo_Trusted_Services_root.pem
    

    a guy from china,any case that the internet was block by the Great Wall? because when i use my VPN connect to the internet. it works fine....

    i push it to production,still got the errors. any ideas

    opened by JellyBool 7
  • Hosts unreachable: Resolving timed out after 2000 milliseconds

    Hosts unreachable: Resolving timed out after 2000 milliseconds

    Hi,

    I´m running into this error with Laravel 5.1 when trying to index some data. Always get this error: AlgoliaException in Client.php line 392:

    Hosts unreachable: Resolving timed out after 2000 milliseconds,Resolving timed out after 2000 milliseconds,Resolving timed out after 4000 milliseconds,Resolving timed out after 4000 milliseconds

    Found something similar on Twitter from 2013 but can´t figure out how to solve my problem.

    Any Ideas on that ? Thanks Marc

    opened by MarcTroesken 7
  • $algoliaSettings['attributesForFaceting'] setting is being ignored.

    $algoliaSettings['attributesForFaceting'] setting is being ignored.

    Hi there,

    Each time I run Product::reindex(); the attributesForFaceting setting gets cleared on my dashboard and I must login and update it manually. Am I doing it wrong?

    class Product extends \ResourceModel {
        use AlgoliaEloquentTrait;
        public static $perEnvironment = true;
        public static $autoIndex = true;
        public $algoliaSettings = [
            'attributesForFaceting' => [ 'category_id', 'vendor_id', 'unit_price', 'brand' ],
        ];
    }
    

    Thanks in advance!

    opened by mspivak 6
  • Where's before indexing

    Where's before indexing

    I'm trying to index my dataset but i only want the data with the status of 1. How would I achieve that because current efforts are not working.

    $products = Product::where('status', 1)->reindex()->get();
            //$products->reindex();
            Product::setSettings();
            $count = count($products);
            return $count.' products sync\'d to Algolia';
    

    "Call to undefined method Illuminate\Database\Query\Builder::reindex()"

    opened by xitude 6
Releases(1.7.1)
Owner
Algolia
Open source tools for building search. Learn more at community.algolia.com
Algolia
Driver for Laravel Scout search package based on https://github.com/teamtnt/tntsearch

TNTSearch Driver for Laravel Scout - Laravel 5.3 - 8.0 This package makes it easy to add full text search support to your models with Laravel 5.3 to 8

TNT Studio 1k Dec 27, 2022
Laravel Scout provides a driver based solution to searching your Eloquent models.

Introduction Laravel Scout provides a simple, driver-based solution for adding full-text search to your Eloquent models. Once Scout is installed and c

The Laravel Framework 1.3k Dec 31, 2022
Elasticsearch driver for Laravel Scout

Elasticsearch driver for Laravel Scout. Contents Compatibility Installation Configuration Basic Usage Advanced Search Migrations Pitfalls Compatibilit

Ivan Babenko 197 Dec 19, 2022
Search among multiple models with ElasticSearch and Laravel Scout

For PHP8 support use php8 branch For Laravel Framework < 6.0.0 use 3.x branch The package provides the perfect starting point to integrate ElasticSear

Sergey Shlyakhov 592 Dec 25, 2022
A scout DB fulltext-based driver that store index data in related tables

A scout DB fulltext-based driver that store index data in related tables This package provide a Laravel/Scout Engine based on database/fulltext only,

Ivano Matteo 10 Nov 10, 2022
A TYPO3 extension that integrates the Apache Solr search server with TYPO3 CMS. dkd Internet Service GmbH is developing the extension. Community contributions are welcome. See CONTRIBUTING.md for details.

Apache Solr for TYPO3 CMS A TYPO3 extension that integrates the Apache Solr enterprise search server with TYPO3 CMS. The extension has initially been

Apache Solr for TYPO3 126 Dec 7, 2022
Plastic is an Elasticsearch ODM and mapper for Laravel. It renders the developer experience more enjoyable while using Elasticsearch, by providing a fluent syntax for mapping, querying, and storing eloquent models.

Plastic is an Elasticsearch ODM and mapper for Laravel. It renders the developer experience more enjoyable while using Elasticsearch, by providing a f

Sleiman Sleiman 511 Dec 31, 2022
Build and execute an Elasticsearch search query using a fluent PHP API

PACKAGE IN DEVELOPMENT, DO NOT USE YET Build and execute ElasticSearch queries using a fluent PHP API This package is a lightweight query builder for

Spatie 94 Dec 14, 2022
Maps Laravel Eloquent models to Elasticsearch types

Elasticquent Elasticsearch for Eloquent Laravel Models Elasticquent makes working with Elasticsearch and Eloquent models easier by mapping them to Ela

Elasticquent 1.3k Jan 4, 2023
A search package for Laravel 5.

Search Package for Laravel 5 This package provides a unified API across a variety of different full text search services. It currently supports driver

Mark Manos 354 Nov 16, 2022
A php trait to search laravel models

Searchable, a search trait for Laravel Searchable is a trait for Laravel 4.2+ and Laravel 5.0 that adds a simple search function to Eloquent Models. S

Nicolás López Jullian 2k Dec 27, 2022
Unmaintained: Laravel Searchy makes user driven searching easy with fuzzy search, basic string matching and more to come!

!! UNMAINTAINED !! This package is no longer maintained Please see Issue #117 Here are some links to alternatives that you may be able to use (I do no

Tom Lingham 533 Nov 25, 2022
Elasticsearch migrations for Laravel

Elastic Migrations Elasticsearch migrations for Laravel allow you to easily modify and share indices schema across the application's environments. Con

Ivan Babenko 151 Dec 20, 2022
Fulltext indexing and searching for Laravel

Laravel fulltext index and search This package creates a MySQL fulltext index for models and enables you to search through those. Install Install with

SWIS 171 Jan 4, 2023
This is an open source demo of smart search feature implemented with Laravel and Selectize plugin

Laravel smart search implementation See demo at: http://demos.maxoffsky.com/shop-search/ Tutorial at: http://maxoffsky.com/code-blog/laravel-shop-tuto

Maksim Surguy 215 Sep 8, 2022
ScoutAPM PHP Agent for the Laravel Framework

Scout Laravel APM Agent Monitor the performance of PHP Laravel applications with Scout's PHP APM Agent. Detailed performance metrics and transaction t

Scout APM 22 Jan 2, 2023
Laravel package to search through multiple Eloquent models. Supports sorting, pagination, scoped queries, eager load relationships and searching through single or multiple columns.

Laravel Cross Eloquent Search This Laravel package allows you to search through multiple Eloquent models. It supports sorting, pagination, scoped quer

Protone Media 844 Dec 25, 2022
Laravel 8.* Elasticsearch Eloquent

Elasticsearch Installation composer require etsetra/elasticsearch Create config file $ php artisan vendor:publish --tag="etsetra-elasticsearch-config

Etsetra 2 Jan 14, 2022
Laravel Searchable - This package makes it easy to get structured search from a variety of sources

This package makes it easy to get structured search from a variety of sources. Here's an example where we search through some model

Spatie 1.1k Dec 31, 2022