onstage2426 / fuzor
Dependency-free full-text search for PHP. BM25 ranking, fuzzy and boolean modes, search-as-you-type prefix matching, stopword filtering and Snowball stemming for 62 languages, snippet extraction and result highlighting — one SQLite file, zero infrastructure.
v1.1.0
2026-06-11 11:40 UTC
Requires
- php: >=8.5
Requires (Dev)
- infection/infection: ^0.32.6 || ^0.33.0
- phpbench/phpbench: ^1.5
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^13.1
- rector/rector: ^2.4
- squizlabs/php_codesniffer: ^4.0
README
About
Fuzor is a dependency-free full-text search library for PHP. It tokenises your documents, stores an inverted index in a single SQLite file, and scores results with Okapi BM25 — no external services required.
- BM25 ranked search with automatic typo tolerance
- Boolean search with AND / OR / NOT operators
- Faceted filtering and per-value counts
- Search-as-you-type prefix matching and phrase search
- Stopword filtering and Snowball stemming for 62 languages
- Result highlighting and snippet extraction
- One SQLite file per index — zero infrastructure
Installation
composer require onstage2426/fuzor
Requirements: PHP 8.5+, SQLite 3.46.0+
Usage
use Fuzor\Index; use Fuzor\SchemaConfig; use Fuzor\SearchOptions; use Fuzor\FacetRange; // Create an index — declare facetable fields at creation time $index = new Index('/path/to/products.db', schema: new SchemaConfig( language: 'en', facetFields: ['type', 'price'], )); $index->insert([ ['id' => 1, 'title' => 'Fast sedan', 'body' => 'City car with great fuel economy.', 'type' => 'sedan', 'price' => 24900], ['id' => 2, 'title' => 'Off-road SUV', 'body' => 'Built for adventure and any terrain.', 'type' => 'suv', 'price' => 41500], ['id' => 3, 'title' => 'Electric coupe', 'body' => 'Zero emissions and instant torque.', 'type' => 'coupe', 'price' => 58000], ]); // BM25 ranked search — typo tolerance fires automatically on words ≥ 5 chars $result = $index->search('economi'); // Boolean search $result = $index->searchBoolean('sedan or coupe -electric'); // Faceted search — filter by attribute, count values $result = $index->search('car', new SearchOptions( filter: ['type' => ['sedan', 'suv'], 'price' => FacetRange::max(45000)], facets: ['type'], )); $result->hits; // documents in relevance order $result->facetDistribution; // ['type' => ['sedan' => 1, 'suv' => 1]]
Documentation
- Indexing — creating indexes, inserting, updating, facet fields, rebuild, snapshots
- Search — BM25, boolean, phrases, typo tolerance, synonyms, facets, sorting, distinct
- Language — stopwords, stemming, CJK/Thai n-grams
- Formatting — result highlighting and snippet extraction
- Document store — storing and retrieving raw documents
- Tuning — BM25 parameters, typo tolerance, field boosting
- Performance — read/write index split, snapshots
- Inspect query — debug the query pipeline
License
MIT — see LICENSE.