waaseyaa / search
Search provider interface and DTOs for Waaseyaa
v0.1.0-alpha.256
2026-07-06 21:24 UTC
Requires
- php: >=8.5
- symfony/event-dispatcher: ^7.0
- twig/twig: ^3.0
- waaseyaa/access: ^0.1.0-alpha.256
- waaseyaa/database-legacy: ^0.1.0-alpha.256
- waaseyaa/entity: ^0.1.0-alpha.256
- waaseyaa/foundation: ^0.1.0-alpha.256
Requires (Dev)
- phpunit/phpunit: ^10.5
This package is auto-updated.
Last update: 2026-07-06 21:32:30 UTC
README
Layer 3 — Services
Full-text and structured search for Waaseyaa applications.
Provides a search index abstraction and query builder for finding entities across types. Supports indexed field selection, faceting, and relevance ranking. Integrates with the API layer for search endpoints.
Key classes: SearchRequest, SearchResult, SearchProviderInterface.
Implementation gotchas
- FTS5
SELECT m.*misses FTS5 columns: When joiningsearch_index(FTS5) withsearch_metadata,m.*only selects metadata columns. To get FTS5 content columns (title, body), select them explicitly:si.title,si.body. Thesnippet()function also requires column index references into the FTS5 table. - FTS5 query escaping must strip special chars: FTS5 treats
*,^,{},:,"as operators in addition toAND/OR/NOT/NEAR. Quoting terms with"..."is not sufficient — strip special characters before quoting to prevent query injection. - Access-filtered pagination must share ONE ordered basis for count and fetch (#1915, R16): when an access checker is wired,
Fts5SearchProvider::search()used to derivetotalHits/facets from a bounded access-filtered PHP scan but fetch the page from an independent unfilteredORDER BY ... LIMIT/OFFSETSQL query. A fixed-size OFFSET then walked the wrong sequence (forbidden rows included), so an accessible document sharing a page window with a forbidden one was silently dropped from every page whiletotalPagespromised a page that could never fully materialize. Fixed byaccessFilteredSearch(): ONE bounded, ordered, access-filtered scan derivestotalHits, the requested page's rows, and facets together, so paging always agrees with the total it's measured against. SeeFts5SearchProviderPaginationAccessFilteredTest.