setono/sylius-meilisearch-plugin

Meilisearch integration for your Sylius store

Fund package maintenance!
Setono

Installs: 13

Dependents: 0

Suggesters: 0

Security: 0

Stars: 1

Watchers: 5

Forks: 2

Open Issues: 3

Type:sylius-plugin

dev-master 2024-09-06 13:35 UTC

README

Latest Version Software License Build Status Code Coverage

Meilisearch is an open-source search engine written in Rust, designed to create lightning-fast and hyper-relevant search experiences out of the box.

Installation

composer require setono/sylius-meilisearch-plugin

Import configuration

# config/packages/setono_sylius_meilisearch.yaml
setono_sylius_meilisearch:
    indexes:
        products:
            document: 'Setono\SyliusMeilisearchPlugin\Document\Product'
            entities: [ 'App\Entity\Product\Product' ]
    search:
        index: products

In your .env.local add your parameters:

###> setono/sylius-meilisearch-plugin ###
MEILISEARCH_HOST=http://localhost:7700
MEILISEARCH_MASTER_KEY=YOUR_MASTER_KEY
###< setono/sylius-meilisearch-plugin ###

Import routing

# config/routes/setono_sylius_meilisearch.yaml
setono_sylius_meilisearch:
    resource: "@SetonoSyliusMeilisearchPlugin/Resources/config/routes.yaml"

or if your app doesn't use locales:

# config/routes/setono_sylius_meilisearch.yaml
setono_sylius_meilisearch:
    resource: "@SetonoSyliusMeilisearchPlugin/Resources/config/routes_no_locale.yaml"

Implement the IndexableInterface in your entities

The entities you've configured for indexing has to implement the Setono\SyliusMeilisearchPlugin\Model\IndexableInterface.

In a typical Sylius application for the Product entity it could look like this:

<?php
declare(strict_types=1);

namespace App\Entity\Product;

use Doctrine\ORM\Mapping as ORM;
use Setono\SyliusMeilisearchPlugin\Model\IndexableAwareTrait;
use Setono\SyliusMeilisearchPlugin\Model\IndexableInterface;
use Sylius\Component\Core\Model\Product as BaseProduct;

/**
 * @ORM\Entity
 * @ORM\Table(name="sylius_product")
 */
class Product extends BaseProduct implements IndexableInterface
{
    public function getDocumentIdentifier(): ?string
    {
        return (string) $this->getId();
    }
}

Filter entities to index

When indexing entities, most likely there are some of the entities that you don't want included in the index. There are two ways you can do this. 1) When data is fetched from the database or 2) when data is traversed during indexing. Obviously, the first option is the most efficient, but let's look at both.

Filtering when fetching data from the database

Here you will listen to the \Setono\SyliusMeilisearchPlugin\Event\QueryBuilderForDataProvisionCreated event and modify the query builder accordingly. Here is an example where we filter out disabled products:

<?php
    
namespace App\EventSubscriber;

use Doctrine\ORM\QueryBuilder;
use Setono\SyliusMeilisearchPlugin\Event\QueryBuilderForDataProvisionCreated;
use Sylius\Component\Resource\Model\ToggleableInterface;use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class FilterDisabledEntitiesSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            QueryBuilderForDataProvisionCreated::class => 'filter',
        ];
    }
    
    public function filter(QueryBuilderForDataProvisionCreated $event): void
    {
        if(!is_a($event->entity, ToggleableInterface::class, true)) {
            return;
        }
        
        $queryBuilder = $event->getQueryBuilder();
        $alias = $queryBuilder->getRootAliases()[0];
        $queryBuilder->andWhere($alias . '.enabled = true');
    }
}

Filtering when traversing data

Here you will implement the \Setono\SyliusMeilisearchPlugin\Model\FilterableInterface in your entity and implement the filter method. The example below is the same as the previous example, but this time we filter out disabled products when traversing the data:

<?php

namespace App\Entity\Product;

use Doctrine\ORM\Mapping as ORM;

use Setono\SyliusMeilisearchPlugin\Model\FilterableInterface;
use Setono\SyliusMeilisearchPlugin\Model\IndexableInterface;
use Sylius\Component\Core\Model\Product as BaseProduct;

/**
 * @ORM\Entity
 * @ORM\Table(name="sylius_product")
 */
class Product extends BaseProduct implements IndexableInterface, FilterableInterface
{
    public function getDocumentIdentifier(): ?string
    {
        return (string) $this->getId();
    }
    
    public function filter(): bool
    {
        return $this->isEnabled();
    }
}