Filtriranje
Kolekcije su liste resursa. Na decoupled sajtu, one se koriste za pravljenje stvari kao što su lista „Novi sadržaj“ ili sekcija „Moj sadržaj“ na klijentskoj strani.
Međutim, kada pošaljete nefiltrirani zahtev ka kolekcionom endpoint-u kao što je /jsonapi/node/article
, dobićete svaki članak koji imate dozvolu da vidite.
Bez filtera, ne možete dobiti samo svoje članke ili samo članke o lamama.
Ovaj vodič će vas naučiti kako da pravite filtere kao profesionalac.
Brzi početak
Najjednostavniji i najčešći filter je key-value filter:
?filter[field_name]=value&filter[field_other]=value
Ovo podudara sve resurse kod kojih je „field_name“ jednako „value“ i „field_other“ jednako „value“.
Za sve ostalo, nastavite sa čitanjem!
Sažetak
JSON:API modul ima neke od najrobustnijih i najbogatijih mogućnosti filtriranja. Sva ta moć dolazi sa određenom krivom učenja.
Na kraju ovog članka, moći ćete da pravite kompleksne upite i razmišljate o problemima sa kojima možete da se suočite, kao što je „kako da dobijem listu članaka autora o lamama ili najbržem članu životinjskog carstva, sokolu lastavičaru?“
Krenućemo od samih osnova. Posle toga, pokazaćemo vam nekoliko prečica koje prave filtere bržim i manje opširnim. Na kraju, videćete mnogo primera filtera iz stvarnog sveta.
Ako niste početnik u Drupalu, verovatno ste već koristili Views modul za ovakve stvari. Za razliku od REST modula koji dolazi uz Drupal Core, JSON:API ne izvozi rezultate iz Viewsa. Kolekcije su JSON:API-jeva API-First zamena za eksportovane „REST prikaze“ u Views-u.
Kreiranje filtera
Osnovni gradivni blokovi JSON:API filtera su uslovi i grupe. Uslovi tvrde da je nešto tačno, a grupe vam omogućavaju da te tvrdnje grupišete u logičke skupove za pravljenje većih grupa uslova. Ti skupovi mogu biti ugnježdeni radi još detaljnijih upita. Možete ih zamisliti kao stablo:
Konvencionalni prikaz:
a( b() && c( d() || e() ) )
Stablo prikaz:
a
/ \
b & c
/ \
d | e
U oba prikaza:
„d” i „e” su članovi „c” u OR grupi.
„b” i „c” su članovi „a” u AND grupi.
Šta je u uslovu?
Hajde da budemo logični 🖖. Zapamtite, uslov govori nešto TRUE ili FALSE o resursu i nekoj tvrdnji o njemu, kao na primer „da li je ovaj entitet kreirao određeni korisnik?“ Kada je uslov FALSE za resurs, taj resurs neće biti uključen u kolekciju.
Uslov ima 3 osnovna dela: path (putanja), operator i value (vrednost).
- 'path' identifikuje polje na resursu
- 'operator' je metoda poređenja
- 'value' je ono sa čim upoređujete
U pseudo-kodu, uslov izgleda ovako:
($field !== 'space')
Gde:
$field
je polje resursa identifikovano svojom putanjom- operator je
!==
- vrednost je string
'space'
U JSON:API modulu, ne možemo to prikazati baš tako lepo, jer mora da radi u URL query stringu. Da bismo to postigli, svaki uslov predstavljamo kroz key/value parove.
Ako bismo filtrirali po imenu korisnika, uslov bi izgledao ovako:
?filter[a-label][condition][path]=field_first_name
&filter[a-label][condition][operator]=%3D <- enkodirani "=" simbol
&filter[a-label][condition][value]=Janis
Primetite da u prve uglaste zagrade stavljamo labelu. Mogli smo da napišemo i b-label
ili this_is_my_super_awesome_label
ili čak broj kao 666
🤘😅. Poenta je da svaki uslov ili grupa treba da imaju identifikator.
Ali šta ako imamo puno osoba po imenu Janis?
Dodajmo još jedan filter da dobijemo samo Janis(e) sa prezimenom koje počinje na „J“:
?filter[first-name-filter][condition][path]=field_first_name
&filter[first-name-filter][condition][operator]=%3D <- enkodirani "="
&filter[first-name-filter][condition][value]=Janis
&filter[last-name-filter][condition][path]=field_last_name
&filter[last-name-filter][condition][operator]=STARTS_WITH
&filter[last-name-filter][condition][value]=J
Možda je množina od Janis zapravo „Janii“ 🤔...
Postoji mnogo više filter operatora osim =
i STARTS_WITH
. Evo kompletne liste direktno iz JSON:API koda:
\Drupal\jsonapi\Query\EntityCondition::$allowedOperators = [
'=', '<>',
'>', '>=', '<', '<=',
'STARTS_WITH', 'CONTAINS', 'ENDS_WITH',
'IN', 'NOT IN',
'BETWEEN', 'NOT BETWEEN',
'IS NULL', 'IS NOT NULL',
];
Simbol operatori moraju biti URL-enkodirani. Ispravno enkodiranje možete dobiti kroz PHP funkciju urlencode()
.
Grupe uslova
Sada znamo kako da napravimo uslove, ali još ne znamo kako da napravimo grupe uslova. Kako da napravimo stablo kao što smo videli iznad?
Da bismo to uradili, potrebno je da imamo „grupu“. Grupa je skup uslova povezanih „konjunkcijom“. Sve grupe imaju konjunkciju, a konjunkcija je ili AND ili OR.
Sada je naš filter možda previše specifičan! Recimo da želimo da pronađemo sve korisnike sa prezimenom koje počinje na „J“ i da im je ime „Janis“ ili ime „Joan“.
Da bismo to uradili, dodajemo grupu:
?filter[rock-group][group][conjunction]=OR
Zatim, dodeljujemo naše filtere toj novoj grupi.
Da bismo to uradili, dodajemo memberOf
ključ. Svaki uslov i grupa može imati memberOf
ključ.
Savet: Grupe mogu imati memberOf
ključ kao i uslovi, što znači da možete imati grupe grupa 🤯!
Napomena: Svaki filter bez memberOf
ključa smatra se delom „root“ grupe sa AND konjunkcijom.
U celosti izgleda ovako:
?filter[rock-group][group][conjunction]=OR
&filter[janis-filter][condition][path]=field_first_name
&filter[janis-filter][condition][operator]=%3D
&filter[janis-filter][condition][value]=Janis
&filter[janis-filter][condition][memberOf]=rock-group
&filter[joan-filter][condition][path]=field_first_name
&filter[joan-filter][condition][operator]=%3D
&filter[joan-filter][condition][value]=Joan
&filter[joan-filter][condition][memberOf]=rock-group
&filter[last-name-filter][condition][path]=field_last_name
&filter[last-name-filter][condition][operator]=STARTS_WITH
&filter[last-name-filter][condition][value]=J
Izgleda poznato?
Treba, jer smo to već videli kao stablo:
a a = root-and-group
/ \
/ \ b = last-name-filter
b c c = rock-group
/ \
/ \ d = janis-filter
d e e = joan-filter
Možete ugnježditi ove grupe koliko god želite.
Putanje (Paths)
Uslovi imaju još jednu osobinu: 'putanje'
Putanje vam omogućavaju da filtrirate na osnovu vrednosti odnosa.
Do sada smo samo filtrirali po hipotetičkim poljima field_first_name
i field_last_name
na korisničkom resursu.
Zamislite da želimo da filtriramo po imenu korisničke karijere, gde su tipovi karijera sačuvani kao zaseban resurs. Mogli bismo da dodamo filter ovako:
?filter[career][condition][path]=field_career.name
&filter[career][condition][operator]=%3D
&filter[career][condition][value]=Rockstar
Putanje koriste „dot notaciju“ da bi prelazile kroz odnose.
Ako resurs ima odnos, možete dodati filter protiv njega tako što ćete povezati ime polja odnosa i polje odnosa tačkom (.
).
Možete čak filtrirati po odnosima odnosa (i dalje) samo dodavanjem još imena polja i tačaka.
Savet: Možete filtrirati na određeni indeks odnosa stavljanjem nenegativnog celog broja u putanju. Dakle, putanja some_relationship.1.some_attribute
filtriraće samo drugi povezani resurs.
Savet: Možete filtrirati po pod-svojstvima polja. Na primer, putanja kao što je field_phone.country_code
radiće iako field_phone
nije odnos.
Savet: Kada filtrirate konfiguracione osobine, možete koristiti zvezdicu (*) da zamenite bilo koji deo putanje. Na primer, /jsonapi/field_config/field_config?filter[dependencies.config.*]=comment.type.comment
bi pronašao sve field config-e kod kojih ["attributes"]["dependencies"]["config"]
(indeksiran niz) sadrži vrednost „comment.type.comment“.
Prečice
To je dosta karaktera za kucanje. Većinu vremena, ne trebaju vam tako komplikovani filteri, i za te slučajeve, JSON:API modul ima nekoliko „prečica“ da filtere napišete brže.
Kada je operator =
, ne morate ga navesti. Podrazumeva se. Dakle:
?filter[a-label][condition][path]=field_first_name
&filter[a-label][condition][operator]=%3D <- enkodirani "=" simbol
&filter[a-label][condition][value]=Janis
postaje
?filter[janis-filter][condition][path]=field_first_name
&filter[janis-filter][condition][value]=Janis
Takođe, retko ćete morati da filtrirate po istom polju dva puta (iako je moguće). Tako da, kada je operator =
i ne filtrirate po istom polju dva puta, path može biti identifikator. Dakle:
?filter[janis-filter][condition][path]=field_first_name
&filter[janis-filter][condition][value]=Janis
postaje
?filter[field_first_name][value]=Janis
Ono dodatno value
je dosadno. Zato možete smanjiti najjednostavnije provere jednakosti na key-value oblik:
?filter[field_first_name]=Janis
Filteri i kontrola pristupa
Prvo, upozorenje: ne pravite grešku da filtere pomešate sa kontrolom pristupa. Samo zato što ste napisali filter da uklonite nešto što korisnik ne bi trebalo da vidi, ne znači da nije dostupno. Uvek obavljajte provere pristupa na backendu.
Uz to upozorenje, hajde da pričamo o korišćenju filtera kao dopune kontroli pristupa. Radi poboljšanja performansi, treba da filtrirate ono što korisnici ne mogu da vide. Najčešći zahtev za podršku u JSON:API issue queue može se rešiti ovim jednostavnim trikom!
Ako znate da korisnici ne mogu da vide neobjavljen sadržaj, dodajte sledeći filter:
?filter[status][value]=1
Korišćenjem ove metode smanjićete broj nepotrebnih zahteva koje treba da šaljete. To je zato što JSON:API ne vraća podatke za resurse kojima korisnik nema pristup. Možete videti koji resursi su potencijalno pogođeni tako što pogledate meta.errors
sekciju JSON:API dokumenta.
Stoga, trudite se da unapred filtrirate nedostupne resurse.
Primeri filtera
1. Dohvati samo objavljene čvorove
Vrlo čest scenario je da učitate samo čvorove koji su objavljeni. Ovo je veoma lak filter za dodavanje.
KRATAK
filter[status][value]=1
NORMALAN
filter[status-filter][condition][path]=status
filter[status-filter][condition][value]=1
2. Dohvati čvorove po vrednosti reference entiteta
Česta strategija je filtriranje sadržaja po entity reference polju.
KRATAK
filter[uid.id][value]=BB09E2CD-9487-44BC-B219-3DC03D6820CD
NORMALAN
filter[author-filter][condition][path]=uid.id
filter[author-filter][condition][value]=BB09E2CD-9487-44BC-B219-3DC03D6820CD
Da biste u potpunosti poštovali JSON API specifikaciju, dok Drupal interno koristi uuid
osobinu, JSON API koristi id
umesto toga.
Od Drupala 9.3 moguće je filtrirati i po target_id
, a ne samo po uuid
svojstvu.
KRATAK
filter[field_tags.meta.drupal_internal__target_id]=1
NORMALAN
filter[name-filter][condition][path]=field_tags.meta.drupal_internal__target_id
filter[name-filter][condition][value]=1
3. Ugnježdeni filteri: Dohvati čvorove koje je napravio korisnik admin
Moguće je filtrirati po poljima iz