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_inputpara 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
filter_input(INPUT_POST, 'nome', FILTER_SANITIZE_SPECIAL_CHARS)obtém o nome já convertendo caracteres especiais em entidades HTML.trim()remove espaços no início e fim, evitando que um nome só com espaços passe na validação.- Para o e-mail,
FILTER_VALIDATE_EMAILretorna o e-mail válido oufalse/null. - A mensagem é sanitizada e depois verificada com
mb_strlen($mensagem) < 10para contar caracteres corretamente (inclusive acentos). - Cada erro é armazenado em
$erroscom a chave do campo, permitindo exibir mensagens individuais. - Se
$errosestiver vazio,$sucessoviratruee a mensagem final é exibida. - No HTML, os valores dos campos são preenchidos com
htmlspecialcharspara evitar XSS e manter o que foi digitado. - 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
strlenem vez demb_strlen:strlen('ação')retorna 5 (bytes), não 4 (caracteres). Usemb_strlenpara 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?