Desafio PHP

Formulário completo com validação e feedback

Enunciado

Crie um formulário de contato com campos nome, email e mensagem. Valide todos: nome não vazio, e-mail válido, mensagem com pelo menos 10 caracteres. Exiba erros específicos ou uma mensagem de sucesso com todos os dados escapados. Mantenha os valores digitados no formulário em caso de erro.

Requisitos

  • Usar filter_input para validar e-mail e sanitizar nome e mensagem.
  • Validar comprimento mínimo da mensagem (10 caracteres).
  • Exibir erros individuais por campo.
  • Preencher os campos com os valores anteriores escapados.
  • Exibir mensagem de sucesso com todos os dados escapados.

Código inicial

<?php
// Seu código aqui
?>
<!DOCTYPE html>
<html>
<body>
<form method="post">
    Nome: <input type="text" name="nome"><br>
    E-mail: <input type="text" name="email"><br>
    Mensagem: <textarea name="mensagem"></textarea><br>
    <button type="submit">Enviar</button>
</form>
</body>
</html>

Saída esperada

Sucesso! Nome: Ana, E-mail: ana@email.com, Mensagem: Olá, tudo bem?
Ver dica

Use mb_strlen() para contar caracteres da mensagem. Valide cada campo separadamente e acumule erros em um array associativo (campo => erro).

Mostrar solução
<?php
// Inicializa variáveis
$nome = $email = $mensagem = '';
$erros = [];
$sucesso = false;

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Obtém e sanitiza os dados
    $nome = trim(filter_input(INPUT_POST, 'nome', FILTER_SANITIZE_SPECIAL_CHARS) ?? '');
    $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
    $mensagem = trim(filter_input(INPUT_POST, 'mensagem', FILTER_SANITIZE_SPECIAL_CHARS) ?? '');

    // Valida nome
    if ($nome === '') {
        $erros['nome'] = 'O nome é obrigatório.';
    }

    // Valida e-mail
    if ($email === false || $email === null) {
        $erros['email'] = 'E-mail inválido.';
    }

    // Valida mensagem (mínimo 10 caracteres)
    if (mb_strlen($mensagem) < 10) {
        $erros['mensagem'] = 'A mensagem deve ter pelo menos 10 caracteres.';
    }

    // Se não houver erros, sucesso
    if (empty($erros)) {
        $sucesso = true;
    }
}
?>
<!DOCTYPE html>
<html>
<body>
    <h1>Contato</h1>

    <?php if ($sucesso): ?>
        <p>Sucesso! Nome: <?= htmlspecialchars($nome) ?>, E-mail: <?= htmlspecialchars($email) ?>, Mensagem: <?= htmlspecialchars($mensagem) ?></p>
    <?php endif; ?>

    <form method="post">
        Nome: <input type="text" name="nome" value="<?= htmlspecialchars($nome) ?>">
        <?php if (isset($erros['nome'])): ?><span style="color:red"><?= htmlspecialchars($erros['nome']) ?></span><?php endif; ?>
        <br>

        E-mail: <input type="text" name="email" value="<?= htmlspecialchars($email ?? '') ?>">
        <?php if (isset($erros['email'])): ?><span style="color:red"><?= htmlspecialchars($erros['email']) ?></span><?php endif; ?>
        <br>

        Mensagem: <textarea name="mensagem"><?= htmlspecialchars($mensagem) ?></textarea>
        <?php if (isset($erros['mensagem'])): ?><span style="color:red"><?= htmlspecialchars($erros['mensagem']) ?></span><?php endif; ?>
        <br>

        <button type="submit">Enviar</button>
    </form>
</body>
</html>

Passo a passo

  1. filter_input(INPUT_POST, 'nome', FILTER_SANITIZE_SPECIAL_CHARS) obtém o nome já convertendo caracteres especiais em entidades HTML.
  2. trim() remove espaços no início e fim, evitando que um nome só com espaços passe na validação.
  3. Para o e-mail, FILTER_VALIDATE_EMAIL retorna o e-mail válido ou false/null.
  4. A mensagem é sanitizada e depois verificada com mb_strlen($mensagem) < 10 para contar caracteres corretamente (inclusive acentos).
  5. Cada erro é armazenado em $erros com a chave do campo, permitindo exibir mensagens individuais.
  6. Se $erros estiver vazio, $sucesso vira true e a mensagem final é exibida.
  7. No HTML, os valores dos campos são preenchidos com htmlspecialchars para evitar XSS e manter o que foi digitado.
  8. As mensagens de erro são exibidas ao lado de cada campo, também escapadas.

Por que funciona

A combinação de filter_input com validações específicas garante que os dados estejam no formato esperado antes de qualquer uso. O escape na saída (htmlspecialchars) protege contra XSS mesmo que a sanitização falhe. A estrutura de erros por campo melhora a usabilidade.

Erros comuns

  • Usar strlen em vez de mb_strlen: strlen('ação') retorna 5 (bytes), não 4 (caracteres). Use mb_strlen para strings multibyte.
  • Não preencher os campos após erro: o usuário perde tudo que digitou. Sempre repopule com os valores anteriores escapados.
  • Validar mensagem antes de sanitizar: se sanitizar primeiro, tags HTML podem ser convertidas e aumentar o comprimento. Valide o valor bruto ou sanitizado consistentemente.
  • Exibir erros sem escape: mensagens de erro também podem conter dados do usuário se forem dinâmicas. Escape sempre.

Outra forma de resolver

Usar um array de validações para evitar repetição:

$validacoes = [
    'nome' => fn($v) => $v !== '' ? null : 'O nome é obrigatório.',
    'email' => fn($v) => filter_var($v, FILTER_VALIDATE_EMAIL) ? null : 'E-mail inválido.',
    'mensagem' => fn($v) => mb_strlen($v) >= 10 ? null : 'Mínimo 10 caracteres.',
];
foreach ($validacoes as $campo => $regra) {
    $valor = $_POST[$campo] ?? '';
    if ($erro = $regra($valor)) {
        $erros[$campo] = $erro;
    }
}

Útil quando há muitos campos e regras repetitivas.

Saída esperada

Sucesso! Nome: Ana, E-mail: ana@email.com, Mensagem: Olá, tudo bem?