PHPackages                             fostercommerce/meilisearch-connect - 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. fostercommerce/meilisearch-connect

ActiveCraft-plugin[Search &amp; Filtering](/categories/search)

fostercommerce/meilisearch-connect
==================================

2.0.0(1mo ago)114.5k3[5 issues](https://github.com/FosterCommerce/meilisearch-connect/issues)proprietaryPHPPHP ^8.1CI passing

Since Feb 26Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/FosterCommerce/meilisearch-connect)[ Packagist](https://packagist.org/packages/fostercommerce/meilisearch-connect)[ RSS](/packages/fostercommerce-meilisearch-connect/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (8)Dependencies (14)Versions (17)Used By (0)

[![Meilisearch Connect Icon](resources/img/header.png)](resources/img/header.png)

Meilisearch Connect
===================

[](#meilisearch-connect)

Meilisearch Connect enables seamless data synchronization between Craft CMS and Meilisearch, allowing your Craft entries and custom fields to be indexed and searched efficiently.

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

[](#requirements)

- PHP &gt;=8.1.0
- CraftCMS ^4.6.0|^5.0.0
- Meilisearch ^1.11.0

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

[](#installation)

You can install this plugin from the Plugin Store or with Composer.

#### From the Plugin Store

[](#from-the-plugin-store)

Go to the Plugin Store in your project’s Control Panel and search for “meilisearch”. Then press “Install”.

#### With Composer

[](#with-composer)

Open your terminal and run the following commands:

```
# Go to the project directory
cd /path/to/my-project.test

# Tell Composer to load the plugin
composer require fostercommerce/craft-meilisearch

# Tell Craft to install the plugin
php craft plugin/install meilisearch
```

Configuration
-------------

[](#configuration)

This plugin can be configured using a regular associative array. Take a look at the [Settings](src/models/Settings.php) class to see all the possible configuration options.

A more convenient method to configuring the plugin is to use the builder classes provided.

These classes allow you to provide just the values necessary to configure your indices, and they provide type-hinting and documentation to make it easier to configure.

### Index handles and index IDs

[](#index-handles-and-index-ids)

When configuring the `indices` array in the plugin config file, each index is represented by a handle. This handle is the *key* in the associative array.

For example:

```
'indices' => [
	'pages' => // ...
	'products' => // ...
]
```

*Meilisearch* uses Index IDs for each index.

By default, Meilisearch Connect will use the handle give for an index as it's Index ID in Meilisearch.

If you'd like use a different ID, you can instead specify the ID yourself by calling `withIndexId`:

```
'indices' => [
	'pages' => IndexBuilder::create()->withIndexId('pages_index')->build(),
	'products' => IndexBuilder::create()->withIndexId('products_index')->build(),
]
```

This is particularly useful if you want to segment indices on shared Meilisearch instances for dev or staging environments.

For example, if you had a staging environment which hosted a number of sites and their respective indices, you can set an environment variable of your choosing to set the Index ID:

```
# .env
MEILISEARCH_PAGES_INDEX=mysite_staging_pages
MEILISEARCH_PRODUCTS_INDEX=mysite_staging_products
```

```
// config.php:
'indices' => [
	'pages' => IndexBuilder::create()
		->withIndexId(App::env('MEILISEARCH_PAGES_INDEX') ?? 'pages')
		->build(),
	'products' => IndexBuilder::create()
		->withIndexId(App::env('MEILISEARCH_PRODUCTS_INDEX') ?? 'products')
		->build(),
]
```

### [Search-only configuration](src/config.search-only.php)

[](#search-only-configuration)

Search-only configuration is useful if you're syncing data to Meilisearch from somewhere other than Craft, but you'd like to search that data from Craft.

The most basic configuration is to simply specify the index handle. This plugin only needs to know where to look in Meilisearch to enable searching.

#### Example configuration

[](#example-configuration)

```
return [
	'meiliHostUrl' => 'http://localhost:7700',
	'meiliSearchApiKey' => '',
	'indices' => [
		'pages' => IndexBuilder::create()->build(),
	],
];
```

### [Full configuration](src/config.php)

[](#full-configuration)

When using a full configuration, the `IndexSettingsBuilder` can be used to assist with configuring the *settings* for the index.

To see what the various index settings options are, have a look at Meilisearch [API reference](https://www.meilisearch.com/docs/reference/api/settings).

#### Element queries

[](#element-queries)

If you're planning on indexing elements, such as Entry's, you can make use of the `withElementQuery` builder method.

This method takes an element query, and a transform function.

The element query can be any implementation of `ElementQuery` or a callable that returns an instance of `ElementQuery`.

It is preferred to use a callable to prevent any possibility of running a query immediately when parsing the config. For example when passing a site handle to the `site` filter, Craft will run a query to fetch the site's ID immediately. This can trigger the warning "Element query executed before Craft is fully initialized."

The transform function receives items from the result of the query and must return an associative array. If the transform function returns a [falsey](https://www.php.net/manual/en/function.empty.php) value, then the item will be skipped from indexing.

It is possible to return multiple documents for each item returned by the query. To do this, return an array of associative arrays from the transform function, instead of a single associative array. For example:

```
->withElementQuery(
	static fn (): ProductQuery => Product::find()->site($siteHandle),
	static function (Entry $entry): array {
		return [
			['id' => $entry->id . '_a'], // Document 1
			['id' => $entry->id . '_b'], // Document 2
		];
	}
)
```

Set the `pageSize` using `withPagesSize` to configure how many elements should be indexed at a time when synchronizing an entire index.

#### Custom data

[](#custom-data)

If you're indexing non-standard data, i.e. anything that isn't an `ElementQuery`, you can implement your own `fetch` and `pages` functions.

`fetch` is a function which returns a [`Generator`](https://www.php.net/manual/en/language.generators.syntax.php) or an array.

If your `fetch` returns a Generator, it is useful to also set the `pages`. The `pages` function which takes the current `Index` and returns the total amount of pages expected to be returned for that index.

This is useful when synchronizing all data for an index using a queue job.

#### Example configuration

[](#example-configuration-1)

```
return [
	'meiliHostUrl' => 'http://localhost:7700',
	'meiliAdminApiKey' => '',
	'meiliSearchApiKey' => '',
	'indices' => [
		'pages' => IndexBuilder::fromSettings(
			IndexSettingsBuilder::create()
				->withRanking([
					'customRanking:desc',
					'words',
					'exactness',
					'proximity',
					'attribute',
					'date:desc',
					'sort',
					'typo',
				])
				->withSearchableAttributes([
					'id',
					'title',
					'section',
				])
				->withFaceting([
					'maxValuesPerFacet' => 300,
				])
				->build()
		)
			->withElementQuery(
				static fn (): EntryQuery => Entry::find(), // Get all entries
				static fn (Entry $entry): array => [
					// Transform the entry
					'id' => $entry->id,
					'title' => $entry->title,
					'section' => $entry->section->handle ?? '',
					'url' => $entry->getUrl(),
					// Any other fields you want to include in indexed content
				]
			)
			->build(),
	],
];
```

Usage
-----

[](#usage)

### Ensuring data is up-to-date

[](#ensuring-data-is-up-to-date)

#### Automatically

[](#automatically)

Indices which have `autoSync` set to true, *and* are using an `ElementQuery`, will automatically synchronize data to their respective indices on Meilisearch.

##### Active check

[](#active-check)

The plugin will check whether the element is active before decided whether to update it in the index.

If it is active, it'll will either update or create the item in Meilisearch.

Otherwise, it will delete the item from Meilisearch.

The default active statuses are `Element::STATUS_ENABLED` and `Entry::STATUS_LIVE`. However, different element types can have different active statuses. For example, in Craft Commerce, a `Product` also has `STATUS_LIVE`.

In this case the `activeStatuses` array should be set for the index to indicate which values you're expecting to indicate that an element is active.

#### Manually

[](#manually)

Auto sync will not work if you have one or more of the following config:

- `autoSync` is false;
- `query` is not an instance of `ElementQuery` or a subclass of that.

In this case, you have two recommended options to keep data in Meilisearch indices up-to-date with your data in Craft:

- Running the sync/all or sync/index commands on a schedule, for example, via crontab, or
- If you're indexing Craft Elements or Entries, updating the data for that item using a save or delete event.

#### `Element::EVENT_AFTER_SAVE`

[](#elementevent_after_save)

```
Event::on(
	Product::class,
	Element::EVENT_AFTER_SAVE,
		static function (\craft\events\ModelEvent $event) {
		if (
			! ElementHelper::isDraft($event->sender) &&
			! $event->sender->resaving &&
			! ElementHelper::isRevision($event->sender)
		) {
			$item = $event->sender;
			$status = $item->getStatus();
			if ($status === Entry::STATUS_LIVE) {
				// If an entry is live, then we can add it to the index
				Queue::push(new SyncJob([
					'indexHandle' => 'pages',
					'sourceHandle' => $item->id,
				]));
			} else {
				// Otherwise, we should make sure that it is not in the index
				Queue::push(new DeleteJob([
					'indexHandle' => 'pages',
					'sourceHandle' => $item->id,
				]));
			}
		}
	}
);
```

#### `Element::EVENT_AFTER_DELETE`

[](#elementevent_after_delete)

```
Event::on(
	Product::class,
	Element::EVENT_AFTER_DELETE,
	static function (\craft\events\Event $event) {
		$item = $event->sender;
		Queue::push(new DeleteJob([
			'sourceHandle' => $item->id,
		]));
	}
);
```

### Search

[](#search)

#### From Twig

[](#from-twig)

This plugin exposes a Twig Variable which can be used to search against your Meilisearch instance.

```
{% set searchResults = craft.meilisearch.search('my-index', query, {'hitsPerPage': 25}) %}
```

`search` takes four arguments. The index handle, your search query, search parameters, and an options array.

The search parameters are [extra parameters](https://www.meilisearch.com/docs/reference/api/search#body) which are sent with the search request to Meilisearch.

Options are additional options to pass to [meilisearch-php](https://github.com/meilisearch/meilisearch-php).

The return value is an associative array with the following keys:

- `results`: An array of results containing the data for each record returned from Meilisearch.
- `pagination`: A standard Craft pagination instance.

### Console Commands

[](#console-commands)

#### `meilisearch-connect/sync/settings`

[](#meilisearch-connectsyncsettings)

Synchronize settings for all indices.

**Note** that this should be run whenever the `settings` key for an index changes. Running this after a deployment is usually a good idea.

#### `meilisearch-connect/sync/index `

[](#meilisearch-connectsyncindex-index-name)

Synchronize data for the given index

#### `meilisearch-connect/sync/all (default)`

[](#meilisearch-connectsyncall-default)

Synchronizes data to all indices.

#### `meilisearch-connect/sync/flush `

[](#meilisearch-connectsyncflush-index-name)

Flushes data for the given index.

#### `meilisearch-connect/sync/flush-all`

[](#meilisearch-connectsyncflush-all)

Flushes data for all indices.

#### `meilisearch-connect/sync/refresh-all`

[](#meilisearch-connectsyncrefresh-all)

Flush and synchronize data for all indices.

### Control Panel Utility

[](#control-panel-utility)

A UI has been provided to allow quick and easy access to controls for syncing and flushing operations on all of your indexes. The utility can be found under Utilities-&gt;Meilisearch Connect.

[![Meilisearch Connect control panel utility](resources/img/cputility.png)](resources/img/cputility.png)

### Events

[](#events)

#### `Sync::EVENT_BEFORE_SYNC_CHUNK`

[](#syncevent_before_sync_chunk)

This event is triggered before a chunk of data is synced to Meilisearch. Data can be modified here before it is synced to Meilisearch.

```
Event::on(
	Sync::class,
	Sync::EVENT_BEFORE_SYNC_CHUNK,
	static function (SyncEvent $event) {
		// Do something with $event->chunk before it's synced.
	}
);
```

#### `Sync::EVENT_AFTER_SYNC_CHUNK`

[](#syncevent_after_sync_chunk)

This event is triggered after a chunk of data is synced to Meilisearch.

```
Event::on(
	Sync::class,
	Sync::EVENT_AFTER_SYNC_CHUNK,
	static function (SyncEvent $event) {
		// Do something with $event->chunk after it's synced.
	}
);
```

###  Health Score

49

—

FairBetter than 94% of packages

Maintenance86

Actively maintained with recent releases

Popularity30

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 71.2% of commits — single point of failure

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 ~38 days

Recently: every ~52 days

Total

11

Last Release

51d ago

Major Versions

1.x-dev → 2.0.02026-03-18

### Community

Maintainers

![](https://www.gravatar.com/avatar/9ac5b96165dd51aed8f0b9ea079d5d5beeb430a915cd07d645db0a228b0ac3aa?d=identicon)[fostercommerce](/maintainers/fostercommerce)

---

Top Contributors

[![johnnynotsolucky](https://avatars.githubusercontent.com/u/4161106?v=4)](https://github.com/johnnynotsolucky "johnnynotsolucky (52 commits)")[![peteeveleigh](https://avatars.githubusercontent.com/u/827065?v=4)](https://github.com/peteeveleigh "peteeveleigh (12 commits)")[![timoschwarzer](https://avatars.githubusercontent.com/u/8849554?v=4)](https://github.com/timoschwarzer "timoschwarzer (5 commits)")[![bramnijssen](https://avatars.githubusercontent.com/u/49712778?v=4)](https://github.com/bramnijssen "bramnijssen (2 commits)")[![sjcallender](https://avatars.githubusercontent.com/u/984311?v=4)](https://github.com/sjcallender "sjcallender (2 commits)")

### Embed Badge

![Health badge](/badges/fostercommerce-meilisearch-connect/health.svg)

```
[![Health](https://phpackages.com/badges/fostercommerce-meilisearch-connect/health.svg)](https://phpackages.com/packages/fostercommerce-meilisearch-connect)
```

###  Alternatives

[studioespresso/craft-scout

Craft Scout provides a simple solution for adding full-text search to your entries. Scout will automatically keep your search indexes in sync with your entries.

80136.8k](/packages/studioespresso-craft-scout)[statamic-rad-pack/meilisearch

meilisearch search driver for Statamic

1661.7k](/packages/statamic-rad-pack-meilisearch)[swixpop/locate

Harness the power of the Google Autocomplete API inside Craft. Adds an autocomplete search box to Craft entries.

154.8k](/packages/swixpop-locate)[swishdigital/faceted-navigation

Provides faceted navigation of entries, using categories, which allows site users to narrow the list of entries they see by applying multiple filters (think Amazon or eBay left sidebar).

152.4k](/packages/swishdigital-faceted-navigation)[fork/craft-elastica

A plugin to connect to Elasticsearch and persist elements via hooks

101.8k](/packages/fork-craft-elastica)

PHPackages © 2026

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