Browser validation (required, type="email") is a convenience for
honest users. Server-side validation is the real thing — anyone can
bypass the browser entirely.
Required fields
PHP
<?php
$errors = [];
$name = trim($_POST['name'] ?? '');
if ($name === '') {
$errors['name'] = 'Name is required.';
} elseif (mb_strlen($name) > 100) {
$errors['name'] = 'Name is too long.';
}Use mb_strlen() rather than strlen() for user text — Devanagari
characters are multi-byte, and strlen() counts bytes, not letters.
PHP
<?php
$email = trim($_POST['email'] ?? '');
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors['email'] = 'Enter a valid email address.';
}Numbers and ranges
PHP
<?php
$age = filter_var($_POST['age'] ?? '', FILTER_VALIDATE_INT, [
'options' => ['min_range' => 5, 'max_range' => 120],
]);
if ($age === false) {
$errors['age'] = 'Age must be a number between 5 and 120.';
}filter_var() returns false on failure — and since 0 is a valid int,
check with === false, not !$age.
Nepali phone numbers
PHP
<?php
$phone = preg_replace('/\D/', '', $_POST['phone'] ?? ''); // digits only
if (!preg_match('/^(97|98)\d{8}$/', $phone)) {
$errors['phone'] = 'Enter a valid 10-digit mobile number.';
}Choices from a fixed list
Never trust a <select> — validate against your own allowed list:
PHP
<?php
$allowed = ['science', 'management', 'humanities'];
$faculty = $_POST['faculty'] ?? '';
if (!in_array($faculty, $allowed, true)) {
$errors['faculty'] = 'Choose a valid faculty.';
}The true third argument makes it a strict comparison — without it,
in_array(0, ['science']) is surprisingly true in older PHP.
Putting it together
PHP
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// ... all checks above, filling $errors ...
if (empty($errors)) {
// safe to save
header('Location: /success.php');
exit;
}
}Sanitise on output, not on input
Store what the user actually typed; escape it when you display it. If you mangle input at save time you can never recover the original.
PHP
<?php
echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8');