Docs›Services›MadValidationException
Services

MadValidationException

Validação Illuminate pura com asInline, asModal, asToast, asDetailForm.

Mad\Form\MadValidationException é lançada por $this->form->validate($rules) quando algum campo falha — as regras são Illuminate puro (required|string|max:255, etc.), processadas via Mad\Form\MadValidator sobre o Illuminate\Validation\Factory nativo. Não existe um DSL de validação próprio do MAD — se você já validou algo num FormRequest do Laravel, as regras são exatamente as mesmas.

API atual é menor que a de versões anteriores da documentação

Esta classe expõe hoje cinco métodos: getErrors(), asInline(), asModal(), asToast() e asDetailForm(). Não existem (mais) asResponse(), first(), has(), get() nem firstField() — se você viu esses métodos em material antigo, foram descontinuados/renomeados nesta versão.

Regras — Illuminate puro

A chave da regra aceita o formato 'campo|Label' — o label depois do | é extraído automaticamente e usado nas mensagens de erro (tem prioridade o parâmetro $attrs explícito, se informado):

// Regras Illuminate puras — exatamente as mesmas usadas em FormRequest/Validator
// do Laravel. Sem DSL de validação próprio do MAD.
$this->form->validate([
    'nome|Nome'  => 'required|string|max:255',  // 'campo|Label' extrai o label
    'cpf'        => 'required|cpf',             // regra custom registrada no projeto
    'idade'      => 'nullable|integer|min:18',
    'documentos' => 'required|array|min:1',
]);

Assinatura completa: $form->validate(array $rules, array $messages = [], array $attrs = []): static — retorna o próprio form (encadeável) quando tudo passa, e lança MadValidationException($errors, array_keys($rules)) quando não. Se $attrs vier vazio, o MAD cai nos auto-labels: os rótulos que o MadWire coletou do HTML e enviou em mad_labels — ou seja, na maioria dos casos a mensagem já sai com o label visível do campo sem você declarar nada.

Padrão típico — try/catch no onSave

use Mad\Form\MadValidationException;
use Mad\Http\MadResponse;

public function onSave(): MadResponse
{
    try {
        $this->form->validate([
            'nome|Nome'   => 'required|string|max:255',
            'email|Email' => 'required|email',
            'valor'       => 'required|numeric|min:0',
        ]);

        $data    = $this->form->getData();
        $produto = Produto::findOrNew($this->registroId);
        $produto->fill($data->toArray());
        $produto->save();

        return MadToast::success('Salvo!')->closeDrawer();

    } catch (MadValidationException $e) {
        return $e->asInline();   // erros inline nos campos (padrão recomendado)

    } catch (\Throwable $e) {
        return MadMessage::error('Erro ao salvar', $e->getMessage());
    }
}

API

MétodoRetornoDescrição
getErrors()arrayMapa ['campo' => 'mensagem'] de todos os erros.
asInline($toast = 'Corrija os erros antes de continuar.')MadResponseMarca cada campo com erro inline + toast de aviso ($toast = '' omite o toast). Padrão recomendado.
asModal($title = 'Erros encontrados')MadResponseLista todos os erros num dialog (MadResponse->alert(), tipo error).
asToast($prefix = '')MadResponseSó o primeiro erro, como toast de aviso — prefixo opcional.
asDetailForm($dfName = '')MadResponseErros escopados a um detail-form (dfFieldError()) — evita colidir com campo de mesmo nome no form master. Sem $dfName, usa o nome passado no 3º argumento do construtor.

Apresentações disponíveis

catch (MadValidationException $e) {
    return $e->asInline();   // marca cada campo + toast de aviso (padrão)
}

catch (MadValidationException $e) {
    return $e->asModal('Dados inválidos'); // lista de erros num dialog
}

catch (MadValidationException $e) {
    return $e->asToast();    // só o primeiro erro, como toast de aviso
}

catch (MadValidationException $e) {
    return $e->asDetailForm(); // erros escopados a um detail-form (sem colidir
                                // com campo de mesmo nome no formulário master)
}

O que asInline() faz, em detalhe

// asInline() faz três coisas:
//   1. clearFieldError() em TODOS os campos que passaram pela validação
//      (limpa erros de uma tentativa anterior, mesmo nos que agora passaram)
//   2. fieldError($campo, $msg) em cada campo que falhou desta vez
//   3. toast de aviso (texto customizável; '' para omitir)
return (new MadValidationException($errors, $camposValidados))->asInline('Verifique os campos destacados.');

O primeiro parâmetro do construtor é $errors; o segundo, $validatedFields, é a lista de TODOS os campos que passaram pela validação (usada por asInline() para limpar erros de campos que falharam numa tentativa anterior mas passaram nesta) — $this->form->validate() já popula isso sozinho a partir das chaves das rules.

Lançar manualmente — validação cross-field

Para regras de negócio que envolvem múltiplos campos (não cabem numa rule isolada do Illuminate), valide o básico via $this->form->validate() e lance a exceção manualmente para o restante:

use Mad\Form\MadValidationException;

public function onSave(): MadResponse
{
    try {
        $this->form->validate(Pedido::rules($this->registroId));
        $data = $this->form->getData();

        // Validação cross-field — não cabe numa rule isolada do Laravel
        $errors = [];

        if ($data->valor_promo > 0 && $data->valor_promo >= $data->valor) {
            $errors['valor_promo'] = 'Valor promocional deve ser menor que o valor.';
        }
        if ($data->dt_fim < $data->dt_ini) {
            $errors['dt_fim'] = 'Data fim deve ser posterior à data início.';
        }

        if ($errors) {
            throw new MadValidationException($errors);
        }

        // ... persistir ...
        return MadToast::success('Salvo!');

    } catch (MadValidationException $e) {
        return $e->asInline();
    }
}

Próximos passos