Schema: Adatérvényesítés
Egy praktikus könyvtár az adatstruktúrák érvényesítésére és normalizálására egy adott séma alapján, intelligens és könnyen érthető API-val.
Telepítés:
Alapvető használat
A $schema
változóban van egy érvényesítési séma (hogy ez pontosan mit jelent és hogyan kell létrehozni,
arról később szólunk), a $data
változóban pedig egy adatszerkezet, amelyet érvényesíteni és normalizálni
szeretnénk. Ez lehet például a felhasználó által egy API-n keresztül küldött adat, konfigurációs fájl stb.
A feladatot a Nette\Schema\Processor osztály látja el, amely feldolgozza a bemenetet, és vagy normalizált adatokat ad vissza, vagy hiba esetén egy Nette\Schema\ValidationException kivételt dob.
A $e->getMessages()
módszer az összes üzenetsorozat tömbjét adja vissza, a
$e->getMessageObjects()
pedig az összes üzenetet Nette\Schema\Message objektumként adja vissza.
Séma definiálása
És most hozzunk létre egy sémát. Ennek definiálására a Nette\Schema\Expect osztályt használjuk, tulajdonképpen
elvárásokat határozunk meg arra vonatkozóan, hogy az adatoknak hogyan kell kinézniük. Tegyük fel, hogy a bemeneti adatnak
egy struktúrának (pl. egy tömbnek) kell lennie, amely processRefund
típusú bool és refundAmount
típusú int típusú elemeket tartalmaz.
Úgy gondoljuk, hogy a sémadefiníció egyértelműnek tűnik, még akkor is, ha először látjuk.
Küldjük el a következő adatokat érvényesítésre:
A kimenet, azaz a $normalized
érték a stdClass
objektum. Ha azt akarjuk, hogy a kimenet egy tömb
legyen, akkor a sémához egy castot adunk hozzá Expect::structure([...])->castTo('array')
.
A struktúra minden eleme opcionális, és alapértelmezett értéke null
. Példa:
Az a tény, hogy az alapértelmezett érték null
, nem jelenti azt, hogy a bemeneti adatokban elfogadható lenne
'processRefund' => null
. Nem, a bemeneti adatnak boolean-nak kell lennie, azaz csak true
vagy
false
. A null
-t kifejezetten engedélyeznünk kellene a Expect::bool()->nullable()
-on
keresztül.
Egy elemet a Expect::bool()->required()
segítségével lehet kötelezővé tenni. Az alapértelmezett
értéket a false
segítségével Expect::bool()->default(false)
vagy röviden a
Expect::bool(false)
segítségével -ra változtatjuk.
És mi lenne, ha a booleans mellett a 1
and 0
-t is el akarnánk fogadni? Akkor felsoroljuk a
megengedett értékeket, amelyeket szintén booleanra normalizálunk:
Most már ismered az alapokat, hogyan definiálódik a séma, és hogyan viselkednek a struktúra egyes elemei. Most megmutatjuk, hogy a séma definiálásakor milyen egyéb elemeket lehet használni.
Adattípusok: type()
Az összes szabványos PHP adattípus felsorolható a sémában:
És ezután az összes típus által támogatott
validátorok keresztül Expect::type('scalar')
vagy rövidített Expect::scalar()
. Az osztály- vagy
interfésznevek is elfogadottak, pl. Expect::type('AddressEntity')
.
Használhatjuk az union jelölést is:
Az alapértelmezett érték mindig null
, kivéve a array
és list
, ahol ez egy üres
tömb. (A lista a nullától kezdve a numerikus kulcsok növekvő sorrendjében indexelt tömb, azaz nem
asszociatív tömb).
Értékek tömbje: arrayOf() listOf()
A tömb túl általános struktúra, célszerűbb pontosan megadni, hogy milyen elemeket tartalmazhat. Például egy olyan tömb, amelynek elemei csak karakterláncok lehetnek:
A második paraméterrel megadhatjuk a kulcsokat (az 1.2-es verzió óta):
A lista egy indexelt tömb:
A paraméter lehet egy séma is, így leírhatjuk:
Az alapértelmezett érték egy üres tömb. Ha megadjuk az alapértelmezett értéket, akkor az összeolvad az átadott
adatokkal. Ez kikapcsolható a mergeDefaults(false)
segítségével (az 1.1-es verzió óta).
Felsorolás: anyOf()
anyOf()
azoknak az értékeknek vagy sémáknak a halmaza, amelyek egy érték lehet. Íme, hogyan írjunk egy
olyan elemekből álló tömböt, amely lehet 'a'
, true
vagy null
:
A felsorolás elemei lehetnek sémák is:
A anyOf()
módszer a variánsokat egyéni paraméterként fogadja el, nem tömbként. Ha értékekből álló
tömböt akarunk átadni neki, használjuk a anyOf(...$variants)
kicsomagoló operátort.
Az alapértelmezett érték a null
. A firstIsDefault()
módszerrel az első elemet teheti
alapértelmezetté:
Struktúrák
A struktúrák meghatározott kulcsokkal rendelkező objektumok. A kulcs ⇒ érték párok mindegyikét „tulajdonságnak“ nevezzük:
A struktúrák tömböket és objektumokat fogadnak, és objektumokat adnak vissza stdClass
.
Alapértelmezés szerint minden tulajdonság opcionális, és alapértelmezett értéke null
. Kötelező
tulajdonságokat a required()
segítségével lehet definiálni:
Ha nem szeretne csak alapértelmezett értékkel rendelkező tulajdonságokat kiadni, használja a
skipDefaults()
:
Bár a null
a optional
tulajdonság alapértelmezett értéke, a bemeneti adatokban nem megengedett
(az értéknek egy karakterláncnak kell lennie). A null
-t elfogadó tulajdonságok a nullable()
használatával kerülnek definiálásra:
A getShape()
módszer a struktúra összes tulajdonságát tartalmazó tömböt adja vissza.
Alapértelmezés szerint a bemeneti adatokban nem lehetnek extra elemek:
Amit a otherItems()
segítségével megváltoztathatunk. Paraméterként megadjuk az egyes extra elemek
sémáját:
Új struktúrát hozhat létre egy másik struktúrából származtatva a extend()
segítségével:
Array
Meghatározott kulcsokkal rendelkező tömb. Ugyanazok a szabályok vonatkoznak rá, mint a struktúrákra.
Definiálhatunk indexelt tömböt is, amelyet tuple-nek nevezünk:
Deprecations
A tulajdonságokat a deprecated([string $message])
módszerrel. A visszavonásról szóló értesítéseket a
$processor->getWarnings()
adja vissza:
Tartományok: min() max()
A min()
és a max()
használatával korlátozhatja a tömbök elemeinek számát:
A karakterláncok esetében korlátozza a hosszukat:
Számok esetében korlátozza az értéküket:
Természetesen lehetséges, hogy csak a min()
, vagy csak a max()
:
Szabályos kifejezések: pattern()
A pattern()
segítségével megadhatunk egy olyan reguláris kifejezést, amelynek a összes bemeneti
karakterláncnak meg kell felelnie (azaz mintha a ^
a $
karakterekbe lenne csomagolva):
assert()
Bármilyen más korlátozást is hozzáadhat a assert(callable $fn)
segítségével.
Vagy a
Minden egyes állításhoz saját leírást adhat. Ez a hibaüzenet része lesz.
A módszer többször is meghívható, hogy több korlátozást adjon hozzá. A transform()
és a
castTo()
hívásokkal keverhető.
Transzformáció: transform()
A sikeresen érvényesített adatok egy egyéni függvény segítségével módosíthatók:
A módszer ismételten meghívható több átalakítás hozzáadásához. Ez keverhető a assert()
és a
castTo()
hívásaival. A műveletek a deklaráció sorrendjében kerülnek végrehajtásra:
A transform()
módszer egyszerre tudja átalakítani és érvényesíteni az értéket. Ez gyakran egyszerűbb és
kevésbé redundáns, mint a transform()
és a assert()
láncolása. Ehhez a funkció egy Context objektumot kap egy addError()
metódussal, amely az érvényesítési problémákra vonatkozó információk hozzáadására használható:
Casting: castTo()
Sikeresen érvényesített adatok önthetők:
A natív PHP-típusok mellett osztályokba is átvihetők. Megkülönbözteti, hogy egyszerű, konstruktor nélküli osztályról vagy konstruktorral rendelkező osztályról van-e szó. Ha az osztálynak nincs konstruktora, akkor létrejön egy példánya, és a struktúra minden elemét kiírja a tulajdonságaiba:
Ha az osztálynak van konstruktora, akkor a struktúra elemeit a konstruktornak nevesített paraméterként adjuk át:
A skalár paraméterrel kombinált öntött objektum létrehoz egy objektumot, és az értéket adja át egyetlen paraméterként a konstruktornak:
Normalizálás: before()
Magát az érvényesítést megelőzően az adatok normalizálhatók a before()
módszerrel. Példaként legyen
egy olyan elemünk, amelynek egy stringekből álló tömbnek kell lennie (pl. ['a', 'b', 'c']
), de a bemenetet egy
karakterlánc formájában kapja meg a b c
:
Objektumokra való leképezés: from()
Az osztályból struktúra sémát generálhatunk. Példa:
Névtelen osztályok is támogatottak:
A második paraméterrel egyéni sémát adhat az elemekhez, mivel az osztálydefinícióból kapott információk nem feltétlenül elegendőek: