Schema : Validation des données
Une bibliothèque pratique pour la validation et la normalisation des structures de données par rapport à un schéma donné, avec une API intelligente et facile à comprendre.
Installation :
Utilisation de base
Dans la variable $schema
nous avons un schéma de validation (ce que cela signifie exactement et comment le créer
nous le dirons plus tard) et dans la variable $data
nous avons une structure de données que nous voulons valider et
normaliser. Cela peut être, par exemple, des données envoyées par l'utilisateur via une API, un fichier de
configuration, etc.
La tâche est gérée par la classe Nette\Schema\Processor, qui traite l'entrée et renvoie les données normalisées ou lève une exception Nette\Schema\ValidationException en cas d'erreur.
La méthode $e->getMessages()
renvoie un tableau de toutes les chaînes de messages et
$e->getMessageObjects()
renvoie tous les messages sous forme d'objets Nette\Schema\Message.
Définition du schéma
Et maintenant, créons un schéma. La classe Nette\Schema\Expect est utilisée pour le définir, nous
définissons en fait les attentes de ce à quoi les données doivent ressembler. Disons que les données d'entrée doivent être
une structure (par exemple un tableau) contenant des éléments processRefund
de type bool et
refundAmount
de type int.
Nous pensons que la définition du schéma semble claire, même si vous la voyez pour la toute première fois.
Envoyons les données suivantes pour validation :
La sortie, c'est-à-dire la valeur $normalized
, est l'objet stdClass
. Si nous voulons que la sortie
soit un tableau, nous ajoutons un cast au schéma Expect::structure([...])->castTo('array')
.
Tous les éléments de la structure sont facultatifs et ont une valeur par défaut null
. Exemple :
Le fait que la valeur par défaut soit null
ne signifie pas qu'elle serait acceptée dans les données d'entrée
'processRefund' => null
. Non, l'entrée doit être booléenne, c'est-à-dire uniquement true
ou
false
. Il faudrait autoriser explicitement null
via Expect::bool()->nullable()
.
Un élément peut être rendu obligatoire en utilisant Expect::bool()->required()
. Nous changeons la valeur par
défaut en false
en utilisant Expect::bool()->default(false)
ou en peu de temps en utilisant
Expect::bool(false)
.
Et si nous voulions accepter 1
and 0
en plus des booléens ? Nous dressons alors la liste des valeurs
autorisées, que nous normaliserons également en booléen :
Vous connaissez maintenant les bases de la définition du schéma et du comportement des différents éléments de la structure. Nous allons maintenant montrer quels sont tous les autres éléments qui peuvent être utilisés pour définir un schéma.
Types de données : type()
Tous les types de données standard de PHP peuvent être listés dans le schéma :
Et ensuite tous les types supportés par les validateurs
via Expect::type('scalar')
ou en abrégé Expect::scalar()
. Les noms de classes ou d'interfaces sont
également acceptés, par exemple Expect::type('AddressEntity')
.
Vous pouvez également utiliser la notation d'union :
La valeur par défaut est toujours null
, sauf pour array
et list
, où il s'agit d'un
tableau vide. (Une liste est un tableau indexé dans l'ordre croissant des clés numériques à partir de zéro, c'est-à-dire un
tableau non associatif).
Tableau de valeurs : arrayOf() listOf()
Le tableau est une structure trop générale, il est plus utile de spécifier exactement quels éléments il peut contenir. Par exemple, un tableau dont les éléments ne peuvent être que des chaînes de caractères :
Le second paramètre peut être utilisé pour spécifier les clés (depuis la version 1.2) :
La liste est un tableau indexé :
Le paramètre peut aussi être un schéma, on peut donc écrire :
La valeur par défaut est un tableau vide. Si vous spécifiez la valeur par défaut, elle sera fusionnée avec les données
passées. Ceci peut être désactivé en utilisant mergeDefaults(false)
(depuis la version 1.1).
Enumération : anyOf()
anyOf()
est un ensemble de valeurs ou de schémas que peut prendre une valeur. Voici comment écrire un tableau
d'éléments qui peuvent être soit 'a'
, true
, soit null
:
Les éléments de l'énumération peuvent également être des schémas :
La méthode anyOf()
accepte les variantes comme paramètres individuels, et non comme tableau. Pour lui passer un
tableau de valeurs, utilisez l'opérateur de décompression anyOf(...$variants)
.
La valeur par défaut est null
. Utilisez la méthode firstIsDefault()
pour faire du premier élément
la valeur par défaut :
Structures
Les structures sont des objets avec des clés définies. Chacune de ces paires clé ⇒ valeur est appelée „propriété“ :
Les structures acceptent des tableaux et des objets et renvoient des objets stdClass
.
Par défaut, toutes les propriétés sont facultatives et ont une valeur par défaut de null
. Vous pouvez définir
des propriétés obligatoires en utilisant required()
:
Si vous ne souhaitez pas éditer les propriétés ayant uniquement une valeur par défaut, utilisez
skipDefaults()
:
Bien que null
soit la valeur par défaut de la propriété optional
, elle n'est pas autorisée dans
les données d'entrée (la valeur doit être une chaîne de caractères). Les propriétés acceptant null
sont
définies à l'aide de nullable()
:
Le tableau de toutes les propriétés de la structure est renvoyé par la méthode getShape()
.
Par défaut, il ne peut y avoir aucun élément supplémentaire dans les données d'entrée :
Ce que nous pouvons changer avec otherItems()
. En tant que paramètre, nous allons spécifier le schéma pour
chaque élément supplémentaire :
Vous pouvez créer une nouvelle structure en dérivant d'une autre à l'aide de extend()
:
Tableau
Un tableau dont les clés sont définies. Les mêmes règles que pour les structures s'appliquent.
Vous pouvez également définir un tableau indexé, appelé tuple :
Dépréciations
Vous pouvez déprécier une propriété en utilisant la méthode deprecated([string $message])
méthode. Les avis
de dépréciation sont renvoyés par $processor->getWarnings()
:
Plages : min() max()
Utilisez min()
et max()
pour limiter le nombre d'éléments des tableaux :
Pour les chaînes de caractères, limitez leur longueur :
Pour les nombres, limitez leur valeur :
Bien sûr, il est possible de ne mentionner que min()
, ou que max()
:
Expressions régulières : pattern()
En utilisant pattern()
, vous pouvez spécifier une expression régulière à laquelle la chaîne d'entrée
entière doit correspondre (c'est-à-dire comme si elle était entourée de caractères ^
a
$
) :
Assertions personnalisées : assert()
Vous pouvez ajouter toute autre restriction en utilisant assert(callable $fn)
.
Ou
Vous pouvez ajouter votre propre description pour chaque assertion. Elle fera partie du message d'erreur.
La méthode peut être appelée plusieurs fois pour ajouter plusieurs contraintes. Elle peut être combinée avec les appels à
transform()
et castTo()
.
Transformation : transform()
Les données validées avec succès peuvent être modifiées à l'aide d'une fonction personnalisée :
La méthode peut être appelée à plusieurs reprises pour ajouter des transformations multiples. Elle peut être combinée
avec des appels à assert()
et castTo()
. Les opérations seront exécutées dans l'ordre dans lequel
elles sont déclarées :
La méthode transform()
peut transformer et valider la valeur simultanément. C'est souvent plus simple et moins
redondant que d'enchaîner transform()
et assert()
. À cette fin, la fonction reçoit un objet Contexte avec une méthode addError()
, qui peut
être utilisée pour ajouter des informations sur les problèmes de validation :
Casting : castTo()
Les données validées avec succès peuvent être coulées :
En plus des types natifs de PHP, vous pouvez également utiliser des classes. Cela permet de distinguer s'il s'agit d'une classe simple sans constructeur ou d'une classe avec constructeur. Si la classe n'a pas de constructeur, une instance est créée et tous les éléments de la structure sont inscrits dans ses propriétés :
Si la classe a un constructeur, les éléments de la structure sont transmis au constructeur en tant que paramètres nommés :
La fonte combinée à un paramètre scalaire crée un objet et transmet la valeur comme seul paramètre au constructeur :
Normalisation : before()
Avant la validation proprement dite, les données peuvent être normalisées à l'aide de la méthode before()
. À
titre d'exemple, prenons un élément qui doit être un tableau de chaînes de caractères (ex. ['a', 'b', 'c']
),
mais qui reçoit des données sous la forme d'une chaîne de caractères a b c
:
Mapping to Objects : from()
Vous pouvez générer un schéma de structure à partir de la classe. Exemple :
Les classes anonymes sont également prises en charge :
Comme les informations obtenues à partir de la définition de la classe peuvent ne pas être suffisantes, vous pouvez ajouter un schéma personnalisé pour les éléments à l'aide du deuxième paramètre :