Skip to main content
SNP-2026-1
Home / Code Snippets / SNP-2026-1
SNP-2026-1  ·  CODE SNIPPET

Validate and Sanitize Form Input with filter_var in PHP

PHP validate production-ready · Published: 2026-05-23 · debmedia
01
Problem Statement & Scenario
The Problem

THE PROBLEM

In the demanding landscape of SaaS development, where applications like FolderX, AdSpy Pro, and Website Factory handle vast amounts of user-generated content and critical configuration data, the integrity and security of input are paramount. Every piece of data submitted through a form—be it a user's email during registration, a product description, a URL for an integration, or an integer for a setting—is a potential vector for attack or a source of data corruption. Without robust server-side validation and sanitization, you're opening the door to a myriad of issues.

Imagine a scenario where a user submits a registration form. If the email field isn't properly validated, you might store "not-an-email" in your database, leading to failed password resets, broken notification systems, and a poor user experience. Worse, if a text area for a profile bio isn't sanitized, a malicious user could inject cross-site scripting (XSS) payloads like <script>alert('XSS');</script>, compromising other users' sessions. An unvalidated URL could lead to server-side request forgery (SSRF) or simply break external API calls. Numeric fields, if not strictly validated, might accept non-numeric input, causing database errors or unexpected behavior in calculations.

The pain point is clear: debugging issues caused by bad data downstream is incredibly time-consuming and costly. It can lead to data loss, security breaches, and a complete breakdown of business logic. Relying solely on client-side JavaScript validation is a critical mistake; it's easily bypassed. This snippet provides a battle-tested, production-ready solution for server-side input validation and sanitization, ensuring that only clean, valid data ever reaches your application's core logic and database.

02
Production-Ready Code Snippet
The Snippet

THE SNIPPET

<?php

/**
 * Validates and sanitizes an array of raw input data using PHP's filter_var.
 *
 * This function provides a robust, declarative way to process form submissions,
 * safeguarding against common vulnerabilities like XSS and ensuring data integrity.
 *
 * @param array $rawData The raw input data, typically from $_POST, $_GET, or $_REQUEST.
 * @param array $rules An associative array defining validation and sanitation rules.
 *                     Key is the input field name, value is an array with:
 *                     - 'filter': The filter constant (e.g., FILTER_VALIDATE_EMAIL, FILTER_SANITIZE_STRING).
 *                     - 'flags' (optional): Filter flags (e.g., FILTER_FLAG_STRIP_LOW, FILTER_NULL_ON_FAILURE).
 *                     - 'options' (optional): Filter options (e.g., ['min_range' => 1, 'max_range' => 100]).
 *                     - 'required' (optional): Boolean, true if the field is mandatory.
 * @return array An associative array containing 'data' (sanitized values) and 'errors' (validation messages).
 */
function validateAndSanitizeInput(array $rawData, array $rules): array
{
    $sanitizedData = []; // Initialize array to store successfully processed data
    $errors = [];        // Initialize array to store validation errors

    foreach ($rules as $field => $config) {
        $filter = $config['filter'] ?? null;    // Get the filter constant for the current field
        $flags = $config['flags'] ?? null;      // Get any filter flags
        $options = $config['options'] ?? null;  // Get any filter options
        $required = $config['required'] ?? false; // Check if the field is marked as required

        $value = $rawData[$field] ?? null; // Safely retrieve the raw value, null if not present in input

        // --- Handle required fields ---
        // Check if the field is required AND its value is effectively empty.
        // Explicitly checks for '0' as a valid non-empty value (e.g., age, quantity).
        if ($required && (empty($value) && $value !== '0' && $value !== 0)) {
            $errors[$field] = ucfirst($field) . ' is required.'; // Add error message
            continue; // Skip further processing for this field if it's required and empty
        }

        // --- Handle non-required, empty fields ---
        // If the field is not required and is empty, set its sanitized value to null and move on.
        if (!$required && (empty($value) && $value !== '0' && $value !== 0)) {
            $sanitizedData[$field] = null;
            continue;
        }

        // --- Prepare arguments for filter_var ---
        $filterArgs = [];
        if ($flags !== null) {
            $filterArgs['flags'] = $flags;
        }
        if ($options !== null) {
            $filterArgs['options'] = $options;
        }

        // --- Apply filter_var ---
        // This is the core function call for validation and sanitization.
        $filteredValue = filter_var($value, $filter, $filterArgs);

        // --- Check for validation failure ---
        // filter_var returns false for validation failures, or null if FILTER_NULL_ON_FAILURE flag is set.
        // We check for both explicitly to be robust.
        if ($filteredValue === false || ($filteredValue === null && !($flags & FILTER_NULL_ON_FAILURE))) {
            $errors[$field] = ucfirst($field) . ' is invalid.'; // Record validation error
        } else {
            // --- Special handling for sanitization edge cases ---
            // For email/URL sanitization, an invalid input might become an empty string.
            // If the original value was not empty but became empty after sanitization, treat as invalid.
            if (($filter === FILTER_SANITIZE_EMAIL || $filter === FILTER_SANITIZE_URL) && $filteredValue === '' && !empty($value)) {
                 $errors[$field] = ucfirst($field) . ' is invalid.';
            } else {
                $sanitizedData[$field] = $filteredValue; // Store the successfully filtered value
            }
        }
    }

    return [
        'data' => $sanitizedData, // Return the array of sanitized data
        'errors' => $errors,     // Return the array of validation errors
    ];
}
03
Line-by-Line Breakdown
How It Works

HOW IT WORKS

The validateAndSanitizeInput function serves as a centralized, declarative mechanism for processing incoming request data. It takes two primary arguments: $rawData, typically an array like $_POST or $_GET, and $rules, an associative array defining how each input field should be handled.

Upon invocation, the function initializes two arrays: $sanitizedData to hold all successfully validated and sanitized values, and $errors to collect any validation messages. It then iterates through each field defined in the $rules array.

For each field, the function first extracts its specific configuration: the filter constant (e.g., FILTER_VALIDATE_EMAIL, FILTER_SANITIZE_STRING), any optional flags (like FILTER_FLAG_STRIP_LOW for sanitization or FILTER_NULL_ON_FAILURE for validation), and any options (such as min_range and max_range for integer validation). It also checks if the field is marked as required.

The raw value for the current field is safely retrieved using the null coalescing operator ($rawData[$field] ?? null), ensuring that if a field is not present in the raw input, it defaults to null without throwing a notice. This is crucial for handling optional fields or unexpected input.

A critical step is the handling of required fields. The function explicitly checks if a field is both marked as required and is effectively empty. The condition (empty($value) && $value !== '0' && $value !== 0) is important: empty() would consider 0 (integer or string) as empty, which is often not desired for numeric inputs. By adding $value !== '0' && $value !== 0, the function correctly treats 0 as a valid, non-empty input. If a required field is truly empty, an error is recorded, and the loop moves to the next field.

Similarly, if a field is not required and is empty, its entry in $sanitizedData is set to null, and no further filtering is performed for that field, preventing unnecessary processing.

Before calling the core filter_var() function, an $filterArgs array is constructed to pass any specified flags and options. This ensures that the filter operates with the desired behavior (e.g., requiring a scheme for a URL, or defining a range for an integer).

The heart of the snippet is the call to filter_var(). This powerful PHP function attempts to validate or sanitize the $value based on the provided $filter and $filterArgs. For a comprehensive list of available filters and their behaviors, refer to the PHP Filters documentation.

After filter_var() executes, the function checks its return value for validation failures. filter_var() typically returns false for validation failures (e.g., an invalid email format with FILTER_VALIDATE_EMAIL). If the FILTER_NULL_ON_FAILURE flag is used, it returns null instead. The condition $filteredValue === false || ($filteredValue === null && !($flags & FILTER_NULL_ON_FAILURE)) robustly captures these failure states. If a validation fails, an error message is stored.

An important edge case is handled for FILTER_SANITIZE_EMAIL and FILTER_SANITIZE_URL. These sanitization filters might return an empty string ('') if the input is highly malformed. If the original $value was not empty but became an empty string after sanitization, it's typically an indication that the input was invalid rather than just empty, so an error is recorded. Otherwise, the successfully filtered value is stored in $sanitizedData.

Finally, the function returns an associative array containing both the 'data' (all valid and sanitized inputs) and 'errors' (any validation messages encountered).

04
Real-World Usage Example
Usage Example

REAL-WORLD USAGE EXAMPLE

1-on-1 Technical Mentorship

Want to master snippets like this?

Debasis Bhattacharjee offers direct mentorship sessions for developers looking to level up their code quality, architecture decisions, and production engineering skills. Two decades of real-world experience — no theory, just craft.