PHPackages                             croox/statamic-meilisearch-extendable - 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. [Search &amp; Filtering](/categories/search)
4. /
5. croox/statamic-meilisearch-extendable

ActiveLibrary[Search &amp; Filtering](/categories/search)

croox/statamic-meilisearch-extendable
=====================================

Extendable Statamic Meilisearch search driver

4.0.0(11mo ago)11.3k↑11.1%[1 issues](https://github.com/croox/statamic-meilisearch-extendable/issues)MITPHPPHP ^8.2CI passing

Since Jun 16Pushed 10mo agoCompare

[ Source](https://github.com/croox/statamic-meilisearch-extendable)[ Packagist](https://packagist.org/packages/croox/statamic-meilisearch-extendable)[ Docs](https://github.com/croox/statamic-meilisearch-extendable)[ RSS](/packages/croox-statamic-meilisearch-extendable/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (9)Versions (2)Used By (0)

Extendable Statamic Meilisearch Driver
======================================

[](#extendable-statamic-meilisearch-driver)

This addon provides a [Meilisearch](https://www.meilisearch.com/) search driver for Statamic sites that provides additional meilisearch centric features such as facetting, filtering and sorting. Additionally, the driver is extendable, allowing you to add custom behaviour in your own application.

Requirements
------------

[](#requirements)

- PHP 8.1+
- Laravel 10+
- Statamic 5
- Meilisearch 1.0+

Installation
------------

[](#installation)

```
composer require croox/statamic-meilisearch-extendable
```

Usage
-----

[](#usage)

```
// config/statamic/search.php
return [
    'drivers' => [
        'meilisearch' => [
            'credentials' => [
                'url' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
                'secret' => env('MEILISEARCH_KEY', ''),
            ],
        ],
    ],

    'indexes' => [
        'default' => [
            'driver' => 'meilisearch',
            'searchables' => [ 'all' ],
            'snippet_length' => 90, // Optional
            'meilisearch' => [
                // 'filtering' => [
                //     // `type` can be one of the following:
                //     // - `statamic` (default): All filtering logic is done in PHP by statamic itself. Meilisearch fetches all results
                //     //                         without filtering or pagination. This can be inefficient for large datasets.
                //     // - `split`: Filtering that can be done in meilisearch (when the property is found in `filterableAttributes`) is done
                //     //            in meilisearch, the rest is done in PHP.
                //     // - `meilisearch`: All filtering logic is done in meilisearch. If an unhandled where-case is found, then an exception
                //     //                  is thrown. This is the most efficient way to filter results and is required for pagination to work.
                //     'type' => 'meilisearch',
                //     'attributes' => [ 'date', 'tags' ]
                // ],
                // 'pagination' => [
                //     // `type` can be one of the following:
                //     // - `meilisearch`: Pagination is done in meilisearch. Requires `filtering.type` to be set to `meilisearch`
                //     // - `statamic` (default): Pagination is done in PHP. This is the default behaviour of statamic.
                //     'type' => 'meilisearch',
                // ],
                // 'query_options' => [
                //     // See https://www.meilisearch.com/docs/reference/api/search
                //     'distinct' => 'title'
                // ],
                // 'facets' => [
                //     'tags',
                //     'date',
                // ],
                // 'sort_order' => [
                //     // The attributes available for sorting must be listed under `available_fields`
                //     'available_fields' => [ 'date', 'name' ],
                //
                //     // The sort order that is applied by default. If not specified, then the results
                //     // are returned in an order that meilisearch deems most fitting to the search term.
                //     'default_sort' => [ 'date:desc' ],
                //
                //     // Optional
                //     'ranking_rules' => [ /* See https://www.meilisearch.com/docs/learn/filtering_and_sorting/sort_search_results#customize-ranking-rule-order-optional */ ]
                // ],
                // 'synonyms' => [
                //      // Searches for 'Dog' should also yield results containing 'Labrador'
                //     'Dog' => [ 'Labrador' ],
                //
                //     // Searches for 'Labrador' should not yield results containing 'Dog',
                //     // therefor the inverse synonym is not added.
                //     // 'Labrador' => [ 'Dog' ],
                //
                //     // A shorthand is available by not using a key. This is equivalent to
                //     // 'Bed' => [ 'Matrace', 'Futon' ],
                //     // 'Matrace' => [ 'Bed', 'Futon' ],
                //     // 'Futon' => [ 'Bed', 'Matrace' ],
                //     [
                //         'Bed',
                //         'Matrace',
                //         'Futon'
                //     ],
                // ],
            ],
        ],
    ]
]
```

### Metadata

[](#metadata)

In addition to the search results provided through statamic, this driver also provides a `meilisearch_metadata` tag, that contains additional information about the search results. The following metadata may be available:

- `runtime_ms`: The time it took to execute the search in milliseconds.
- `facets`: An array of facets that can be displayed to the user. For more details, check the facets section below.
- `active_sort`: Information about the currently active sort, if any.

```
{{ search:results paginate="20" as="results" }}
  {{ meta = {meilisearch_metadata} }}

  Took {{ meta.runtime_ms }}ms
{{ /search }}
```

### `IndexNamePrefix`

[](#indexnameprefix)

In order to support multiple environments on the same meilisearch instance, the index names are prefixed with the app name and environment. If this does not satisfy your needs, you can override the index name by setting the `index_name` config value.

### `EnsureKeyIsNotMaster`

[](#ensurekeyisnotmaster)

In order to prevent the use of a master key in production, the addon will check if the key is a master key. If it is, it will throw an exception with information on how to create a new, restricted key.

### `AdditionalQueryOptions`

[](#additionalqueryoptions)

You can set custom query options in the config file by using the `query_options` key. These query options will be sent to meilisearch on every search request.

```
// config/statamic/search.php
'indexes' => [
    'default' => [
        // See https://www.meilisearch.com/docs/reference/api/search
        'meilisearch' => [
            'query_options' => [
                'distinct' => 'title'
            ]
        ]
    ]
]
```

### `RawResults`

[](#rawresults)

You can access the raw result from meilisearch by accessing `rawResult`. This can be helpful to get formatted results combined with `query_options`.

```
{{ search:results as="results"}}
    {{ results }}
        {{ rawResult._formatted.title }}
    {{ /results }}
{{ /search:results }}
```

### `Filtering`

[](#filtering)

By default, statamic fetches *all* results from the search index and implements filtering logic in PHP. This is not ideal, as properly optimized search backends such as meilisearch are preferrable for this task. This option modifier allows moving of filtering logic to meilisearch, which is much more efficient.

```
'indexes' => [
    'default' => [
        'meilisearch' => [
            'filtering' => [
                'filtering' => [
                    'type' => 'split', // Or 'statamic' (default) or `meilisearch`
                    'attributes' => [ 'site' ],
                ]
            ]
        ],
    ],
]
```

Attributes found in `attributes` can be processed by meilisearch, so be sure to add them accordingly.

NOTE: Make sure to update the search index by using `please search:update` after changing the `attributes` config option in order to configure the meilisearch index correctly.

The following filter types are available:

- `statamic` (default): All filtering logic is done in PHP. This is the default behaviour of statamic.
- `split`: Filtering that can be done in meilisearch (when the property is found in `filterableAttributes`) is done in meilisearch. The rest is done in PHP.
- `meilisearch`: All filtering logic is done in meilisearch. If an unhandled where-case is found, then an exception is thrown.

### `Pagination`

[](#pagination)

By default, statamic fetches *all* results from the search index and implements pagination logic in PHP. This is not ideal in most cases, as it leads to unnecessary data transfer and processing. This option modifier allows moving of pagination logic to meilisearch, which is much more efficient.

```
'indexes' => [
    'default' => [
        'meilisearch' => [
            'pagination' => [
                'type' => 'meilisearch', // or 'statamic' (default)
            ]
        ],
    ]
]
```

The following pagination types are available:

- `meilisearch`: Pagination is done in meilisearch. Requires `filtering.type` to be set to `meilisearch`
- `statamic` (default): Pagination is done in PHP. This is the default behaviour of statamic. Because this fetches all data from the search index and the meilisearch query must have a limit, `pagination.statamic_hits` can be used in order to control the limit that is sent to meilisearch. It is set to `1000` by default.

### `SearchSnippets`

[](#searchsnippets)

If configured, the search results will contain a `search_snippets` array that mimics the `search_snippets` of the `local` driver: It contains highlighted matches of the search term in the results. This can be activated by using `snippet_length` in the configuration.

```
// config/statamic/search.php
'indexes' => [
    'default' => [
        'snippet_length' => 50
    ]
]
```

NOTE 1: This feature is implemented by leveraging meilisearches highlighting feature. Enabling this implies the following `query_options`: `attributesToHighlight=['*']`, `highlightPreTag=''`, `highlightPostTag=''`. You can customize them if you want to.

NOTE 2: In contrast to the `local` driver, the `search_snippets` array will contain the Tag marking the search query already, making `| mark` in the template unnecessary.

```
{{ search:results as="results"}}
    {{ results }}
        {{ title }}
        {{ search_snippets | implode('...') | substr(0, 300) }}
    {{ /results }}
{{ /search:results }}
```

### `Facets`

[](#facets)

Enables the use of facets for faceted search, allowing you to filter the results based on specific attributes. In order to use facets, you need to configure the `facets` key in the config file and update the search index.

**Note: The search index must be updated every time you change the facets.**

```
'indexes' => [
    'default' => [
        'meilisearch' => [
            'facets' => [
                'tags',
                'number_trained_pets',
                'date',
            ],
        ]
    ],
]
```

The facet values can be accessed in the template using the `facets` metadata key and are expected to be provided as `facet[NAME]` in the request. The following subkeys are available:

- `facet[NAME][values][]`: To filter for one or more specific values
- `facet[NAME][min]`: To filter for values greater than or equal to the given value
- `facet[NAME][max]`: To filter for values less than or equal to the given value
- `facet[NAME][date_min]`: To filter for dates greater than or equal to the given date
- `facet[NAME][date_max]`: To filter for dates less than or equal to the given date

```
{{ search:results paginate="20" as="results" }}
    {{ meta = {meilisearch_metadata} }}

    {{ if meta.facets.tags }}

            all
            {{ foreach :array="meta.facets.tags.distribution" as="value|valueCount" }}

                  {{ value }} ({{ valueCount }})

            {{ /foreach }}

    {{ /if }}

    {{ if meta.facets.number_trained_pets }}

    {{ /if }}

    {{ if meta.facets.date }}

    {{ /if }}

{{ /search:results }}
```

### `QueryTime`

[](#querytime)

Allows using the `runtime_ms` metadata in order to print information about the query runtime.

```
{{ search:results paginate="20" as="results" }}
    {{ meta = {meilisearch_metadata} }}
    Query took {{ meta.runtime_ms }}ms
{{ /search:results }}
```

### `SortOrder`

[](#sortorder)

Allows the user to change the sort order of the results. **Note: The search index must be updated every time you change the config.**

```
'indexes' => [
    'default' => [
        'meilisearch' => [
            'sort_order' => [
                // The attributes available for sorting must be listed under `available_fields`
                'available_fields' => [ 'date', 'name' ],

                // The sort order that is applied by default. If not specified, then the results
                // are returned in an order that meilisearch deems most fitting to the search term.
                'default_sort' => [ 'date:desc' ],

                // Optional
                'ranking_rules' => [ /* See https://www.meilisearch.com/docs/learn/filtering_and_sorting/sort_search_results#customize-ranking-rule-order-optional */ ]
            ],
        ]
    ],
]
```

```

        Default

        Newest first

        Oldest first

        By name ascending

        By name descending

```

### `Synonyms`

[](#synonyms)

In order to improve search result ranking, the `SynonymsOptionModifier` allows specifying a list of synonyms that are passed to meilisearch.

Synonyms can either be defined in the [default meilisearch format](https://www.meilisearch.com/docs/learn/relevancy/synonyms)for more precision or in a shorthand format that automatically adds the inverse

```
'indexes' => [
    'default' => [
        'meilisearch' => [
            'synonyms' => [
                // Searches for 'Dog' should also yield results containing 'Labrador'
                'Dog' => [ 'Labrador' ],

                // Searches for 'Labrador' should not yield results containing 'Dog',
                // therefor the inverse synonym is not added.
                // 'Labrador' => [ 'Dog' ],

                // A shorthand is available by not using a key. This is equivalent to
                // 'Bed' => [ 'Matrace', 'Futon' ],
                // 'Matrace' => [ 'Bed', 'Futon' ],
                // 'Futon' => [ 'Bed', 'Matrace' ],
                [
                    'Bed',
                    'Matrace',
                    'Futon'
                ]
            ],
        ]
    ],
]
```

### Implementing your own `MeilisearchOptionModifier`

[](#implementing-your-own-meilisearchoptionmodifier)

In order to extend the behaviour of the meilisearch addon, you can create your own class extending `MeilisearchOptionModifier`and register it in the config file under `meilisearch_modifiers`.

NOTE: You will probably want to use `...Meilisearch::DEFAULT_MODIFIERS` in order to keep the default modifiers enabled.

```
'indexes' => [
    'default' => [
        'meilisearch_modifiers' => [
            ...\Croox\StatamicMeilisearchExtendable\Meilisearch::DEFAULT_MODIFIERS,
            \App\Modifiers\MyCustomModifier::class,
        ],
    ],
],
```

NOTE: Some query related methods will be called twice for a single query - once in order to fetch the total number of results and then a second time to fetch the actual results. If you want to have different behaviour for the two queries, you can can use `$options['_is_count']`.

### Few words about Document IDs in meilisearch

[](#few-words-about-document-ids-in-meilisearch)

When you index your Statamic Entries, the driver will always transform the ID. This is required because meilisearch only allows `id` to be a string containing alphanumeric characters (a-Z, 0-9), hyphens (-) and underscores (\_). You can read more about this in the [meilisearch documentation](https://www.meilisearch.com/docs/learn/core_concepts/primary_key#invalid_document_id)

As an Entry, Asset, User or Taxonomy reference is a combination of the type, handle/container and ID separated with a `::` (e.g. assets::heros/human01.jpg, categories::cats) this could not be indexed by meilisearch.

As a Workaround, we take care add reference while indexing your entries automatically 🎉.

Internally Statamic will use `\Statamic\Facades\Data::find($reference)` to resolve the corresponding Statamic Entry, Asset, User or Taxonomy.

###  Health Score

32

—

LowBetter than 72% of packages

Maintenance33

Infrequent updates — may be unmaintained

Popularity21

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 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

Unknown

Total

1

Last Release

331d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/68921efba746cfd6337319cd1b4b449729f2baf46489e8d209cbbca346673591?d=identicon)[klickreflex](/maintainers/klickreflex)

![](https://www.gravatar.com/avatar/73afe4e714bad6a4dc26a7d645a84d0166d19fe6a1b6c05deffe755e1e271764?d=identicon)[j6s](/maintainers/j6s)

---

Top Contributors

[![okaufmann](https://avatars.githubusercontent.com/u/4414498?v=4)](https://github.com/okaufmann "okaufmann (50 commits)")[![j6s](https://avatars.githubusercontent.com/u/3374170?v=4)](https://github.com/j6s "j6s (28 commits)")[![duncanmcclean](https://avatars.githubusercontent.com/u/19637309?v=4)](https://github.com/duncanmcclean "duncanmcclean (28 commits)")[![tao](https://avatars.githubusercontent.com/u/1446331?v=4)](https://github.com/tao "tao (19 commits)")[![lakkes-ra](https://avatars.githubusercontent.com/u/63732644?v=4)](https://github.com/lakkes-ra "lakkes-ra (12 commits)")[![ryanmitchell](https://avatars.githubusercontent.com/u/51899?v=4)](https://github.com/ryanmitchell "ryanmitchell (7 commits)")[![Z3d0X](https://avatars.githubusercontent.com/u/75579178?v=4)](https://github.com/Z3d0X "Z3d0X (1 commits)")[![godismyjudge95](https://avatars.githubusercontent.com/u/3847288?v=4)](https://github.com/godismyjudge95 "godismyjudge95 (1 commits)")[![naabster](https://avatars.githubusercontent.com/u/1961461?v=4)](https://github.com/naabster "naabster (1 commits)")[![ym-henkelhiedl](https://avatars.githubusercontent.com/u/40430080?v=4)](https://github.com/ym-henkelhiedl "ym-henkelhiedl (1 commits)")[![andjsch](https://avatars.githubusercontent.com/u/9936988?v=4)](https://github.com/andjsch "andjsch (1 commits)")

---

Tags

searchmeilisearchstatamic

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/croox-statamic-meilisearch-extendable/health.svg)

```
[![Health](https://phpackages.com/badges/croox-statamic-meilisearch-extendable/health.svg)](https://phpackages.com/packages/croox-statamic-meilisearch-extendable)
```

###  Alternatives

[statamic-rad-pack/meilisearch

meilisearch search driver for Statamic

1661.7k](/packages/statamic-rad-pack-meilisearch)[marcorieser/statamic-live-search

A Statamic Live Search realized with Laravel Livewire.

2210.5k](/packages/marcorieser-statamic-live-search)[cmsig/seal

Search Engine Abstraction Layer

32207.9k53](/packages/cmsig-seal)[cmsig/seal-symfony-bundle

An integration of CMS-IG SEAL search abstraction into Symfony Framework.

15195.8k5](/packages/cmsig-seal-symfony-bundle)[omure/scout-advanced-meilisearch

Laravel Scout extension that allows to use meilisearch advanced features as well as has an extended collection driver for testing purposes.

123.9k](/packages/omure-scout-advanced-meilisearch)

PHPackages © 2026

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