Schema: валидиране на данни
Практична библиотека за проверка и нормализиране на структури от данни в съответствие с дадена схема, с интелигентен и лесен за разбиране API.
Инсталация:
Използване на
В променливата $schema
имаме схема за валидиране (какво точно
означава тя и как да я създадем, ще обясним по-късно), а в променливата
$data
имаме структура от данни, която искаме да валидираме и
нормализираме. Това могат да бъдат например данни, изпратени от
потребителя чрез API, конфигурационен файл и т.н.
Задачата се изпълнява от класа Nette\Schema\Processor, който обработва входните данни и връща нормализирани данни или при грешка хвърля изключение Nette\Schema\ValidationException.
Методът $e->getMessages()
връща масив от всички низове на
съобщенията, а $e->getMessageObjects()
връща всички съобщения като
обекти Nette\Schema\Message.
Определяне на схема
Сега нека създадем схема. С класа Nette\Schema\Expect всъщност определяме
как трябва да изглеждат данните. Да предположим, че входните данни
трябва да са структура (например масив), съдържаща елементите
processRefund
от тип bool и refundAmount
от тип int.
Смятаме, че дефиницията на схемата изглежда ясна, дори ако я виждате за първи път.
Ще изпратим следните данни за проверка:
Изходът, т.е. стойността $normalized
, е обектът stdClass
. Ако
искаме резултатът да бъде масив, добавяме преобразуване на схемата
Expect::structure([...])->castTo('array')
.
Всички елементи на структурата са незадължителни и имат стойност по
подразбиране null
. Пример:
Фактът, че стойността по подразбиране е null
, не означава, че тя
ще бъде приета във входните данни 'processRefund' => null
. Не, входните
данни трябва да са булеви, т.е. само true
или false
. Ще трябва
изрично да разрешим null
чрез Expect::bool()->nullable()
.
Елементът може да бъде направен задължителен с помощта на
Expect::bool()->required()
. Променяме стойността по подразбиране на
false
, като използваме Expect::bool()->default(false)
или за кратко
Expect::bool(false)
.
Но какво ще стане, ако искаме да приемаме 1
и 0
в
допълнение към булевите числа? Нека изброим валидните стойности, които
също нормализираме в булеви:
Вече знаете основите на това как се дефинира една схема и как се държат отделните елементи на структурата. Сега ще ви покажем какви други елементи могат да се използват при дефинирането на схемата.
Типове данни: type()
Всички стандартни типове данни на PHP могат да бъдат изброени в схемата:
И след това всички типове, поддържани от валидаторите чрез
Expect::type('scalar')
или съкратено Expect::scalar()
. Приемат се и имена
на класове или интерфейси, например: Expect::type('AddressEntity')
.
Можете също така да използвате запис на съюз:
Стойността по подразбиране винаги е null
, с изключение на
array
и list
, където тя е празен масив. (Списъкът е масив,
индексиран във възходящ числов ред на ключовете от нула, т.е.
неасоциативен масив).
Масив от стойности: arrayOf() listOf()
Масивът е твърде обща структура, по-полезно е да се посочи точно кои елементи може да съдържа. Например масив, чиито елементи могат да бъдат само низове:
Вторият параметър може да се използва за задаване на ключове (от версия 1.2):
Списъкът е индексиран масив:
Параметърът може да бъде и схема, така че можем да напишем
Стойността по подразбиране е празен масив. Ако посочите стойност по
подразбиране, тя ще бъде обединена с предадените данни. Това може да
бъде деактивирано с mergeDefaults(false)
(от версия 1.1 нататък).
Изброяване: anyOf()
anyOf()
– е набор от стойности или модели, които могат да бъдат
стойност. Ето как да запишете масив от елементи, които могат да бъдат
или 'a'
, или true
, или null
:
Елементите на изброяване могат да бъдат и схеми:
Методът anyOf()
приема варианти като отделни параметри, а не като
масив. За да му предадете масив от стойности, използвайте оператора за
разопаковане anyOf(...$variants)
.
Стойността по подразбиране е null
. Използвайте метода
firstIsDefault()
, за да направите първия елемент по подразбиране:
Структури
Структурите са обекти с определени ключове. Всяка от тези двойки ключ ⇒ стойност се нарича „свойство“:
Структурите приемат масиви и обекти и връщат обекти stdClass
.
По подразбиране всички свойства са незадължителни и имат стойност по
подразбиране null
. Можете да дефинирате задължителни свойства,
като използвате required()
:
Ако не искате да извеждате свойствата само със стойността по
подразбиране, използвайте skipDefaults()
:
Въпреки че null
е стойността по подразбиране на свойството
optional
, тя не е разрешена във входа (стойността трябва да бъде низ).
Свойствата, приемащи стойността null
, се дефинират с помощта на
nullable()
:
Масивът от всички свойства на структурата се връща от метода
getShape()
.
По подразбиране във входните данни не може да има допълнителни елементи:
Променяйте подобни елементи с otherItems()
. Ще посочим схемата за
всеки допълнителен елемент като параметър:
Можете да създадете нова структура, като я извлечете от друга с
помощта на extend()
:
Масив
Масив с дефинирани ключове. Прилагат се същите правила като за структурите.
Можете да дефинирате и индексиран масив, известен като кортеж:
Остарели елементи
Можете да обявите дадено свойство за неактуално с помощта на
deprecated([string $message])
. Остарелите известия се връщат с помощта на
$processor->getWarnings()
:
Обхвати: min() max()
Използвайте min()
и max()
, за да ограничите броя на
елементите в масивите:
За низове ограничете дължината им:
За числата ограничете тяхната стойност:
Разбира се, можете да споменете само min()
, или само max()
:
Редовни изрази: pattern()
С помощта на pattern()
, можете да зададете регулярен израз, който
да съвпада с всички от входния низ (т.е. все едно е обвит в ^
a
$
символи):
Потребителски оператори: assert()
Можете да добавите други ограничения, като използвате
assert(callable $fn)
.
Или
Можете да добавите собствено описание за всяко твърдение. Това ще бъде част от съобщението за грешка.
Методът може да бъде извикан многократно, за да се добавят множество
ограничения. Той може да се смесва с извикванията на transform()
и
castTo()
.
Трансформация: transform()
Успешно валидираните данни могат да бъдат модифицирани с помощта на потребителска функция:
Методът може да бъде извикан многократно, за да се добавят множество
трансформации. Той може да се смесва с извиквания на assert()
и
castTo()
. Операциите ще бъдат изпълнени в реда, в който са
декларирани:
Методът transform()
може едновременно да трансформира и валидира
стойността. Това често е по-просто и по-малко излишно от верижното
използване на transform()
и assert()
. За тази цел функцията
получава обект Context с метод
addError()
, който може да се използва за добавяне на информация за
проблеми с валидирането:
Заличаване: castTo()
Успешно валидираните данни могат да бъдат хвърлени:
В допълнение към нативните PHP типове можете да използвате и класове. Той разграничава дали става въпрос за обикновен клас без конструктор или за клас с конструктор. Ако класът няма конструктор, се създава негова инстанция и всички елементи на структурата се записват в свойствата му:
Ако класът има конструктор, елементите на структурата се предават като именувани параметри на конструктора:
Casting в комбинация със скаларен параметър създава обект и предава стойността като единствен параметър на конструктора:
Нормализация: преди()
Преди самото валидиране данните могат да бъдат нормализирани с
помощта на метода before()
. Като пример, нека има елемент, който
трябва да бъде масив от низове (напр, ['a', 'b', 'c']
), но получава вход
като низ a b c
:
Съпоставяне с обекти: from()
Можете да генерирате структурна схема от класа. Пример:
Поддържат се и анонимни класове:
Тъй като информацията, получена от дефиницията на класа, може да не е достатъчна, можете да добавите потребителска схема за елементите с втория параметър: