NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Query Builder for Laravel

Vyhľadávanie vo viacerých stĺpcoch

AllowedFilter::search(string $name, array $columns, array $asText = []) dá endpointu jedno vyhľadávacie pole, ktoré prehľadá viac stĺpcov naraz: riadok vyhovie, keď frázu obsahuje ktorýkoľvek z nich. Namiesto interného názvu prijíma zoznam stĺpcov:

use RoundlyConsulting\QueryBuilder\AllowedFilter;

->allowedFilters(
    AllowedFilter::search('search', ['name', 'email']),                              // bare columns: index-friendly
    AllowedFilter::search('q', ['name', 'key', 'kind', 'tags'], asText: ['tags']),   // jsonb compared as text
)

// After a join, qualify the columns:
QueryBuilder::for(User::query()->join('teams', 'teams.id', '=', 'users.team_id')->select('users.*'))
    ->allowedFilters(AllowedFilter::search('search', ['users.name', 'teams.name']));

Request sa zostaví do jednej zoskupenej podmienky — na PostgreSQL ILIKE, inde LIKE — pričom vzor aj escape znak sa viažu pre každý stĺpec:

-- GET /users?filter[search]=ann  (PostgreSQL; like on the other engines)
("name" ilike ? escape ? or "email" ilike ? escape ?)
-- bound once per column: '%ann%' and '\'

Jedna fráza

// ?filter[search]=Smith, John         → one phrase: "Smith, John"
// ?filter[search][]=a&filter[search][]=b → rejoined: "a,b"
// ?filter[search]=,                    → no constraint
// ?filter[search]=not:draft            → searched as the text "not:draft"
// ?filter[search]=ann&filter[status]=published → (name or email contains "ann") and status = 'published'
  • Vyhľadávacie pole obsahuje jeden kus textu, preto je čiarka jeho súčasťou: Smith, John sa hľadá presne tak, ako bolo zadané, nikdy ako Smith alebo John. Zámerne sa to líši od zoznamu v partial(), ktorý je OR hodnôt.
  • Zápis poľom sa spojí späť čiarkami. Fráza sa po spojení skráti na limits.max_value_length a potom oreže cez mb_trim (medzery, tabulátory, nezlomiteľné medzery).
  • Prázdna fráza — prázdna, len z bielych znakov alebo len z čiarok — nepridá žiadnu podmienku.
  • Prefix operátora sa nečíta (not:draft sa hľadá ako text) a true / false ostávajú textom.

Doslovne, bezpečne voči NULL a zoskupene

  • %, _ a \ vo fráze sa escapujú a porovnávajú s explicitnou klauzulou escape '\' na každom engine, takže sú to obyčajné znaky.
  • Stĺpec s hodnotou NULL jednoducho nevyhovie; riadok sa aj tak nájde cez iný stĺpec.
  • Stĺpce tvoria jedno OR v zátvorkách, spojené cez AND so všetkými ostatnými filtrami: filter[search]=ann&filter[status]=published nikdy nevráti koncept, ktorý spomína „ann“.
  • Veľkosť písmen rieši engine, rovnako ako pri partial() (pozrite Filtre).

Netextové stĺpce — asText

Holý stĺpec sa porovnáva tak, ako je — nikdy sa neprevádza na malé písmená ani nepretypuje. Stĺpec uvedený v asText (musí byť aj v $columns) sa pretypuje na text:

DriverStĺpec v asTextVeľkosť písmen
PostgreSQL"tags"::text ilike ?Podľa ctype locale databázy, ako pri partial().
MySQL / MariaDBcast(`tags` as char) like ?Podľa collation spojenia (predvolené utf8mb4_unicode_ci v Laraveli ignoruje veľkosť písmen aj diakritiku), takže JSON sa správa ako text.
SQLite a ostatnébez zmenyLen písmená ASCII, ako pri partial().

PostgreSQL nemá ILIKE pre stĺpce json / jsonb, uuid, integer, inet ani natívne enumy: nepretypovaný stĺpec skončí chybou SQLSTATE 42883 (operator does not exist). Každý netextový stĺpec preto uveďte v asText. Na MySQL sa nepretypovaný JSON stĺpec porovnáva binárne — rozlišuje veľkosť písmen, takže foo nenájde ["Foo"] — a aj to asText vyrieši.

Indexy

Keďže sa stĺpec nikdy neprevádza na malé písmená, index gin_trgm_ops (pg_trgm) na ňom sa použije a vyhľadávanie vo viacerých stĺpcoch použije jeden index na stĺpec (BitmapOr), ak ho má každý z nich. lower(col) like ? — čo zvyčajne píšu ručne robené vyhľadávacie callbacky — index stĺpca použiť vôbec nevie. Do asText uvádzajte len netextové stĺpce; omylom uvedený varchar na PostgreSQL nič nestojí (merané na PostgreSQL 16: "title"::text ilike ? aj "title" ilike ? dajú rovnaký plán, oba nad indexom). pg_trgm potrebuje aspoň 3 znaky, aby výsledky vôbec zúžil.

Relácie a chyby v deklarácii

  • Žiadne vyhľadávanie v reláciách — bodka je kvalifikátor tabuľky (posts.title), ako všade v balíku. Ak chcete prehľadať súvisiacu tabuľku, pripojte ju cez join a stĺpce kvalifikujte, alebo použite callback s whereHas.
  • Chybná deklarácia vyhodí InvalidFilterDeclaration (LogicException) už pri vytvorení filtra: žiadne stĺpce, stĺpec, ktorý nie je holý ani tabuľkou kvalifikovaný názov (tags::text, lower(name), name as n — namiesto pretypovania použite asText), alebo stĺpec v asText, ktorý filter neprehľadáva.
  • Duplicitné stĺpce sa odstránia, poradie ostane zachované.

Priame použitie SearchFilter

RoundlyConsulting\QueryBuilder\Filters\SearchFilter — new SearchFilter(array $columns, array $asText = []) — je to, čo obaľuje AllowedFilter::search(). Zaregistrujte ho pod iným názvom cez AllowedFilter::custom() alebo ho použite mimo filter[] pre samostatný parameter ?search=:

use RoundlyConsulting\QueryBuilder\AllowedFilter;
use RoundlyConsulting\QueryBuilder\Filters\SearchFilter;

// The same filter under another wire name:
->allowedFilters(AllowedFilter::custom('q', new SearchFilter(['users.name', 'users.email'])))

// Outside filter[], for a top-level ?search= contract:
(new SearchFilter(['name', 'email']))->apply($query, $request->string('search')->toString(), 'search');

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.