mgussekloo/ laravel-facet-filter
在 Laravel 项目中实现简单的分面过滤(有时称为分面搜索或分面导航),无需烦恼。
dev-master
2024-10-01 06:39 UTC
Requires
- php: ^8.0
- spatie/laravel-package-tools: ^1.9.2
Requires (Dev)
- laravel/pint: ^1.6
- nunomaduro/larastan: ^2.0
- orchestra/testbench: ^8.0
This package is auto-updated.
Last update: 2024-10-01 06:39:19 UTC
README
本包在 Laravel 项目中提供了简单的分面过滤(有时称为分面搜索或分面导航)。它可以帮助您根据模型属性缩小查询结果。
- 免费,无依赖项
- 易于在任何项目中使用
- 易于自定义
- 有一个演示项目可以帮助您入门
贡献
请通过创建拉取请求或报告问题来为此包做出贡献。
安装
此包可以通过Composer安装。
composer require mgussekloo/laravel-facet-filter
准备您的项目
发布并运行迁移
php artisan vendor:publish --tag="facet-filter-migrations"
php artisan migrate
更新您的模型
为应该支持分面过滤的模型添加 Facettable 特性和 facetDefinitions() 方法。
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Mgussekloo\FacetFilter\Traits\Facettable; class Product extends Model { use HasFactory; use Facettable; public static function facetDefinitions() { // Return an array of definitions return [ [ 'title' => 'Main color', // The title will be used for the parameter. 'fieldname' => 'color' // Model property from which to get the values. ], [ 'title' => 'Sizes', 'fieldname' => 'sizes.name' // Use dot notation to get the value from related models. ] ]; } }
构建索引
在您开始过滤之前,您必须构建一个索引。该包包含一个索引器。
use Mgussekloo\FacetFilter\Indexer; $products = Product::with(['sizes'])->get(); // get some products $indexer = new Indexer(); $indexer->resetIndex(); // clear the entire index or... $indexer->resetRows($products); // clear only the provided models $indexer->buildIndex($products); // process the models
获取结果
将分面过滤器应用于查询
$filter = request()->all(); // use the request parameters $filter = ['main-color' => ['green']]; // (or provide your own array) $products = Product::facetsMatchFilter($filter)->get();
构建前端
$facets = Product::getFacets(); /* You can filter and sort like any regular Laravel collection. */ $singleFacet = $facets->firstWhere('fieldname', 'color'); /* Find out stuff about the facet. */ $paramName = $singleFacet->getParamName(); // "main-color" $options = $singleFacet->getOptions(); /* Options look like this: (object)[ 'value' => 'Red', 'selected' => false, 'total' => 3, 'slug' => 'color_red', 'http_query' => 'main-color%5B1%5D=red&sizes%5B0%5D=small' ] */
基本前端示例
这是一个简单的演示项目,展示了基本的前端。
<div class="flex"> <div class="w-1/4 flex-0"> @foreach ($facets as $facet) <p> <h3>{{ $facet->title }}</h3> @foreach ($facet->getOptions() as $option) <a href="?{{ $option->http_query }}" class="{{ $option->selected ? 'underline' : '' }}">{{ $option->value }} ({{ $option->total }}) </a><br /> @endforeach </p><br /> @endforeach </div> <div class="w-3/4"> @foreach ($products as $product) <p> <h1>{{ $product->name }} ({{ $product->sizes->pluck('name')->join(', ') }})</h1> {{ $product->color }}<br /><br /> </p> @endforeach </div> </div>
Livewire 示例
这是 Livewire 的样子。
<h2>Colors</h2> @foreach ($facet->getOptions() as $option) <div class="facet-checkbox-pill"> <input wire:model="filter.{{ $facet->getParamName() }}" type="checkbox" id="{{ $option->slug }}" value="{{ $option->value }}" /> <label for="{{ $option->slug }}" class="{{ $option->selected ? 'selected' : '' }}"> {{ $option->value }} ({{ $option->total }}) </label> </div> @endforeach
自定义
高级索引
扩展索引器来自定义行为,例如将“范围括号”值而不是“单个价格”值保存到索引中。
class MyCustomIndexer extends \Mgussekloo\FacetFilter\Indexer { public function buildValues($facet, $model) { $values = parent::buildValues($facet, $model); if ($facet->getSlug() == 'App\Models\Product.price') { foreach ($values as $index => $value) { if ($value > 0 && $value < 500) { $values[$index] = '0-490'; } if ($value > 490 && $value < 1000) { $values[$index] = '500-990'; } if ($value > 990) { $values[$index] = 'Expensive'; } } } return $values; } }
对非常大的数据集分批处理模型。
$perPage = 1000; $currentPage = Cache::get('facetIndexingPage', 1); $products = Product::with(['sizes'])->paginate($perPage, ['*'], 'page', $currentPage); $indexer = new Indexer($products); if ($currentPage == 1) { $indexer->resetIndex(); } $indexer->buildIndex(); if ($products->hasMorePages()) {} // next iteration, increase currentPage with one }
自定义分面
在分面定义中提供自定义属性和可选的自定义Facet 类。
public static function facetDefinitions() { return [ [ 'title' => 'Main color', 'description' => 'The main color.', // optional custom attribute, you could use $facet->description when creating the frontend... 'related_id' => 23, // ... or use $facet->related_id with your custom indexer 'fieldname' => 'color', 'facet_class' => CustomFacet::class // optional Facet class with custom logic ] ]; }
许可
MIT 许可证(MIT)。请参阅许可文件获取更多信息。