← Laravel: pedidos, dados e decisões de aplicação
04 / 10 · 65 MIN

Validação e contratos dos pedidos

Definir presença, nulidade, tipos e chaves aceites; consumir o resultado validado sem reintroduzir input bruto. Separar autorização, validação e transformação no ciclo da FormRequest.

Escolher chaves não valida valores

request->only seleciona nomes presentes no input. Não sabe que quantity deve ser inteiro positivo nem que um email tem de ter formato válido. Uma FormRequest ou um validador aplica regras; validated devolve o resultado e safe permite selecionar um subconjunto desse conjunto validado.

No exemplo, o serviço recebe o payload preparado e não volta a consultar all. Não transformes esta disciplina numa alegação de autorização: validar dados não decide quem pode alterar o recurso.

Ausente, vazio e nulo

No PATCH do cenário, a ausência de email significa não alterar esse dado. Se email for enviado, a equipa exige um valor não vazio e válido: sometimes|required|email exprime essa distinção. nullable exprime outra decisão, a aceitação de null.

Com os middleware padrão de normalização, uma string vazia pode tornar-se null antes das regras. Para publish_at opcional, nullable|date permite esse estado e continua a rejeitar valores não nulos que não sejam datas válidas.

O momento da transformação

prepareForValidation permite preparar a entrada antes das regras. Usa-o para uma normalização que o contrato aceite, como tornar canónica uma representação de código; não para aceitar silenciosamente qualquer valor defeituoso. passedValidation ocorre depois das regras, pelo que transformar aí o input não demonstra que o valor transformado tenha sido validado.

Identifica qual representação as regras observaram e qual chega ao serviço, sobretudo se outro código altera o pedido depois da validação.

Arrays precisam de um limite de chaves

A regra array isolada valida o tipo exterior e pode deixar seguir chaves internas sem regras próprias no resultado validated. No exemplo, array:display_name,email recusa propriedades adicionais; as regras dos campos definem ainda presença, tipo e conteúdo.

Esta combinação evita que profile.is_admin seja tratado como um campo normal só porque o nome passou. A camada de persistência deve continuar a aplicar os seus próprios limites; a lista de chaves não substitui políticas de acesso ou autorização.

Excluir é também escolher o resultado

exclude_if remove o campo do resultado retornado por validate ou validated quando a condição corresponde. Se tax_id é excluído para type=personal, copiar depois o campo de all para o serviço desfaz esse limite. Não assumas que uma regra de validação reescreveu todo o pedido bruto.

Em regras unique de atualização, a identidade ignorada deve vir do modelo conhecido e autorizado pelo servidor. Um campo oculto ignore_id continua a ser controlável pelo cliente e não é uma origem fiável.

Falhas locais e interrupção global

bail interrompe as regras seguintes do campo que falhou. Não transforma a falha num aviso nem obriga a interromper todos os outros campos. stopOnFirstFailure no validador tem um âmbito global; a versão 13 também documenta uma opção equivalente por atributo da FormRequest.

Nos exercícios, a ausência explícita desse controlo global permite prever que outros campos ainda podem ser validados. Escolhe a política de erros com intenção: menos regras executadas não significa dados aceites.

Autorizar, validar e responder

Quando authorize de uma FormRequest devolve false, o tratamento normal devolve 403 e não executa a ação do controller. Já uma ValidationException num pedido que espera JSON devolve 422 com mensagens e erros; chaves aninhadas aparecem em notação com pontos.

Não troques uma recusa de acesso por uma correção de formato, nem interpretes todas as respostas 4xx como o mesmo problema. O cliente deve preservar os dados de edição apropriados e apresentar os erros correspondentes ao contrato realmente violado.

<?php
// Rules excerpt from a profile FormRequest; authorization is separate.
public function rules(): array
{
    return [
        'profile' => ['required', 'array:display_name,email'],
        'profile.display_name' => ['required', 'string', 'max:80'],
        'profile.email' => ['sometimes', 'required', 'email'],
        'publish_at' => ['nullable', 'date'],
    ];
}

// Consumer excerpt after successful FormRequest validation.
$payload = $request->safe()->only(['profile', 'publish_at']);
NA PRÁTICA

A ação aceita profile apenas com display_name e email. Uma chave profile.is_admin provoca falha pela lista de chaves permitidas, mesmo que o nome seja válido. Email pode estar ausente, mas não vazio quando enviado. publish_at pode ser nulo ou uma data válida.

O excerto não implementa authorize, persistência nem uma política completa de perfil; essas decisões continuam separadas.

Armadilhas comuns

Tratar only como validador; confundir nullable com sometimes; supor que array valida cada chave; passar input do cliente a unique ignore; interpretar bail como interrupção global; considerar que formato válido concede autorização.

Tópicos relacionados: Rotas, binding e middleware · Eloquent, relações e custo das consultas · Autenticação, autorização e sessões

Leva esta ideia contigo

O contrato inclui presença, valores, chaves e identidade da operação. Aplica as regras à representação correta, limita o resultado entregue ao serviço e mantém autorização separada. Explica a falha observada a partir da fase onde ocorreu.

Criar conta

Referência: Validated input selection · Laravel 13.x; PHP 8.3+