Blog Detail

30

Aug
Add Simple Facet Filtering in Your Laravel Applications cover image

arrow_back Add Simple Facet Filtering in Your Laravel Applications

Laravel Facet Filter is an awesome package that provides simple facet filtering in Laravel projects.

Installation

This package can be installed through Composer.

composer require mgussekloo/laravel-facet-filter

Prepare your project

Publish and run the migrations

php artisan vendor:publish --tag="facet-filter-migrations"
php artisan migrate

Update your model

For all models that should support facet filtering, add a Facettable trait and a defineFacets() method. This method returns a title and model property from which to pull the value(s) for each facet.

use Illuminate\Database\Eloquent\Model;
use Mgussekloo\FacetFilter\Traits\Facettable;

class Product extends Model
{
    use Facettable;

    public static function defineFacets()
    {
        return [
            [
                'Main color', /* Title of the facet */
                'color' /* Model property from which to get values */
            ],
            [
                'Size',
                'sizes.name' /* Use dot notation to get the value from related models. */
            ]
    }

Build the index

The included simple indexer iterates over models, populating the facetrows table based on the facet definitions.

namespace App\Console\Commands;

use Illuminate\Console\Command;

use App\Models\Product;
use Mgussekloo\FacetFilter\Indexer;

class IndexFacets extends Command
{

    public function handle()
    {
        /* Build the whole index in one go */
        $products = Product::with(['sizes'])->get();
        $indexer = new Indexer($products);

        $indexer->resetIndex(); // clears the index
        $indexer->buildIndex(); // process all supplied models
    }
}

Usage

Apply facet filtering to a query

A local scope on the Facettable trait, facetsMatchFilter(), applies the filter to the query.

/* Get the filter from the request, e.g. /?main-color=green&size=[s,m] becomes [ 'main-color' => [ 'green' ], 'size' => [ 's', 'm' ] ] */
$arr = request()->all();
$filter = Product::getFilterFromArr($arr);

/* Or from a single query parameter, e.g. /?filter[main-color][0]=green becomes [ 'main-color' => [ 'green' ], 'size' => [ ] ] */
$arr = request()->query('filter');
$filter = Product::getFilterFromArr($arr)

/* Build your query!*/
$products = Product::facetsMatchFilter($filter)->get(); // You can also apply the facets to the subsection of models, e.g. Product::where('discounted', true)->facetsMatchFilter($filter)->get()

Display the facets

This package doesn’t have any opinions about the frontend you should use. This is how you can render the facets:

/* Get the facets to display them in your frontend. Calling getFacets() after you've called facetsMatchFilter() lets the facets have the correct option counts for the queried results. */
$facets = Product::getFacets($filter);

/* It returns a Laravel collection! */
$singleFacet = $facets->firstWhere('fieldname', 'color');

/* A getOptions() method helps you grab the info you need to render the facet. */
$options = $singleFacet->getOptions();

/* Options have these properties: value, slug, selected (whether it's selected in the $filter), total (total occurrences within current results).
[
    (object)[
        'value' => 'Red'
        'selected' => false,
        'total' => 3
        'slug' => 'color_red'
    ],
    (object)[
        'value' => 'Green'
        'selected' => true
        'total' => 2
        'slug' => 'color_green'
    ]
*/

/* There's some other info you can get from a facet, such as a title and the identifying key for the filter. */

$title = $singleFacet->title; // "Main color"
$paramName = $singleFacet->getParamName(); // "main-color"

The above example uses Laravel Livewire’s wire:model directive to communicate a selected option to the backend, but you could use an AJAX request, form submit, or whatever you like. Just make sure to build a correct $filter so you can apply the facetsMatchFilter() scope to refine your query!

For more details or source code, please visit Github

Published at : 30-08-2022

Author : Rizwan Aslam
AUTHOR
Rizwan Aslam

I am a highly results-driven professional with 12+ years of collective experience in the grounds of web application development especially in laravel, native android application development in java, and desktop application development in the dot net framework. Now managing a team of expert developers at Codebrisk.

Launch your project

Launch project