Every piece of data from $_POST or $_GET should be treated as hostile until proven otherwise. Proper validation and sanitization is the difference between a contact form and an open door.
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if ($email === false) {
$errors[] = "Invalid email address";
}
$name = trim(strip_tags($_POST['name'] ?? ''));
if (strlen($name) < 2 || strlen($name) > 100) {
$errors[] = "Name must be between 2 and 100 characters";
}
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT, [
'options' => ['min_range' => 0, 'max_range' => 120]
]);
Sanitize on Input, Escape on Output
Validate and sanitize when data comes in, but always escape it again with htmlspecialchars() when displaying it back in HTML — sanitizing once on input is not a substitute for escaping on output, since the two protect against different things.