Validação de formulários em PHP
Na última aula, você aprendeu a receber dados de formulários. Esta aula aborda a etapa mais crítica: a validação. Nunca confie nas entradas do usuário. Os usuários cometem erros de digitação. Os usuários podem ter más intenções. Os usuários deixam campos em branco. A validação de formulários é sua primeira linha de defesa.
1. A arquitetura de validação
Toda a validação ocorre no lado do servidor (PHP). A validação no lado do cliente (HTML5 / JavaScript) é apenas uma camada de conveniência opcional:
Browser (JS validation, easily bypassed)
↓
PHP server (MUST validate — never skip this step)
↓
Store in database
<?php
$errors = [];
// 1. Collect and clean input
$name = trim($_POST['name'] ?? '');
$age = $_POST['age'] ?? '';
$email = trim($_POST['email'] ?? '');
// 2. Apply validation rules
if ($name === '') {
$errors['name'] = 'Name is required';
} elseif (strlen($name) > 50) {
$errors['name'] = 'Name must not exceed 50 characters';
}
if ($age === '') {
$errors['age'] = 'Age is required';
} elseif (!is_numeric($age)) {
$errors['age'] = 'Age must be a number';
} elseif ((int)$age < 1 || (int)$age > 150) {
$errors['age'] = 'Age must be between 1 and 150';
}
if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors['email'] = 'Invalid email format';
} // Email is optional, but if provided it must be valid
// 3. Determine the outcome
if (empty($errors)) {
echo "Validation passed!";
} else {
foreach ($errors as $field => $msg) {
echo "<p style='color:red'>{$msg}</p>";
}
}
?>
$errors para coletar mensagens de erro. A estrutura $errors['field_name'] facilita a exibição dos erros ao lado dos campos correspondentes.
2. Validação com filter_var()
A função embutida filter_var() do PHP é a maneira mais simples de validar tipos de dados comuns:
<?php
// Email validation
$email = "test@example.com";
var_dump(filter_var($email, FILTER_VALIDATE_EMAIL));
// "test@example.com" (returns the original value on success)
$badEmail = "not-an-email";
var_dump(filter_var($badEmail, FILTER_VALIDATE_EMAIL));
// bool(false) (validation failed)
// URL validation
$url = "https://www.example.com";
var_dump(filter_var($url, FILTER_VALIDATE_URL));
// IP address validation
$ip = "192.168.1.1";
var_dump(filter_var($ip, FILTER_VALIDATE_IP));
// Integer range validation
$age = 25;
var_dump(filter_var($age, FILTER_VALIDATE_INT, [
"options" => ["min_range" => 1, "max_range" => 150]
]));
?>
▶ Exemplo: Validando um formulário inteiro com filter_var
<?php
$errors = [];
// Validate email
$email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL);
if ($email === false) {
$errors['email'] = 'Please enter a valid email address';
}
// Validate URL
$website = filter_var($_POST['website'] ?? '', FILTER_VALIDATE_URL);
if ($website === false && ($_POST['website'] ?? '') !== '') {
$errors['website'] = 'Please enter a valid URL';
}
// Validate integer range
$age = filter_var($_POST['age'] ?? '', FILTER_VALIDATE_INT, [
"options" => ["min_range" => 1, "max_range" => 120]
]);
if ($age === false) {
$errors['age'] = 'Age must be between 1 and 120';
}
?>
3. Validação de expressões regulares com preg_match()
Quando os validadores integrados não são suficientes, entram em cena as expressões regulares:
<?php
// Phone number (10-digit North American)
$phone = "5551234567";
if (preg_match('/^\d{10}$/', $phone)) {
echo "Phone number format is valid";
}
// Username (alphanumeric + underscore, 3-20 characters)
$username = "user_2024";
if (preg_match('/^[a-zA-Z0-9_]{3,20}$/', $username)) {
echo "Username format is valid";
}
// Strong password (min 8 chars, at least one lowercase, one uppercase, one digit)
$password = "MyPass123";
if (preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/', $password)) {
echo "Password meets strength requirements";
}
?>
4. Fortalecimento da segurança
(1) htmlspecialchars() — Prevenção de ataques XSS
Se uma entrada do usuário que contenha as tags <script> for exibida diretamente, o navegador irá executá-la:
<?php
$userInput = '<script>alert("Hacked!")</script>';
// ❌ Dangerous — direct output
echo $userInput; // The script executes!
// ✅ Safe — escape special characters
echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
// Renders as: <script>alert("Hacked!")</script>
// The browser displays the text rather than executing it
?>
(2) strip_tags() — Remoção de tags HTML
<?php
$content = "<p>This is <b>important</b> content</p>";
echo strip_tags($content); // This is important content
// Optionally allow specific tags (whitelist as second argument)
echo strip_tags($content, '<b><i>'); // This is <b>important</b> content
?>
(3) trim() — Remoção de espaços em branco no início e no final
<?php
$input = " John ";
echo trim($input); // John
?>
▶ Exemplo: Uma função completa de sanitização de entradas
<?php
/**
* Clean user-supplied text input
*/
function cleanInput(string $data): string {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
return $data;
}
$name = cleanInput($_POST['name'] ?? '');
$comment = cleanInput($_POST['comment'] ?? '');
?>
5. Juntando tudo
▶ Exemplo: Formulário de inscrição completo com validação
<?php
$errors = [];
$username = $email = $password = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = trim($_POST['username'] ?? '');
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
// Username validation
if ($username === '') {
$errors['username'] = 'Username is required';
} elseif (strlen($username) < 3 || strlen($username) > 20) {
$errors['username'] = 'Username must be 3–20 characters';
} elseif (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) {
$errors['username'] = 'Username may only contain letters, digits, and underscores';
}
// Email validation
$emailClean = filter_var($email, FILTER_VALIDATE_EMAIL);
if ($email === '') {
$errors['email'] = 'Email is required';
} elseif ($emailClean === false) {
$errors['email'] = 'Invalid email format';
}
// Password validation
if ($password === '') {
$errors['password'] = 'Password is required';
} elseif (strlen($password) < 6) {
$errors['password'] = 'Password must be at least 6 characters';
}
if (empty($errors)) {
$usernameSafe = htmlspecialchars($username, ENT_QUOTES, 'UTF-8');
echo "<h3 style='color:green'>Registration successful! Welcome, {$usernameSafe}!</h3>";
$username = $email = $password = '';
}
}
?>
<form method="POST" action="">
<div>
<label>Username:</label>
<input type="text" name="username"
value="<?= htmlspecialchars($username) ?>">
<span style="color:red"><?= $errors['username'] ?? '' ?></span>
</div>
<div>
<label>Email:</label>
<input type="email" name="email"
value="<?= htmlspecialchars($email) ?>">
<span style="color:red"><?= $errors['email'] ?? '' ?></span>
</div>
<div>
<label>Password:</label>
<input type="password" name="password">
<span style="color:red"><?= $errors['password'] ?? '' ?></span>
</div>
<button type="submit">Register</button>
</form>
❓ Perguntas Frequentes
P: Eu já tenho os atributos
requiredepatternno front-end. Ainda preciso da validação em PHP? R: Com certeza. A validação no front-end é facilmente contornada — basta desativar o JavaScript ou simular uma solicitação com o curl. A validação no PHP é a última linha de defesa e não pode ser ignorada.
P: Quando devo usar
htmlspecialcharse quandostrip_tags? R: Usehtmlspecialcharsquando quiser exibir a entrada do usuário tal como está, mas com segurança (ele faz o escape do HTML sem removê-lo). Usestrip_tagsquando quiser remover completamente todo o HTML. Na maioria dos casos,htmlspecialcharsé suficiente.
P: As expressões regulares parecem intimidadoras. Preciso memorizá-las? R: Não. Padrões comuns (e-mail, telefone, URL) têm fórmulas bem conhecidas. Basta lembrar-se de
preg_match()e de alguns símbolos básicos —^(início),$(fim),\d(dígito),[](conjunto de caracteres),{}(quantidade) — e você vai se virar bem.
📖 Resumo
- Sequência de validação: verificação obrigatória → verificação de tipo → verificação de intervalo → verificação de formato
filter_var($val, FILTER_VALIDATE_EMAIL/URL/INT)é o atalho de validação mais simplespreg_match('/pattern/', $val)lida com requisitos complexos de formataçãohtmlspecialchars()previne XSS — faça a codificação de escape antes de gerar o HTMLstrip_tags()remove todo o HTML;trim()remove os espaços em branco ao redor- A validação no front-end visa melhorar a experiência do usuário; a validação em PHP visa garantir a segurança
📝 Exercícios
- Crie um formulário de edição de perfil com apelido, idade, e-mail e URL do site pessoal. Valide cada campo com a regra apropriada.
- Crie um formulário para alteração de senha: solicite a senha atual, exija que a nova senha tenha pelo menos 8 caracteres, com uma combinação de letras e números, e confirme se as duas senhas coincidem.
- Teste uma vulnerabilidade XSS: crie um formulário de livro de visitas que omita deliberadamente
htmlspecialchars. Tente postar<script>alert(1)</script>e observe o que acontece. Em seguida, adicionehtmlspecialcharse teste novamente.



