PHP Form Validation

sa sahaya jerish Updated 17 Oct 2026
7 min read ·Lesson 91 of 109
In this post

What Is Form Validation? In simple terms: Validation checks whether submitted data is acceptable before your application uses it — for example, that an email address looks like an email address, an ag

What Is Form Validation?

In simple terms: Validation checks whether submitted data is acceptable before your application uses it — for example, that an email address looks like an email address, an age is a whole number in a sensible range, and a password is long enough.

Technically: Validation applies rules to each input value and either accepts it (often converting it to the right type) or rejects it with an error message. In PHP, validation is built from comparisons, string functions, regular expressions, and the filter extension (filter_var() and related functions).

Why Server-Side Validation Is Mandatory

HTML attributes such as required, type="email", min, and maxlength improve the user experience, but they run in the browser, which the user controls. Anyone can remove them in developer tools or send requests directly with tools such as curl. Only validation on the server protects your data:

Client-Side (HTML/JavaScript)Server-Side (PHP)
Instant feedback while typingRuns after submission
Can be bypassedCannot be bypassed
Optional, for convenienceRequired, for correctness and security

Kinds of Validation Rules

Rule TypeExampleTypical Tool
PresenceName must not be emptytrim($value) !== '' (see PHP Form Required)
TypeAge must be an integerfilter_var(..., FILTER_VALIDATE_INT)
FormatEmail, URL, PIN codeFILTER_VALIDATE_EMAIL, preg_match()
LengthPassword at least 8 charactersmb_strlen()
RangeRating from 1 to 5Filter options min_range/max_range
Allowed valuesPlan is free or proin_array(..., true)
ConsistencyPassword confirmation matches=== comparison
UniquenessEmail not already registeredDatabase query

The Filter Extension: filter_var()

Syntax

filter_var(mixed $value, int $filter = FILTER_DEFAULT, array|int $options = 0): mixed

Validation filters return the converted value on success and false on failure.

Validating Integers

<?php
var_dump(filter_var('42', FILTER_VALIDATE_INT));
var_dump(filter_var(' 42 ', FILTER_VALIDATE_INT));
var_dump(filter_var('42abc', FILTER_VALIDATE_INT));
var_dump(filter_var('4.2', FILTER_VALIDATE_INT));
var_dump(filter_var('150', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 120]]));

Output

int(42)
int(42)
bool(false)
bool(false)
bool(false)
  • A valid value is returned as a real int, ready to use.
  • Leading and trailing whitespace is ignored.
  • Partial numbers (42abc) and decimals are rejected — unlike (int), which would silently convert '42abc' to 42.
  • min_range and max_range enforce a range in the same step.

Watch out for 0: A valid input of '0' returns int(0), which is falsy. Always compare with === false, never with if (!$result).

Validating Floats and Booleans

<?php
var_dump(filter_var('3.14', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('3,14', FILTER_VALIDATE_FLOAT, ['options' => ['decimal' => ',']]));

var_dump(filter_var('yes', FILTER_VALIDATE_BOOL));
var_dump(filter_var('off', FILTER_VALIDATE_BOOL));
var_dump(filter_var('maybe', FILTER_VALIDATE_BOOL, FILTER_NULL_ON_FAILURE));

Output

float(3.14)
float(3.14)
bool(true)
bool(false)
NULL
  • The decimal option accepts a comma as the decimal separator.
  • FILTER_VALIDATE_BOOL (an alias of FILTER_VALIDATE_BOOLEAN, PHP 8.0+) accepts 1, true, on, yes as true and 0, false, off, no, '' as false.
  • Because false is both a valid result and the failure value, add FILTER_NULL_ON_FAILURE to get null for invalid input such as 'maybe'.

Other Validation Filters

FilterValidates
FILTER_VALIDATE_EMAILEmail addresses (see PHP Form URL/E-mail)
FILTER_VALIDATE_URLURLs
FILTER_VALIDATE_IPIPv4/IPv6 addresses (flags for private/reserved ranges)
FILTER_VALIDATE_DOMAINDomain names (with FILTER_FLAG_HOSTNAME)
FILTER_VALIDATE_MACMAC addresses
FILTER_VALIDATE_REGEXPA custom regular expression ('options' => ['regexp' => '/.../'])

Validating Many Fields at Once: filter_var_array()

<?php
$input = ['age' => '25', 'email' => 'asha@example', 'newsletter' => 'yes', 'rating' => '7'];

$definition = [
    'age' => ['filter' => FILTER_VALIDATE_INT, 'options' => ['min_range' => 13, 'max_range' => 120]],
    'email' => FILTER_VALIDATE_EMAIL,
    'newsletter' => ['filter' => FILTER_VALIDATE_BOOL, 'flags' => FILTER_NULL_ON_FAILURE],
    'rating' => ['filter' => FILTER_VALIDATE_INT, 'options' => ['min_range' => 1, 'max_range' => 5]],
];

var_dump(filter_var_array($input, $definition));

Output

array(4) {
  ["age"]=>
  int(25)
  ["email"]=>
  bool(false)
  ["newsletter"]=>
  bool(true)
  ["rating"]=>
  bool(false)
}

Each field gets its own filter and options. Fields listed in the definition but missing from the input are returned as null, which lets you distinguish "missing" (null) from "invalid" (false). filter_input_array(INPUT_POST, $definition) does the same directly on the request data.


Building a Reusable Validator

Real forms combine several rules per field and need readable error messages. A small rule-based validator keeps form code short and consistent:

<?php
function validate(array $input, array $rules): array
{
    $errors = [];

    foreach ($rules as $field => $fieldRules) {
        $raw = $input[$field] ?? '';
        $value = is_string($raw) ? trim($raw) : '';
        $label = str_replace('_', ' ', $field);

        foreach ($fieldRules as $rule) {
            [$name, $a, $b] = array_pad(explode(':', $rule), 3, null);

            $error = match ($name) {
                'required' => $value === '' ? "The $label field is required." : null,
                'email' => $value !== '' && filter_var($value, FILTER_VALIDATE_EMAIL) === false
                    ? "The $label must be a valid email address." : null,
                'min' => $value !== '' && mb_strlen($value) < (int) $a
                    ? "The $label must be at least $a characters." : null,
                'max' => mb_strlen($value) > (int) $a
                    ? "The $label may not be longer than $a characters." : null,
                'int' => $value !== '' && filter_var($value, FILTER_VALIDATE_INT, [
                        'options' => ['min_range' => (int) $a, 'max_range' => (int) $b],
                    ]) === false
                    ? "The $label must be a whole number between $a and $b." : null,
                'same' => $value !== (is_string($input[$a] ?? null) ? trim($input[$a]) : '')
                    ? "The $label must match the $a." : null,
                default => throw new InvalidArgumentException("Unknown rule: $name"),
            };

            if ($error !== null) {
                $errors[$field] = $error;
                break;
            }
        }
    }

    return $errors;
}

$rules = [
    'name' => ['required', 'max:50'],
    'email' => ['required', 'email'],
    'age' => ['required', 'int:18:100'],
    'password' => ['required', 'min:8'],
    'password_confirm' => ['required', 'same:password'],
];

print_r(validate([
    'name' => '',
    'email' => 'asha@',
    'age' => '15',
    'password' => 'short',
    'password_confirm' => 'shorter',
], $rules));

$valid = validate([
    'name' => 'Asha',
    'email' => 'asha@example.com',
    'age' => '24',
    'password' => 'Secure#2026',
    'password_confirm' => 'Secure#2026',
], $rules);

echo $valid === [] ? "No errors\n" : "Errors found\n";

Output

Array
(
    [name] => The name field is required.
    [email] => The email must be a valid email address.
    [age] => The age must be a whole number between 18 and 100.
    [password] => The password must be at least 8 characters.
    [password_confirm] => The password confirm must match the password.
)
No errors

How It Works

  1. Rules are written as short strings ('int:18:100'); explode(':', ...) splits the rule name from its parameters, and array_pad() guarantees three elements for destructuring.
  2. Every value is read safely: non-string input (for example, an array sent as name[]) is treated as empty.
  3. A match expression maps each rule to its check. Most rules skip empty values, so required alone decides whether a field may be empty — optional fields can still have format rules.
  4. Only the first failing rule per field is reported (break), giving one clear message per field.
  5. Unknown rule names throw an exception, so typos in rule definitions are noticed immediately.

Note: This simplified validator trims every value. In a real application, do not trim passwords — leading or trailing spaces may be intentional. Frameworks provide complete validators (Laravel's $request->validate(), Symfony Validator) built on the same ideas.


Where Validation Fits

read input → validate → (if errors) re-display form with messages
                      → (if valid) process with the validated, typed values
  • Validate all fields and show all errors together.
  • Use the converted values from validation (for example, the integer returned by filter_var()) for further processing.
  • Validation does not replace output escaping (htmlspecialchars()) or prepared statements for SQL; each protects a different step.

Common Mistakes

Relying on HTML Validation

Effect: Invalid or malicious data reaches the server.

Fix: Validate every field in PHP.

Using Casts Instead of Validation

Effect: (int) 'abc' silently becomes 0; (int) '42abc' becomes 42.

Fix: filter_var(..., FILTER_VALIDATE_INT) and check for false.

Checking Filter Results Loosely

Effect: Valid values 0 or false are treated as failures.

Fix: Compare with === false (or use FILTER_NULL_ON_FAILURE for booleans).

Validating Without Allow-Lists

Effect: Unexpected values for plans, roles, or sort orders are accepted.

Fix: in_array($value, $allowed, true).

Stopping at the First Error

Effect: Users fix one problem, resubmit, and discover the next.

Fix: Collect errors for all fields.


Best Practices

  • Validate on the server, using HTML validation only for convenience.
  • Use filter_var() for types and standard formats, and regular expressions for custom formats.
  • Keep validation rules in one place and return field-specific error messages.
  • Work with the converted, validated values afterwards.
  • Combine validation with output escaping, prepared statements, and CSRF protection.

Official reference: https://www.php.net/manual/en/book.filter.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Home PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement PHP Home PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope PHP Casting Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence Continue Statement Modify Strings PHP If...Else...Elseif PHP If Modify Strings PHP If Operators PHP Functions Concatenate Strings PHP If...Else Slicing Strings User-defined Functions Slicing Strings PHP Shorthand if Escape Characters Default Argument Values PHP Nested if Pass by Reference String Interpolation Named Arguments PHP File Upload Variadic Functions Return Values Search in Strings Multibyte Strings Type Declarations in Functions PHP Numbers PHP Math PHP Floats PHP Random Numbers PHP Constants PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Cookies PHP Destructor PHP Access Modifiers Readonly Properties PHP Sessions PHP Inheritance Method Overriding PHP Filters The final Keyword CSRF Protection PHP Filters Advanced Session Security Secure Cookies PHP Magic Constants File Upload Security PHP Callback Functions PHP Operators Filesystem Security PHP JSON Arithmetic Operators Error Reporting in Production Hiding PHP Assignment Operators PHP Configuration (php.ini) Comparison Operators PHP Command Line (CLI) PHP Exceptions Increment / Decrement Operators Migrating to PHP 8 PHP Form Validation PHP Form Required PHP Form URL/E-mail Error Handling Form Input Sanitizing Escaping Output (htmlspecialchars) Custom Error Handler Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators
Ask about this post
AI Ask about this post

Ask questions about PHP Form Validation and get answers drawn from it.

Signed-in readers only.