Schema: zatwierdzanie danych
Poręczna biblioteka do walidacji i normalizacji struktur danych względem danego schematu z inteligentnym, łatwym do zrozumienia API.
Instalacja:
Zastosowanie podstawowe
W zmiennej $schema
mamy schemat walidacji (o tym, co to dokładnie znaczy i jak stworzyć taki schemat powiemy
później), a w zmiennej $data
mamy strukturę danych, którą chcemy zwalidować i znormalizować. Mogą to być
np. dane przesłane przez użytkownika poprzez API, plik konfiguracyjny itp.
Zadanie to jest obsługiwane przez klasę Nette\Schema\Processor, która przetwarza dane wejściowe i albo zwraca znormalizowane dane, albo w przypadku błędu rzuca wyjątek Nette\Schema\ValidationException.
Metoda $e->getMessages()
zwraca tablicę wszystkich wiadomości jako ciągi znaków, a
$e->getMessageObjects()
zwraca wszystkie wiadomości jako obiekty Nette\Message.
Definiowanie schematu
Teraz stwórzmy schemat. Do jego zdefiniowania służy klasa Nette\Schema\Expect, tak naprawdę definiujemy oczekiwania co
do tego, jak powinny wyglądać dane. Powiedzmy, że dane wejściowe muszą być strukturą (na przykład tablicą) zawierającą
elementy processRefund
typu bool oraz refundAmount
typu int.
Wierzymy, że definicja schematu wygląda na łatwą do zrozumienia, nawet jeśli widzisz ją po raz pierwszy.
Prześlemy następujące dane do walidacji:
Wyjściem, czyli wartością $normalized
, jest obiekt stdClass
. Jeśli chcielibyśmy, aby wyjście
było tablicą, dodamy nadpisanie schematu Expect::structure([...])->castTo('array')
.
Wszystkie elementy struktury są opcjonalne i mają domyślną wartość null
. Przykład:
Fakt, że wartością domyślną jest null
, nie oznacza, że 'processRefund' => null
zostałaby
zaakceptowana w danych wejściowych. Nie, dane wejściowe muszą być booleanem, czyli tylko true
lub
false
. Aby dopuścić null
musielibyśmy wyraźnie użyć
Expect::bool()->nullable()
.
Wpis może być obowiązkowy za pomocą Expect::bool()->required()
. Możemy zmienić wartość domyślną na
false
za pomocą Expect::bool()->default(false)
lub w skrócie Expect::bool(false)
.
A co by było gdybyśmy chcieli oprócz boolean przyjąć 1
a 0
? Następnie wymieniamy wartości,
które dodatkowo pozwalamy znormalizować do boolean:
Teraz znasz już podstawy definiowania schematu i tego, jak zachowują się elementy struktury. Teraz zobaczymy, jakie pozostałe elementy mogą być użyte podczas definiowania schematu.
Typy danych: type()
Wszystkie standardowe typy danych PHP mogą być wymienione w schemacie:
Jak również wszystkie typy obsługiwane przez klasę
Validators, na przykład Expect::type('scalar')
lub w skrócie Expect::scalar()
. Również nazwy
klas lub interfejsów, na przykład Expect::type('AddressEntity')
.
Można również zastosować notację unijną:
Domyślnie zawsze jest to null
z wyjątkiem array
i list
, gdzie jest to puste pole.
(Lista to tablica indeksowana przez rosnący szereg kluczy numerycznych od zera, czyli tablica nieasocjacyjna).
Tablica wartości: arrayOf() listOf()
Tablica jest zbyt ogólną strukturą; bardziej przydatne jest określenie dokładnie, jakie elementy może zawierać. Na przykład tablica, której elementami mogą być tylko ciągi znaków:
Drugi parametr może być użyty do określenia kluczy (od wersji 1.2):
Lista jest tablicą indeksowaną:
Parametr może być również schematem, więc możemy napisać:
Domyślną wartością jest puste pole. Jeśli określisz wartość domyślną, zostanie ona połączona z przekazanymi
danymi. Można to wyłączyć za pomocą mergeDefaults(false)
(od wersji 1.1).
Wyliczenie: anyOf()
anyOf()
reprezentuje wyliczenie wartości lub schematów, które może przyjąć dana wartość. W ten sposób
piszemy tablicę z elementami, które mogą być albo 'a'
, true
, albo null
:
Elementami wyliczenia mogą być również schematy:
Metoda anyOf()
przyjmuje warianty jako pojedyncze parametry, a nie tablice. Aby przekazać mu tablicę wartości,
użyj operatora rozpakowywania anyOf(...$variants)
.
Wartość domyślna to null
. Użyj metody firstIsDefault()
, aby pierwszy element był domyślny:
Struktury
Struktury to obiekty o zdefiniowanych kluczach. Każda z par klucz ⇒ wartość jest określana jako „właściwość“:
Struktury akceptują tablice i obiekty oraz zwracają obiekty stdClass
.
Domyślnie wszystkie właściwości są opcjonalne i domyślnie ustawione na null
. Możesz zdefiniować
właściwości obowiązkowe używając required()
:
Jeśli nie chcesz, aby właściwości z wartością domyślną znalazły się na wyjściu, użyj
skipDefaults()
:
Chociaż null
jest domyślną wartością właściwości optional
, nie jest dozwolone w danych
wejściowych (wartość musi być łańcuchem). Właściwości akceptujące null
są definiowane za pomocą
nullable()
:
Tablica wszystkich właściwości struktury jest zwracana przez metodę getShape()
.
Domyślnie w danych wejściowych nie może być żadnych dodatkowych elementów:
Które można zmienić za pomocą otherItems()
. Jako parametr podajemy schemat, według którego będą walidowane
dodatkowe elementy:
Nową strukturę można utworzyć poprzez wyprowadzenie jej z innej za pomocą extend()
:
Tablica
Tablica ze zdefiniowanymi kluczami. Obowiązują te same zasady, co w przypadku struktur.
Można również zdefiniować tablicę indeksowaną, znaną jako krotka:
Właściwości przestarzałe
Możesz oznaczyć właściwość jako przestarzałą używając metody deprecated([string $message])
. Informacje
o deprecjacji są zwracane za pomocą $processor->getWarnings()
:
Zakresy: min() max()
Użyj min()
i max()
, aby ograniczyć liczbę elementów dla tablic:
W przypadku ciągów, ogranicz ich długość:
W przypadku liczb, ogranicz ich wartość:
Oczywiście można wymienić tylko min()
, lub tylko max()
:
Wyrażenia regularne: pattern()
Możesz użyć pattern()
do określenia wyrażenia regularnego, do którego musi pasować cały łańcuch
wejściowy (tj. tak jakby zawinięty przez ^
a $
):
Niestandardowe ograniczenie: assert()
Wszelkie dodatkowe ograniczenia można określić za pomocą assert(callable $fn)
.
Albo
Do każdego ograniczenia można dodać własny opis. Zostanie to uwzględnione w komunikacie o błędzie.
Metoda ta może być wywoływana wielokrotnie w celu dodania wielu ograniczeń. Można ją łączyć z wywołaniami
transform()
i castTo()
.
Transformacja: transform()
Pomyślnie zweryfikowane dane można modyfikować za pomocą funkcji niestandardowej:
Metoda ta może być wywoływana wielokrotnie w celu dodania wielu przekształceń. Można ją mieszać z wywołaniami
assert()
i castTo()
. Operacje będą wykonywane w kolejności, w jakiej zostały zadeklarowane:
Metoda transform()
może jednocześnie przekształcać i weryfikować wartość. Jest to często prostsze
i mniej zbędne niż łączenie metod transform()
i assert()
. W tym celu funkcja otrzymuje obiekt Context z metodą addError()
, która może
być użyta do dodania informacji o kwestiach walidacji:
Casting: castTo()
Pomyślnie zweryfikowane dane mogą być rzutowane:
Oprócz natywnych typów PHP, można również rzutować na klasy. Rozróżnia to, czy jest to prosta klasa bez konstruktora, czy klasa z konstruktorem. Jeśli klasa nie ma konstruktora, tworzona jest jej instancja, a wszystkie elementy struktury są zapisywane w jej właściwościach:
Jeśli klasa ma konstruktor, elementy struktury są przekazywane jako nazwane parametry do konstruktora:
Rzutowanie w połączeniu z parametrem skalarnym tworzy obiekt i przekazuje wartość jako jedyny parametr do konstruktora:
Normalizacja: before()
Przed walidacją dane mogą zostać znormalizowane przy użyciu metody before()
. Jako przykład rozważmy element,
który musi być tablicą łańcuchów (np. ['a', 'b', 'c']
), ale otrzymuje dane wejściowe w postaci ciągu
a b c
:
Mapowanie do obiektów: from()
Można wygenerować schemat struktury z klasy. Przykład:
Obsługiwane są również klasy anonimowe:
Ponieważ informacje uzyskane z definicji klasy mogą nie być wystarczające, można dodać niestandardowy schemat dla elementów za pomocą drugiego parametru: