PHPForm Validation

Form Validation

Reading a value out of $_POST only tells you that a field with that name was submitted — it says nothing about whether the value makes sense. Validation is the step where you decide whether "Aisha" is an acceptable name, whether "not-an-email" is a valid email address, and whether "twenty" is an acceptable age when you asked for a number.

Required-field checks

The simplest validation is confirming a field was actually filled in. Trimming whitespace first avoids treating a field of only spaces as "filled in."

Checking a required field

PHP
<?php
$errors = [];
$name = trim($_POST['name'] ?? '');

if ($name === '') {
    $errors['name'] = 'Name is required.';
}
Validating format with filter_var()

PHP's filter_var() function checks a value against a named filter and returns the validated value on success or false on failure. FILTER_VALIDATE_EMAIL and FILTER_VALIDATE_INT cover two of the most common cases: email addresses and whole numbers.

Validating an email and an age

PHP
<?php
$errors = [];

$email = trim($_POST['email'] ?? '');
if ($email === '' || filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
    $errors['email'] = 'Enter a valid email address.';
}

$age = $_POST['age'] ?? '';
$validatedAge = filter_var($age, FILTER_VALIDATE_INT, [
    'options' => ['min_range' => 0, 'max_range' => 120],
]);
if ($validatedAge === false) {
    $errors['age'] = 'Enter a whole number between 0 and 120.';
}
array(2) {
  ["email"]=> string(29) "Enter a valid email address."
  ["age"]=> string(35) "Enter a whole number between 0 and 120."
}
Collecting errors and re-displaying the form

Rather than stopping at the first invalid field, gather every problem into an $errors array keyed by field name, then only proceed if that array is still empty. Re-rendering the form with the previous values and the matching error messages gives visitors a chance to fix everything in one pass instead of one field at a time.

A validation pass that collects every error

PHP
<?php
$errors = [];
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');

if ($name === '') {
    $errors['name'] = 'Name is required.';
}
if ($email === '' || filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
    $errors['email'] = 'Enter a valid email address.';
}

if (empty($errors)) {
    // safe to save $name and $email
    echo 'Form saved successfully.';
}
?>
<?php if (!empty($errors['name'])): ?>
    <p class="error"><?= htmlspecialchars($errors['name'], ENT_QUOTES, 'UTF-8') ?></p>
<?php endif; ?>
<form method="post" action="">
  <input type="text" name="name" value="<?= htmlspecialchars($name, ENT_QUOTES, 'UTF-8') ?>">
  <input type="email" name="email" value="<?= htmlspecialchars($email, ENT_QUOTES, 'UTF-8') ?>">
  <button type="submit">Submit</button>
</form>
Why client-side validation is not enough
  • A visitor can disable JavaScript, use a very old browser, or submit the form with a tool like curl, bypassing any HTML required attribute or JS check entirely.

  • Client-side validation is only visible to a normal browser; the raw HTTP request can be crafted by hand to contain anything at all.

  • Server-side validation is the only check your application can actually trust, because it runs on infrastructure you control.

Client-side validation is a UX feature, not a security control
HTML5 attributes like `required`, `type="email"`, and JavaScript validation libraries genuinely improve the experience by giving instant feedback, but they run entirely on the visitor's machine. Treat them as a convenience layer on top of — never a substitute for — the server-side checks shown above.
Tip
Return validation errors as an associative array keyed by field name, the same shape used above. It makes it trivial to check `!empty($errors['email'])` next to the exact input that needs correcting, rather than showing one generic error message at the top of the form.