PHPackages                             baril/sqlout - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. baril/sqlout

ActiveLibrary[Database &amp; ORM](/categories/database)

baril/sqlout
============

MySQL fulltext driver for Laravel Scout.

v5.2.0(11mo ago)4512.9k↓48.5%6MITPHPPHP ^7.3|^8.0CI passing

Since Sep 26Pushed 11mo ago3 watchersCompare

[ Source](https://github.com/michaelbaril/sqlout)[ Packagist](https://packagist.org/packages/baril/sqlout)[ RSS](/packages/baril-sqlout/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (9)Dependencies (9)Versions (10)Used By (0)

Sqlout 🐬
========

[](#sqlout-dolphin)

[![Version](https://camo.githubusercontent.com/f42f368d3c9da1018f4ec0044f388c7cf007f01e0286c13cdadea3adc28c7221/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f626172696c2f73716c6f75743f6c6162656c3d737461626c65)](https://packagist.org/packages/baril/sqlout)[![License](https://camo.githubusercontent.com/5f8fbaec78d5a9b8de2bd57812828969cd523068e48b2910cf71a83bd4a5afaf/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f626172696c2f73716c6f7574)](https://packagist.org/packages/baril/sqlout)[![Downloads](https://camo.githubusercontent.com/2150f98322a7083d97b1119b757d6634dd5adeda7b1d468803d5343b514143a0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f626172696c2f73716c6f7574)](https://packagist.org/packages/baril/sqlout/stats)[![Tests](https://camo.githubusercontent.com/45265f1b00828aaeea32a0075271b9b5df6aa1fd53c56052344899b87cb32f55/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6d69636861656c626172696c2f73716c6f75742f72756e2d74657374732e796d6c3f6272616e63683d6d6173746572266c6162656c3d7465737473)](https://github.com/michaelbaril/sqlout/actions/workflows/run-tests.yml?query=branch%3Amaster)[![Coverage](https://camo.githubusercontent.com/f79daa13fe5e0394f1e0b5228b4c9e802bf4e85ca50c616f62fd670dbc660cce/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f75726c3d68747470732533412532462532466d69636861656c626172696c2e6769746875622e696f25324673716c6f7574253246636f76657261676525324662616467652e6a736f6e)](https://michaelbaril.github.io/sqlout/coverage/)

Sqlout is a MySQL driver for Laravel Scout. It indexes the data into a dedicated table of the MySQL database, and uses a fulltext index to search. It is meant for small-sized projects, for which bigger solutions such as ElasticSearch would be an overkill.

Sqlout is different than Scout's native `Database` engine because it indexes data in a separate, dedicated table, and uses a fulltext index. Sqlout has more features such as field weights and word stemming.

Sqlout is compatible with Laravel 5.8+ to 12.x and Scout 7.1+ / 8.x / 9.x / 10.x (credit goes to [ikari7789](https://github.com/ikari7789) for Laravel 9 and 10 / Scout 9 and 10 support).

You can find the full API documentation [here](https://michaelbaril.github.io/sqlout/api/).

Version compatibility
---------------------

[](#version-compatibility)

LaravelScoutSqlout11.x / 12.x10.x5.1+9.x / 10.x10.x5.x8.x / 9.x9.x4.x8.x8.x3.x7.x8.x2.06.x8.x2.06.x7.1 / 7.21.x / 2.05.87.1 / 7.21.x / 2.0Setup
-----

[](#setup)

Require the package:

```
composer require baril/sqlout
```

Publish the configuration:

```
php artisan vendor:publish
```

If you're not using package discovery, manually add the service providers (Scout's and Sqlout's) to your `config/app.php` file:

```
return [
    // ...
    'providers' => [
        // ...
        Laravel\Scout\ScoutServiceProvider::class,
        Baril\Sqlout\SqloutServiceProvider::class,
    ],
];
```

Creating the index
------------------

[](#creating-the-index)

Models are indexed in a separate table. You can either create a single table and use it as a global index for all models, or create 1 index table per model (or a mix of both).

### Global index

[](#global-index)

The default name for the table is `searchindex`. If you want to use a different name, you can configure it in `config/scout.php`:

```
return [
    // ...
    'sqlout' => [
        'table_name' => 'my_custom_index_name',
        // ...
    ],
    // ...
];
```

Then, migrate your database:

```
php artisan sqlout:make-migration
php artisan migrate
```

This will create the `searchindex` table (or whatever name you've configured).

### Different connections

[](#different-connections)

If you want to index models that belong to different connections, you need an index table per connection. To create the table on a connection that is not the default connection, you can call the `sqlout:make-migration` command and pass the name of the connection:

```
php artisan sqlout:make-migration my_other_connection
php artisan migrate
```

### Separate indexes

[](#separate-indexes)

If you prefer to index each model in a different table, set the global index name to an empty string:

```
return [
    // ...
    'sqlout' => [
        'table_name' => '',
        // ...
    ],
    // ...
];
```

Each model will be indexed in a table named like the model table followed by `_index`, eg. the `Post` model will be index in `posts_index`.

You can configure a different suffix, and also a prefix, in the config file:

```
return [
    'prefix' => 'sqlout_',
    'suffix' => '',
];
```

You can also customize the table name for each model with the `searchableAs` method (see [next section](#making-a-model-searchable)).

Once you're set up, create the index table for your models like this:

```
php artisan sqlout:make-migration --model="\\App\\Models\\Post"
php artisan migrate
```

Making a model searchable
-------------------------

[](#making-a-model-searchable)

```
namespace App\Models;

use Baril\Sqlout\Searchable;

class Post extends Model
{
    use Searchable;

    protected $weights = [
        'title' => 4,
        'excerpt' => 2,
    ];

    public function toSearchableArray()
    {
        return [
            'title' => $this->post_title,
            'excerpt' => $this->post_excerpt,
            'body' => $this->post_content,
        ];
    }

    // Optionally, you can customize the
    // name of the table that the model
    // will be indexed in:
    public function searchableAs(): string
    {
        return 'my_custom_index';
    }
}
```

The example above is similar to what is described in [Scout's documentation](https://laravel.com/docs/master/scout#configuration), with the following differences/additions:

- The model uses the `Baril\Sqlout\Searchable` trait instead of `Laravel\Scout\Searchable`.
- The `$weight` property can be used to "boost" some fields. The default value is 1.

Once this is done, you can index your data using Scout's Artisan command:

```
php artisan scout:import "App\\Models\\Post"
```

Your models will also be indexed automatically on save.

Searching
---------

[](#searching)

### Basics

[](#basics)

```
$results = Post::search('this rug really tied the room together')->get();
$results = Post::search('the dude abides')->withTrashed()->get();
```

See [Scout's documentation](https://laravel.com/docs/master/scout#searching)for more details.

Sqlout's builder also provides the following additional methods:

```
// Restrict the search to some fields only:
$builder->only('title');
$builder->only(['title', 'excerpt']);
// (use the same names as in the toSearchableArray method)

// Retrieve the total number of results:
$nbHits = $builder->count();
```

### Using scopes

[](#using-scopes)

With Sqlout, you can also use your model scopes on the search builder, as if it was a query builder on the model itself. Similarly, all calls to the `where` method on the search builder will be forwarded to the model's query builder.

```
$results = Post::search('you see what happens larry')
    ->published() // the `published` scope is defined in the Post class
    ->where('date', '>', '2010-10-10')
    ->get();
```

> ⚠️ Keep in mind that these forwarded scopes will actually be applied to a subquery (the main query here being the one on the `searchindex` table). This means that for example a scope that adds an `order by` clause won't have any effect. See below for the proper way to order results.

If the name of your scope collides with the name of a method of the `Baril\Sqlout\Builder` object, you still have the option to use Scout's `query` method:

```
$results = Post::search('ve vant ze money lebowski')
    ->query(function ($query) {
        $query->within('something');
    })
    ->get();
```

### Search modes

[](#search-modes)

MySQL's fulltext search comes in 3 flavours:

- natural language mode,
- natural language mode with query expansion,
- boolean mode.

Sqlout's default mode is "natural language" (but this can be changed in the config file).

You can also switch between all 3 modes on a per-query basis, by using the following methods:

```
$builder->inNaturalLanguageMode();
$builder->withQueryExpansion();
$builder->inBooleanMode();
```

### Ordering the results

[](#ordering-the-results)

If no order is specified, the results will be ordered by score (most relevant first). But you can also order the results by any column of your table.

```
$builder->orderBy('post_status', 'asc')->orderByScore();
// "post_status" is a column of the original table
```

In the example below, the results will be ordered by status first, and then by descending score.

### Filters, tokenizer, stopwords and stemming

[](#filters-tokenizer-stopwords-and-stemming)

In your config file, you can customize the way the indexed content and search terms will be processed:

```
return [
    // ...
    'sqlout' => [
        // ...
        'filters' => [ // anything callable (function name, closure...)
            'strip_tags',
            'html_entity_decode',
            'mb_strtolower',
            'strip_punctuation', // this helper is provided by Sqlout (see helpers.php)
        ],
        'token_delimiter' => '/[\s]+/',
        'minimum_length' => 2,
        'stopwords' => [
            'est',
            'les',
        ],
        'stemmer' => Wamania\Snowball\Stemmer\French::class,
    ],
];
```

In the example, the stemmer comes from the package [`wamania/php-stemmer`](https://github.com/wamania/php-stemmer), but any class with a `stem` method, or anything callable such as a closure, will do.

As for stopwords, you can either list them directly in the config (as shown above), or load them from a file. The file can be either a TXT file (with one stopword per line), or a PHP file that returns an array:

```
// config/scout.php
return [
    // ...
    'sqlout' => [
        // ...
        'stopwords' => 'storage/app/stopwords/fr.php',
        // ...
    ],
];
```

```
// storage/app/stopwords/fr.php
return [
    'à',
    'le',
    'la',
];
```

You may want to use the package [`voku/stop-words`](https://github.com/voku/stop-words), which provides collections of stopwords for various languages as PHP files, or [`yooper/stop-words`](https://github.com/yooper/stop-words), which provides them as TXT files.

###  Health Score

48

—

FairBetter than 95% of packages

Maintenance52

Moderate activity, may be stable

Popularity38

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity69

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~261 days

Recently: every ~239 days

Total

9

Last Release

332d ago

Major Versions

v1.1.0 → v2.0.02020-06-03

v2.0.0 → v3.0.02021-02-27

v3.0.0 → v4.0.02022-11-04

v4.0.1 → v5.0.02023-12-27

PHP version history (2 changes)v1.0.0PHP &gt;=7.0

v4.0.0PHP ^7.3|^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/95cbe396c7a3fe89d006b143506ee5e5645317318f2cf8cf00faf5d327ef6114?d=identicon)[michaelbaril](/maintainers/michaelbaril)

---

Top Contributors

[![michaelbaril](https://avatars.githubusercontent.com/u/11444287?v=4)](https://github.com/michaelbaril "michaelbaril (32 commits)")[![andrew-miller-rakuten](https://avatars.githubusercontent.com/u/159877857?v=4)](https://github.com/andrew-miller-rakuten "andrew-miller-rakuten (23 commits)")[![mbwbd](https://avatars.githubusercontent.com/u/231652605?v=4)](https://github.com/mbwbd "mbwbd (15 commits)")[![ikari7789](https://avatars.githubusercontent.com/u/1041215?v=4)](https://github.com/ikari7789 "ikari7789 (2 commits)")

---

Tags

searchlaravelmysqlfulltextscout

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/baril-sqlout/health.svg)

```
[![Health](https://phpackages.com/badges/baril-sqlout/health.svg)](https://phpackages.com/packages/baril-sqlout)
```

###  Alternatives

[kirschbaum-development/eloquent-power-joins

The Laravel magic applied to joins.

1.6k25.2M34](/packages/kirschbaum-development-eloquent-power-joins)[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[mehdi-fathi/eloquent-filter

Eloquent Filter adds custom filters automatically to your Eloquent Models in Laravel.It's easy to use and fully dynamic, just with sending the Query Strings to it.

450191.6k1](/packages/mehdi-fathi-eloquent-filter)[jeroen-g/explorer

Next-gen Elasticsearch driver for Laravel Scout.

397612.3k](/packages/jeroen-g-explorer)[pmatseykanets/laravel-scout-postgres

PostgreSQL Full Text Search Driver for Laravel Scout

164213.7k2](/packages/pmatseykanets-laravel-scout-postgres)[nqxcode/laravel-lucene-search

Laravel 5.5 package for full-text search over Eloquent models based on ZendSearch Lucene.

7216.5k](/packages/nqxcode-laravel-lucene-search)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
