SyntaxStudy
Sign Up
PHP Server-Side Validation Patterns
PHP Intermediate 9 min read

Server-Side Validation Patterns

As applications grow, ad-hoc validation logic becomes messy. Adopting consistent patterns keeps code readable and testable.

  • Centralise rules in a validation function or class.
  • Use PHP's filter_var() with FILTER_VALIDATE_* for common types.
  • Apply the Post/Redirect/Get (PRG) pattern to prevent duplicate form submissions on refresh.
Example
<?php
// Reusable validator helper
function validate(array $data, array $rules): array
{
    $errors = [];
    foreach ($rules as $field => $rule) {
        $value = trim($data[$field] ?? '');
        foreach (explode('|', $rule) as $r) {
            [$type, $param] = array_pad(explode(':', $r, 2), 2, null);
            match ($type) {
                'required' => $value === '' ? $errors[$field][] = "$field is required" : null,
                'min'      => strlen($value) < $param ? $errors[$field][] = "$field min $param chars" : null,
                'max'      => strlen($value) > $param ? $errors[$field][] = "$field max $param chars" : null,
                'email'    => !filter_var($value, FILTER_VALIDATE_EMAIL) ? $errors[$field][] = "$field must be valid email" : null,
                'numeric'  => !is_numeric($value) ? $errors[$field][] = "$field must be numeric" : null,
                default    => null,
            };
        }
    }
    return $errors;
}

// Usage
$rules = [
    'name'  => 'required|min:2|max:100',
    'email' => 'required|email',
    'age'   => 'required|numeric',
];

$errors = validate($_POST, $rules);

if (empty($errors)) {
    // Process, then redirect (PRG pattern)
    header('Location: /success.php');
    exit;
}
Pro Tip

Tip: The Post/Redirect/Get (PRG) pattern prevents duplicate submissions: after a successful POST, redirect to a GET URL. This way, if the user hits refresh, they re-fetch the GET page instead of re-submitting the POST data.