Schema: Validação de dados
Uma biblioteca prática para validação e normalização de estruturas de dados contra um determinado esquema com uma API inteligente e fácil de entender.
Instalação:
Utilização básica
Na variável $schema
temos um esquema de validação (o que exatamente isto significa e como criá-lo diremos
mais tarde) e na variável $data
temos uma estrutura de dados que queremos validar e normalizar. Estes podem ser, por
exemplo, dados enviados pelo usuário através de uma API, arquivo de configuração, etc.
A tarefa é tratada pela classe Nette\Schema\Processor, que processa a entrada e ou retorna dados normalizados ou lança uma exceção Nette\Schema\ValidationException sobre erro.
O método $e->getMessages()
retorna a matriz de todas as cadeias de mensagens e
$e->getMessageObjects()
retorna todas as mensagens como objetos „Nette\Schema\Message:https://api.nette.org/…Message.html “.
Definindo o esquema
E agora vamos criar um esquema. A classe Nette\Schema\Expect é usada para defini-lo, na verdade
definimos expectativas de como os dados devem ser. Digamos que os dados de entrada devem ser uma estrutura (por exemplo, uma
matriz) contendo elementos processRefund
do tipo bool e refundAmount
do tipo int.
Acreditamos que a definição do esquema parece clara, mesmo que você a veja pela primeira vez.
Vamos enviar os seguintes dados para validação:
A saída, ou seja, o valor $normalized
, é o objeto stdClass
. Se quisermos que a saída seja uma
matriz, adicionamos um elenco ao esquema Expect::structure([...])->castTo('array')
.
Todos os elementos da estrutura são opcionais e têm um valor padrão null
. Exemplo:
O fato de o valor padrão ser null
não significa que ele seria aceito nos dados de entrada
'processRefund' => null
. Não, a entrada deve ser booleana, ou seja, apenas true
ou
false
. Teríamos que permitir explicitamente null
via Expect::bool()->nullable()
.
Um item pode ser tornado obrigatório usando Expect::bool()->required()
. Mudamos o valor padrão para
false
usando Expect::bool()->default(false)
ou em breve usando Expect::bool(false)
.
E se quiséssemos aceitar 1
and 0
além de booleanos? Então listamos os valores permitidos, que
também normalizaremos para booleanos:
Agora você conhece as bases de como o esquema é definido e como os elementos individuais da estrutura se comportam. Agora vamos mostrar o que todos os outros elementos podem ser usados na definição de um esquema.
Tipos de dados: tipo()
Todos os tipos de dados padrão PHP podem ser listados no esquema:
E depois todos os tipos suportados pelos validadores via
Expect::type('scalar')
ou abreviado Expect::scalar()
. Também são aceitos nomes de classes ou
interfaces, por exemplo Expect::type('AddressEntity')
.
Você também pode usar a notação sindical:
O valor padrão é sempre null
exceto para array
e list
, onde é uma matriz vazia. (Uma
lista é um array indexado em ordem ascendente de chaves numéricas a partir de zero, ou seja, um array não-associativo).
Conjunto de valores: arrayOf() listOf()
A matriz é estrutura muito geral, é mais útil especificar exatamente quais elementos ela pode conter. Por exemplo, uma matriz cujos elementos só podem ser cordas:
O segundo parâmetro pode ser usado para especificar chaves (desde a versão 1.2):
A lista é uma matriz indexada:
O parâmetro também pode ser um esquema, para que possamos escrever:
O valor padrão é uma matriz vazia. Se você especificar o valor padrão, ele será fundido com os dados passados. Isto pode
ser desabilitado usando mergeDefaults(false)
(desde a versão 1.1).
Enumeração: anyOf()
anyOf()
é um conjunto de valores ou esquemas que um valor pode ser. Eis como escrever um conjunto de elementos
que podem ser 'a'
, true
, ou null
:
Os elementos de enumeração também podem ser esquemas:
O método anyOf()
aceita variantes como parâmetros individuais, não como array. Para passar-lhe uma matriz de
valores, use o operador de desembalagem anyOf(...$variants)
.
O valor padrão é null
. Use o método firstIsDefault()
para tornar o primeiro elemento
o padrão:
Estruturas
As estruturas são objetos com chaves definidas. Cada uma destas chaves ⇒ pares de valores é chamada de „propriedade“:
As estruturas aceitam matrizes e objetos e retornam objetos stdClass
.
Por padrão, todas as propriedades são opcionais e têm um valor padrão de null
. Você pode definir propriedades
obrigatórias usando required()
:
Se você não quiser emitir propriedades com apenas um valor padrão, use skipDefaults()
:
Embora null
seja o valor padrão da propriedade optional
, ele não é permitido nos dados de entrada
(o valor deve ser uma string). As propriedades que aceitam null
são definidas usando nullable()
:
A matriz de todas as propriedades da estrutura é retornada pelo método getShape()
.
Por padrão, não pode haver itens extras nos dados de entrada:
Que podemos mudar com otherItems()
. Como parâmetro, especificaremos o esquema para cada elemento extra:
Você pode criar uma nova estrutura derivando de outra usando extend()
:
Matriz
Uma matriz com chaves definidas. Aplicam-se as mesmas regras das estruturas.
Você também pode definir uma matriz indexada, conhecida como tupla:
Depreciações
Você pode depreciar os bens usando o deprecated([string $message])
método. Os avisos de depreciação são
devolvidos por $processor->getWarnings()
:
Faixas: min() max()
Use min()
e max()
para limitar o número de elementos para arrays:
Para as cordas, limite seu comprimento:
Para os números, limite seu valor:
Naturalmente, é possível mencionar apenas min()
, ou apenas max()
:
Expressões regulares: padrão()
Usando pattern()
, você pode especificar uma expressão regular que a string de entrada whole deve combinar
(ou seja, como se estivesse embrulhada em caracteres ^
a $
):
Asserções personalizadas: assert()
Você pode adicionar quaisquer outras restrições usando assert(callable $fn)
.
Ou
Você pode acrescentar sua própria descrição para cada asserção. Ela será parte da mensagem de erro.
O método pode ser chamado repetidamente para adicionar várias restrições. Ele pode ser misturado com chamadas para
transform()
e castTo()
.
Transformação: transform()
Os dados validados com sucesso podem ser modificados usando uma função personalizada:
O método pode ser chamado repetidamente para adicionar várias transformações. Ele pode ser misturado com chamadas para
assert()
e castTo()
. As operações serão executadas na ordem em que forem declaradas:
O método transform()
pode transformar e validar o valor simultaneamente. Isso geralmente é mais simples e
menos redundante do que encadear transform()
e assert()
. Para esse fim, a função recebe um objeto Context com um método addError()
, que pode ser
usado para adicionar informações sobre problemas de validação:
Transmissão: castTo()
Os dados validados com sucesso podem ser convertidos:
Além dos tipos nativos do PHP, você também pode converter para classes. Ele distingue se é uma classe simples sem um construtor ou uma classe com um construtor. Se a classe não tiver um construtor, será criada uma instância dela e todos os elementos da estrutura serão gravados em suas propriedades:
Se a classe tiver um construtor, os elementos da estrutura serão passados como parâmetros nomeados para o construtor:
A conversão combinada com um parâmetro escalar cria um objeto e passa o valor como o único parâmetro para o construtor:
Normalização: before()
Antes da validação propriamente dita, os dados podem ser normalizados usando o método before()
. Como exemplo,
vamos ter um elemento que deve ser um conjunto de cordas (por exemplo ['a', 'b', 'c']
), mas recebe entrada sob a
forma de um cordel a b c
:
Mapeamento para objetos: from()
Você pode gerar um esquema de estrutura a partir da classe. Exemplo:
Também há suporte para classes anônimas:
Como as informações obtidas da definição da classe podem não ser suficientes, você pode adicionar um esquema personalizado para os elementos com o segundo parâmetro: