MasterPHP.in
PHP Tutorial

PHP Form Validation & Basic Security


Why You Can Never Trust Form Input

The previous lesson covered how to receive form data, but there's a core principle every PHP developer needs to internalize: never trust user input. Anything submitted through a form, a URL parameter, or an API request could be empty, malformed, unexpected, or even deliberately malicious. Validation and security aren't optional extras — they're a fundamental part of handling forms correctly, not a separate advanced topic.

This lesson covers two closely related things: validation (checking that input meets the rules you expect) and basic security (protecting your application from common attacks through that input).


Required Field Validation

The most basic form of validation is checking that required fields aren't empty.


php

<?php
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
$errors = [];

if (empty($name)) {
    $errors[] = "Name is required.";
}

if (empty($email)) {
    $errors[] = "Email is required.";
}

if (!empty($errors)) {
    foreach ($errors as $error) {
        echo $error . "\n";
    }
} else {
    echo "Form submitted successfully.";
}

Collecting errors into an array, rather than stopping at the first problem, is generally better practice — it lets you show the user everything that needs fixing at once, instead of making them resubmit repeatedly for one error at a time.


Validating Email Format

PHP includes a built-in filter specifically for validating email addresses, which is far more reliable than trying to write your own pattern-matching logic.


php

<?php
$email = $_POST['email'] ?? '';

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "Please enter a valid email address.";
} else {
    echo "Email looks valid.";
}

filter_var() with FILTER_VALIDATE_EMAIL checks that the string follows a properly formatted email structure. It's worth noting this only validates the format — it doesn't confirm the email address actually exists or belongs to the person submitting the form.


Validating Numbers and Ranges


php

<?php
$age = $_POST['age'] ?? '';

if (!filter_var($age, FILTER_VALIDATE_INT)) {
    echo "Age must be a valid number.";
} elseif ($age < 18 || $age > 100) {
    echo "Age must be between 18 and 100.";
} else {
    echo "Age is valid.";
}

FILTER_VALIDATE_INT confirms the submitted value is genuinely an integer before you attempt any range checks or calculations on it — an important step, since form input always arrives as a string, and a value like "25abc" could otherwise cause unexpected behavior.


Validating Against a Pattern (Regular Expressions)

For formats that don't have a built-in filter, such as a specific phone number pattern, regular expressions provide precise control.


php

<?php
$phone = $_POST['phone'] ?? '';

if (!preg_match('/^[0-9]{10}$/', $phone)) {
    echo "Phone number must be exactly 10 digits.";
} else {
    echo "Phone number is valid.";
}

This pattern (^[0-9]{10}$) requires exactly 10 numeric digits, with nothing before or after — a common validation requirement for Indian mobile numbers.


What is Sanitization, and How Is It Different from Validation?

Validation checks whether input meets your rules and rejects it if it doesn't. Sanitization is different — it cleans or modifies input to make it safe, rather than rejecting it outright. Both are typically used together.


Concept          What It Does                          Example
------------------------------------------------------------
Validation        Checks if input meets the rules,      "Is this a
                   accepts or rejects it                  valid email?"

Sanitization       Cleans/modifies input to remove       Strips out HTML
                   potentially unsafe content              tags from a
                                                            comment field


php

<?php
$comment = $_POST['comment'] ?? '';

$cleanComment = htmlspecialchars($comment);
echo $cleanComment;

Preventing Cross-Site Scripting (XSS)

One of the most important security habits in PHP is using htmlspecialchars() any time you display user-submitted content back on a page. Without it, a malicious user could submit HTML or JavaScript code as form input, which would then execute in other visitors' browsers when displayed — an attack known as Cross-Site Scripting (XSS).


php

<?php
$comment = $_POST['comment'] ?? '';

// Unsafe: directly echoing user input
// echo $comment;

// Safe: converts special characters into harmless HTML entities
echo htmlspecialchars($comment);

If a user submitted <script>alert('hacked')</script> as a comment, htmlspecialchars() converts the angle brackets into their safe HTML entity equivalents, so the browser displays the text literally instead of executing it as code. This single function is one of the most important habits to build early — apply it any time you output user-submitted data back onto a page.


Trimming and Normalizing Input

Users frequently submit data with accidental extra spaces, which can cause validation checks to behave unexpectedly (an email with a trailing space, for instance, might otherwise pass a check but fail to match later).


php

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

Applying trim() consistently before validating or storing input is a small habit that prevents a surprising number of subtle bugs.


Whitelisting Expected Values

For fields with a fixed set of valid options, like a dropdown, it's good practice to verify the submitted value is actually one of the expected choices, rather than trusting it blindly — since form data can be manipulated outside of the browser.


php

<?php
$country = $_POST['country'] ?? '';
$allowedCountries = ['IN', 'US', 'UK'];

if (!in_array($country, $allowedCountries)) {
    echo "Invalid country selection.";
} else {
    echo "Country accepted.";
}

Even though a dropdown limits what a user can see as options, nothing stops someone from submitting a different value directly, bypassing the HTML entirely. Server-side validation like this is what actually enforces the rule.


A Note on Passwords

Password fields deserve special mention: passwords should never be stored as plain, readable text. PHP provides a built-in function specifically for this purpose:


php

<?php
$password = $_POST['password'] ?? '';

$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
// Store $hashedPassword in the database, never the original password

// Later, when verifying a login attempt:
if (password_verify($password, $hashedPassword)) {
    echo "Password matches.";
}

password_hash() converts a password into a scrambled, irreversible format, and password_verify() checks a plain password attempt against that stored hash without ever needing to store or compare the original text. This is a non-negotiable practice for any application handling user accounts.


Putting It All Together: A Validated Form


php

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

if (empty($name)) {
    $errors[] = "Name is required.";
}

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    $errors[] = "A valid email is required.";
}

if (!filter_var($age, FILTER_VALIDATE_INT) || $age < 18) {
    $errors[] = "Age must be a number, 18 or older.";
}

if (empty($errors)) {
    $safeName = htmlspecialchars($name);
    echo "Welcome, $safeName!";
} else {
    foreach ($errors as $error) {
        echo $error . "\n";
    }
}

This example combines required-field checks, format validation, and safe output into a single realistic flow, closely resembling how a real signup or contact form would be handled.


What's Next

  • With forms, validation, and basic security covered, you now have the tools to safely collect and process real user input, one of the most common tasks in any PHP application. From here, the natural next step is learning object-oriented PHP, which introduces a more structured way to organize the logic you've been writing so far — including form handling — into reusable classes.

Frequently Asked Questions

Validation checks whether input meets specific rules and either accepts or rejects it entirely, such as confirming an email is properly formatted. Sanitization instead cleans or modifies input to make it safer, such as stripping out HTML tags, without necessarily rejecting the submission.
Without it, any HTML or JavaScript code submitted by a user could execute in other visitors' browsers when displayed on the page, a vulnerability known as Cross-Site Scripting (XSS). htmlspecialchars() converts special characters into safe equivalents so they display as plain text instead of executing.
No. Client-side validation improves user experience by catching mistakes early, but it can be bypassed entirely, since anyone can submit data directly to your server without going through the HTML form at all. Server-side validation in PHP is what actually protects your application.
If a database is ever compromised, plain text passwords would be immediately readable and exploitable. Using password_hash() stores an irreversible, scrambled version instead, so even in a data breach, the original passwords remain protected.
filter_var() is a built-in PHP function that checks or sanitizes a value against a specific filter, such as FILTER_VALIDATE_EMAIL or FILTER_VALIDATE_INT. It's generally more reliable than writing custom validation logic for common formats, since PHP's built-in filters are well-tested and consistently maintained.

Share this tutorial