aghfatehi/laravel-smartsearch

Laravel SmartSearch by Fatehi AL-AGHBARI — production-grade search abstraction layer for Laravel with OpenSearch, Elasticsearch, Scout, and database fallback. Unified search API, automatic indexing, Arabic/multilingual support, queue-driven, safe fallback. AI-powered semantic search with vector embe

Maintainers

Package info

github.com/aghfatehi/laravel-smartsearch

pkg:composer/aghfatehi/laravel-smartsearch

Statistics

Installs: 16

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.4.0 2026-06-07 14:49 UTC

This package is auto-updated.

Last update: 2026-06-07 17:24:33 UTC


README

PHP Version Laravel Version Drivers AI Search License Tests Packagist Downloads FsoftDev Author

Laravel SmartSearch

Laravel search package — the most versatile full text search for Laravel with OpenSearch, Elasticsearch, Scout, and database search.
Zero-config, production-safe, queue-driven search indexing with AI-powered semantic & vector search.
A powerful Eloquent search engine for your models.

What is Laravel SmartSearch?

Laravel SmartSearch is a powerful, production-ready Laravel search package that provides a unified search API across OpenSearch, Elasticsearch, Laravel Scout, and database full-text search — a true Laravel Scout alternative with more flexibility. Built by Fatehi AL-AGHBARI, it solves the common pain points teams face when adding search to Laravel applications — complex setup, vendor lock-in, and brittle fallback logic.

Whether you need OpenSearch for Laravel, Elasticsearch for Laravel, a Laravel Scout alternative, or database search for Laravel, SmartSearch gives you one clean Laravel search API that works everywhere. The Eloquent search layer integrates directly with your models for zero-friction indexing.

Why Laravel SmartSearch?

Integrating search for Laravel applications often means:

  • Hard-coding Elasticsearch queries
  • Breaking changes when switching providers
  • No safety net when the search engine goes down
  • Painful multilingual setup (especially Arabic)

SmartSearch fixes all of this:

Problem Traditional Approach SmartSearch
Setup complexity Hours of config 1-minute setup
Vendor lock-in Tied to one engine Switch drivers anytime
No fallback 503 errors Auto database fallback
Arabic search Custom hacks Built-in normalizer
Indexing overhead Manual sync Auto queue-driven

Features

  • Unified Laravel search APISmartSearch::for(Model::class)->query('term')->get()
  • Full text search for Laravel — works out of the box with database search, no extra packages
  • Eloquent search — trait-based, integrates directly with your models
  • Database search LaravelLIKE / ILIKE auto-detects MySQL, PostgreSQL, SQLite, SQL Server
  • Elasticsearch for Laravel — high-performance dedicated search, install only if needed
  • OpenSearch for Laravel — open-source search engine, fully compatible API
  • Laravel Scout bridge — works with Algolia, MeiliSearch, Typesense through Scout
  • Search indexing — queue-driven on model created/updated/deleted
  • Automatic safe fallback — if Elasticsearch/Scout is down, falls back to database
  • Arabic search for Laravel — built-in normalization for Arabic content
  • Multilingual search — configurable analyzers for any language
  • Driver-based architecture — Strategy Pattern, extensible
  • Works with any database — MySQL, PostgreSQL, SQLite, SQL Server, no breaking changes
  • Laravel 9 / 10 / 11 / 12 / 13 — full backward compatibility

What Sets SmartSearch Apart

These features are not available in Elasticsearch or Laravel Scout alone. They are the unique value SmartSearch brings:

Feature Elasticsearch Native OpenSearch Native Laravel Scout Native SmartSearch
Single API across engines No No No — Scout providers only Yes — database, OpenSearch, Elasticsearch, and Scout through one API
Standalone DB driver No No Requires Scout ecosystem Yes — works standalone, no extra packages
Queue auto-indexing No — you build it No — you build it Opt-in (SCOUT_QUEUE=true) Yes — enabled by default, zero config
Automatic fallback No — downtime = 503 No — downtime = 503 No — only pagination count fallback Yes — configurable fallback driver
Arabic normalization Server-side only Server-side only No Yes — PHP-level across all drivers
OpenSearch support No N/A (is OpenSearch) Requires community driver Yes — built-in driver, no extra config
Elasticsearch support N/A (is Elasticsearch) No Requires community driver Yes — built-in driver

SmartSearch is not "yet another wrapper." It is an open-source abstraction layer that:

  • Unifies database, OpenSearch, Elasticsearch, and Scout providers under one fluent API
  • Adds features no single engine provides alone (PHP-level Arabic normalization, driver fallback, queue-by-default indexing)
  • Gives OpenSearch and Elasticsearch first-class support — no community adapters needed
  • Lets you start with the free database driver, migrate to self-hosted OpenSearch, then scale to Elasticsearch or Scout providers — all by changing one .env line

Driver Architecture

SmartSearch decouples your application from the search engine. The architecture has three layers — your code, the manager, and the drivers:

Layer 1 — Your Code (unified API, never changes)

SmartSearch::for(Product::class)->query('phone')->where('price', '>', 100)->get();

Layer 2 — SearchManager (routes to the active driver)

Setting Value
SMARTSEARCH_DRIVER Pick one: database, opensearch, elasticsearch, scout
SMARTSEARCH_FALLBACK Optional fallback if primary driver fails

Layer 3 — Drivers (execution engines)

Driver Type Mechanism Cost Setup Effort
DatabaseDriver Standalone LIKE / ILIKE auto-detect Free None — works immediately
OpenSearchDriver Standalone HTTP API via opensearch-php Free Medium — Docker self-hosted
ElasticsearchDriver Standalone HTTP API via elasticsearch-php Cloud / Self-hosted Medium — Cloud ID or hosts
ScoutDriver Bridge Delegates to Scout providers Per provider Low — Scout + API keys

ScoutDriver providers:

Provider Type Environment
Algolia Paid cloud SaaS, zero server management
MeiliSearch Free open-source / Paid cloud Self-hosted or managed cloud
Typesense Free open-source / Paid cloud Self-hosted or managed cloud

Installation

Core package

composer require aghfatehi/laravel-smartsearch

This installs the core package with the database driver only — no extra dependencies, no conflicts.

Optional driver packages

The database driver works immediately. For other search engines, install the corresponding package:

Engine Command Required for
Elasticsearch composer require elasticsearch/elasticsearch SMARTSEARCH_DRIVER=elasticsearch
OpenSearch composer require opensearch-project/opensearch-php SMARTSEARCH_DRIVER=opensearch
Scout (Algolia / MeiliSearch / Typesense) composer require laravel/scout SMARTSEARCH_DRIVER=scout

The package auto-detects which drivers are installed — missing packages just mean that driver throws a clear error message if used.

Publish config (optional)

php artisan vendor:publish --tag=smartsearch-config

Quick Setup

1. Add the trait to your model

use SmartSearch\Traits\SmartSearchable;

class Product extends Model
{
    use SmartSearchable;

    protected $smartSearchable = ['name', 'description', 'price'];
}

2. (Optional) Configure your driver

The default driver is database — works immediately with your existing database. To switch to Elasticsearch:

SMARTSEARCH_DRIVER=elasticsearch
SMARTSEARCH_FALLBACK=database

That's it.

Elasticsearch Setup

To use the Elasticsearch for Laravel driver, set the driver in your .env:

SMARTSEARCH_DRIVER=elasticsearch

Connecting to Elasticsearch

Local / self-hosted:

ELASTICSEARCH_HOSTS=localhost:9200

With Basic Auth:

ELASTICSEARCH_HOSTS=localhost:9200
ELASTICSEARCH_USER=elastic
ELASTICSEARCH_PASS=changeme

With API Key (takes precedence over Basic Auth):

ELASTICSEARCH_HOSTS=localhost:9200
ELASTICSEARCH_API_KEY=base64encodedapikey

Where to get an API key: https://cloud.elastic.co > Your deployment > Stack Management > Security > API Keys > Create API key

Elastic Cloud:

SMARTSEARCH_DRIVER=elasticsearch
ELASTICSEARCH_CLOUD_ID=my-cluster:dXM...
ELASTICSEARCH_USER=elastic
ELASTICSEARCH_PASS=yourpassword

No port or host needed — Cloud ID resolves endpoints automatically.

Where to get Cloud ID: https://cloud.elastic.co > Your deployment > Copy Cloud ID (or Help icon > Connection Details)

Additional Options

ELASTICSEARCH_RETRIES=3          # Connection retries on failure
ELASTICSEARCH_SSL_VERIFY=true    # SSL cert verification
ELASTICSEARCH_ANALYZER=arabic    # Text analyzer (standard, arabic, english, etc.)

Note: The Elasticsearch driver requires a separate install: composer require elasticsearch/elasticsearch. The package detects its presence automatically.

OpenSearch Setup

To use the OpenSearch for Laravel driver, first install the client:

composer require opensearch-project/opensearch-php

Then set the driver in your .env:

SMARTSEARCH_DRIVER=opensearch
SMARTSEARCH_FALLBACK=database

Connecting to OpenSearch

OpenSearch uses the same HTTP API as Elasticsearch. The driver requires opensearch-project/opensearch-php but the setup is almost identical:

Local / self-hosted:

OPENSEARCH_HOSTS=https://localhost:9200
OPENSEARCH_USER=admin
OPENSEARCH_PASS=admin
OPENSEARCH_SSL_VERIFY=false    # Self-signed certs in dev

With API Key:

OPENSEARCH_HOSTS=https://opensearch-cluster:9200
OPENSEARCH_API_KEY=base64encodedapikey

Docker (OpenSearch official image):

# docker-compose.yml
services:
  opensearch:
    image: opensearchproject/opensearch:latest
    environment:
      - discovery.type=single-node
      - plugins.security.disabled=true    # Disable security for dev
    ports:
      - "9200:9200"

Note: OpenSearch is the open-source fork of Elasticsearch — fully compatible API, Apache 2.0 license, no Elastic Cloud dependency. Perfect for self-hosted production search without licensing costs.

Additional Options

OPENSEARCH_RETRIES=3          # Connection retries on failure
OPENSEARCH_SSL_VERIFY=true    # SSL cert verification
OPENSEARCH_ANALYZER=arabic    # Text analyzer (standard, arabic, english, etc.)

Semantic Search (AI-Powered Embeddings & Vector Search)

AI-powered semantic search — a game-changer for the search world.
SmartSearch understands meaning, not just keywords. Powered by free, local Ollama — no subscriptions, no third-party APIs.
Perfect for SEO, user experience, and Arabic & multilingual applications.

SmartSearch supports semantic search using vector embeddings — it understands meaning, not just keywords. This is powered by Ollama (free, local, no API keys).

How it works

SMARTSEARCH_EMBEDDINGS_ENABLED=true
SMARTSEARCH_EMBEDDINGS_PROVIDER=ollama
SMARTSEARCH_EMBEDDINGS_MODEL=nomic-embed-text
SMARTSEARCH_EMBEDDINGS_HOST=http://localhost:11434
Setting Default Description
SMARTSEARCH_EMBEDDINGS_ENABLED false Set to true to enable semantic search
SMARTSEARCH_EMBEDDINGS_PROVIDER ollama Embedding provider (only ollama currently)
SMARTSEARCH_EMBEDDINGS_MODEL nomic-embed-text Model — see ollama embeddings
SMARTSEARCH_EMBEDDINGS_HOST http://localhost:11434 Ollama server URL (Docker: http://ollama:11434)
SMARTSEARCH_EMBEDDINGS_DIMENSIONS auto Vector dimensions (768 for nomic-embed-text)
SMARTSEARCH_EMBEDDINGS_TIMEOUT 30 Request timeout in seconds

1. Install and run Ollama

# Install Ollama: https://ollama.com

# Pull an embedding model
ollama pull nomic-embed-text

# Run the server (starts automatically on install)
ollama serve

Docker:

services:
  ollama:
    image: ollama/ollama:latest
    ports:
      - "11434:11434"
    volumes:
      - ollama_data:/root/.ollama
docker compose exec ollama ollama pull nomic-embed-text

2. Add embedding column to your model's table

Schema::table('products', function ($table) {
    $table->text('embedding')->nullable();
});

3. Configure which fields to embed (optional)

Override searchableEmbeddings() on your model — defaults to the same fields as $smartSearchable:

<?php

use SmartSearch\Traits\SmartSearchable;

class Property extends Model
{
    use SmartSearchable;

    protected array $smartSearchable = ['title', 'description', 'city'];

    public function searchableEmbeddings(): array
    {
        return ['title', 'description', 'city', 'neighborhood'];
    }
}

4. Enable auto-indexing

Set SMARTSEARCH_EMBEDDINGS_ENABLED=true in your .env. The package will generate embeddings for your models automatically on save (via queue jobs).

5. Search semantically

// Full-text + semantic combined (hybrid)
SmartSearch::for(Property::class)
    ->query('شقة في الرياض')
    ->similarTo('قريبة من المدارس والخدمات')  // ← semantic search
    ->where('price', '<', 1000000)
    ->get();

The similarTo() method accepts an optional weight parameter that controls the balance between full-text and semantic results:

// 30% full-text, 70% semantic
->similarTo('قريبة من المدارس', weight: 0.3)

Driver compatibility

Driver Vector Search Mechanism
database Yes Cosine similarity in PHP (TEXT column)
opensearch Yes k-NN query on dense_vector field
elasticsearch Yes knn query on dense_vector field
scout No Depends on Scout provider

Zero-cost semantic search: With database driver + Ollama locally, you get AI-powered search for $0 — no API fees, no external services.

Scout Driver

To use the Scout driver, you first install and configure Laravel Scout normally — it has its own .env variables and config/scout.php settings independent of SmartSearch:

SMARTSEARCH_DRIVER=scout         # SmartSearch uses Scout
SCOUT_DRIVER=algolia             # Scout's own driver (algolia / meilisearch / typesense / database / collection)
ALGOLIA_APP_ID=your-app-id
ALGOLIA_SECRET=your-write-api-key

Since Scout manages its own model events, use Scout's own Searchable trait on your model (not SmartSearch's):

use Laravel\Scout\Searchable;

class Product extends Model
{
    use Searchable;
}

SmartSearch's ScoutDriver will call Scout's API through your model. Auto-indexing is handled by Scout internally.

Service Signup Get API Keys
Algolia https://www.algolia.com/users/sign_up Dashboard > API Keys
MeiliSearch Cloud https://cloud.meilisearch.com Project Settings > API Keys
Typesense Cloud https://cloud.typesense.org Dashboard > API Keys

Scout is optional (require-dev). Run composer require laravel/scout and publish its config to use it.

Environment Variables

Variable Default Description
SMARTSEARCH_DRIVER database Primary search driver: database, elasticsearch, or scout
SMARTSEARCH_FALLBACK database Fallback driver when primary is unavailable
SMARTSEARCH_QUEUE true Enable/disable queue-driven indexing
SMARTSEARCH_CONNECTION default Queue connection for index/delete jobs
SMARTSEARCH_INDEX_PREFIX `` Prefix for all search index names
ELASTICSEARCH_HOSTS localhost:9200 Comma-separated Elasticsearch hosts
ELASTICSEARCH_ANALYZER standard Elasticsearch text analyzer (e.g. arabic, english)

Usage

Basic search

use SmartSearch\Facades\SmartSearch;

$results = SmartSearch::for(Product::class)
    ->query('iphone')
    ->get();

Search with filters

$results = SmartSearch::for(Product::class)
    ->query('iphone')
    ->where('price', '<', 5000)
    ->where('brand', 'Apple')
    ->get();

Paginated search

$results = SmartSearch::for(Product::class)
    ->query('laptop')
    ->paginate(20);

Eloquent-style shortcut

Product::smartSearch('iphone')->get();

Helper function

smartSearch(Product::class, 'iphone')->get();

Auto Indexing

SmartSearch hooks into Eloquent events to keep your search index in sync automatically:

Event Action
created Queue IndexDocument job
updated Queue IndexDocument job
deleted Queue DeleteDocument job

All operations are queue-based (non-blocking) and configurable.

Safe Database Fallback

When your primary search engine (Elasticsearch / Scout) is unavailable:

// No special error handling needed
$results = SmartSearch::for(Product::class)->query('iphone')->get();
// Automatically falls back to database search

The database driver auto-detects your database engine:

Database LIKE Operator Case-Insensitive
MySQL LIKE Depends on collation
PostgreSQL ILIKE Always
SQLite LIKE ASCII
SQL Server LIKE Depends on collation

Arabic & Multilingual Search

Full Arabic search for Laravel and multilingual search support out of the box:

use SmartSearch\Support\ArabicNormalizer;

ArabicNormalizer::normalize('مُحَمَّد'); // محمد
ArabicNormalizer::normalize('أحمد إبراهيم آدم'); // احمد ابراهيم ادم

Configurable Elasticsearch analyzer for any language:

// config/smartsearch.php
'elasticsearch' => [
    'analyzer' => 'arabic', // or 'standard', 'english', custom, etc.
],

Driver System

Driver When to use
DatabaseDriver (default) Works out of the box — no extra packages needed
ElasticsearchDriver High-performance, dedicated search infrastructure
ScoutDriver Already using Laravel Scout (Algolia, MeiliSearch, Typesense)

Configuration

// config/smartsearch.php
return [
    'driver' => env('SMARTSEARCH_DRIVER', 'elasticsearch'),
    'fallback' => env('SMARTSEARCH_FALLBACK', 'database'),
    'queue' => env('SMARTSEARCH_QUEUE', true),
    'connection' => env('SMARTSEARCH_CONNECTION', 'default'),
    'elasticsearch' => [
        'hosts' => explode(',', env('ELASTICSEARCH_HOSTS', 'localhost:9200')),
        'analyzer' => env('ELASTICSEARCH_ANALYZER', 'standard'),
    ],
    'index_prefix' => env('SMARTSEARCH_INDEX_PREFIX', ''),
];

Architecture

Built on clean architecture principles:

  • Strategy Pattern for drivers
  • Service Container binding
  • Event-driven indexing
  • SOLID principles throughout
Laravel Application
    |
    v
Laravel SmartSearch Layer
    |
    v
+---------------------------------------------+
| DatabaseDriver    (default - works OOB)     |
| OpenSearchDriver  (optional - self-hosted)  |
| ElasticsearchDriver (optional - high-perf)  |
| ScoutDriver       (optional - Algolia, ...) |
+---------------------------------------------+
| Automatic safe fallback between drivers     |
+---------------------------------------------+

Use Cases

  • E-commerce search — product search with filters and faceting
  • ERP systems — search across invoices, customers, orders
  • SaaS platforms — multi-tenant search (coming soon)
  • Real estate listings — full-text property search
  • Document management — search titles, descriptions, content
  • Arabic content platforms — normalized Arabic search for Laravel

Requirements

  • PHP 8.1+
  • Laravel 9.x / 10.x / 11.x / 12.x / 13.x
  • Database MySQL / PostgreSQL / SQLite / SQL Server (any Laravel-supported database)
  • Elasticsearch 7.x+ (only if using the Elasticsearch driver — optional)

Contributing

  1. Fork the repo
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Commit your changes (git commit -m 'Add my feature')
  4. Push (git push origin feature/my-feature)
  5. Open a Pull Request

Support

If this Laravel search package helps you:

  • Star the repository on GitHub
  • Report issues
  • Share with the Laravel community
  • Looking for an Elasticsearch Laravel or database search solution? This is it.

License

MIT License. Free for personal and commercial use.