Session 4.5 – PHP Filters

Module 4: Server-Side Scripting – PHP | Duration: 1 hr

Learning Objectives

By the end of this session, students will be able to:

  • Understand the importance of input filtering and sanitization
  • Use PHP filter functions for validation and sanitization
  • Apply appropriate filters for different data types
  • Implement custom filter validation
  • Secure applications against injection attacks
  • Combine filters for comprehensive data validation

Introduction to PHP Filters

PHP filters are used to validate and sanitize external input. They provide a secure way to handle user data and protect against injection attacks and invalid data.

Why Use Filters?
  • Security: Prevent SQL injection, XSS, and other attacks
  • Data Integrity: Ensure data meets expected format
  • Consistency: Standardized validation across application
  • Performance: Built-in functions are optimized

Filter Types

Validation Filters

Check if data meets certain criteria. Returns the value if valid, FALSE otherwise.

  • FILTER_VALIDATE_BOOLEAN
  • FILTER_VALIDATE_EMAIL
  • FILTER_VALIDATE_FLOAT
  • FILTER_VALIDATE_INT
  • FILTER_VALIDATE_IP
  • FILTER_VALIDATE_URL
  • FILTER_VALIDATE_REGEXP
  • FILTER_VALIDATE_DOMAIN
Sanitization Filters

Remove or encode unwanted characters. Returns the sanitized value.

  • FILTER_SANITIZE_EMAIL
  • FILTER_SANITIZE_ENCODED
  • FILTER_SANITIZE_NUMBER_FLOAT
  • FILTER_SANITIZE_NUMBER_INT
  • FILTER_SANITIZE_SPECIAL_CHARS
  • FILTER_SANITIZE_STRING
  • FILTER_SANITIZE_URL
  • FILTER_UNSAFE_RAW

Validation Filters

Email Validation
<?php
$email = "user@example.com";

// Basic validation
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "Valid email address";
} else {
    echo "Invalid email address";
}

// Check if email exists (additional validation)
function isValidEmail($email) {
    // Validate format
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        return false;
    }

    // Check domain has MX record
    list($user, $domain) = explode('@', $email);
    if (!checkdnsrr($domain, 'MX')) {
        return false;
    }

    return true;
}
?>
URL Validation
<?php
$url = "https://www.example.com";

if (filter_var($url, FILTER_VALIDATE_URL)) {
    echo "Valid URL";
} else {
    echo "Invalid URL";
}

// Validate URL with specific protocol
$options = array(
    'options' => array(
        'default' => NULL,
        'regexp' => '/^https:\/\/.*/'  // Must start with https://
    )
);

if (filter_var($url, FILTER_VALIDATE_REGEXP, $options)) {
    echo "Valid HTTPS URL";
}
?>
Integer and Float Validation
<?php
// Integer validation
$age = "25";

if (filter_var($age, FILTER_VALIDATE_INT)) {
    echo "Valid integer";
}

// Integer with range
$options = array(
    'options' => array(
        'min_range' => 18,
        'max_range' => 120
    )
);

if (filter_var($age, FILTER_VALIDATE_INT, $options)) {
    echo "Valid age (18-120)";
}

// Float validation
$price = "19.99";

if (filter_var($price, FILTER_VALIDATE_FLOAT)) {
    echo "Valid float";
}

// Float with decimal separator
$options = array(
    'options' => array(
        'decimal' => ','  // Accept comma as decimal separator
    )
);

$price_eu = "19,99";
if (filter_var($price_eu, FILTER_VALIDATE_FLOAT, $options)) {
    echo "Valid European price format";
}
?>
IP Address Validation
<?php
$ip = "192.168.1.1";

// Validate any IP address
if (filter_var($ip, FILTER_VALIDATE_IP)) {
    echo "Valid IP address";
}

// Validate IPv4 only
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
    echo "Valid IPv4 address";
}

// Validate IPv6 only
$ipv6 = "2001:0db8:85a3::8a2e:0370:7334";
if (filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
    echo "Valid IPv6 address";
}

// Not private or reserved range
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
    echo "Valid public IP address";
}
?>
Boolean Validation
<?php
// These return TRUE
$values = array("1", "true", "on", "yes");
foreach ($values as $value) {
    var_dump(filter_var($value, FILTER_VALIDATE_BOOLEAN));  // bool(true)
}

// These return FALSE
$values = array("0", "false", "off", "no");
foreach ($values as $value) {
    var_dump(filter_var($value, FILTER_VALIDATE_BOOLEAN));  // bool(false)
}

// NULL_ON_FAILURE flag
$result = filter_var("invalid", FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
var_dump($result);  // NULL instead of FALSE
?>

Sanitization Filters

Sanitize Email
<?php
$email = "user(comment)@exa mple.com";
$clean_email = filter_var($email, FILTER_SANITIZE_EMAIL);
echo $clean_email;  // user@example.com

// Remove all illegal characters
?>
Sanitize URL
<?php
$url = "https://www.example.com/<script>alert('xss')</script>";
$clean_url = filter_var($url, FILTER_SANITIZE_URL);
echo $clean_url;  // https://www.example.com/scriptalert'xss'/script

// Removes all illegal characters from URL
?>
Sanitize Numbers
<?php
// Sanitize integer
$number = "123abc456";
$clean_int = filter_var($number, FILTER_SANITIZE_NUMBER_INT);
echo $clean_int;  // 123456

// Sanitize float
$price = "$19.99 USD";
$clean_float = filter_var($price, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
echo $clean_float;  // 19.99

// Allow decimal and thousand separator
$price = "1,234.56";
$clean = filter_var($price, FILTER_SANITIZE_NUMBER_FLOAT,
    FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND);
echo $clean;  // 1,234.56
?>
Sanitize Special Characters
<?php
$text = "<script>alert('XSS')</script>";

// Encode special characters
$clean = filter_var($text, FILTER_SANITIZE_SPECIAL_CHARS);
echo $clean;  // &lt;script&gt;alert('XSS')&lt;/script&gt;

// This is similar to htmlspecialchars()
$clean2 = htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
echo $clean2;
?>
Remove HTML Tags
<?php
$html = "<p>Hello <b>World</b><script>alert('xss')</script></p>";

// Remove all HTML tags
$clean = strip_tags($html);
echo $clean;  // Hello World

// Allow specific tags
$clean = strip_tags($html, '<p><b>');
echo $clean;  // <p>Hello <b>World</b></p>
?>

Filter Functions

filter_var() - Single Variable
<?php
// Basic usage
$email = "user@example.com";
$result = filter_var($email, FILTER_VALIDATE_EMAIL);

if ($result !== false) {
    echo "Valid: $result";
} else {
    echo "Invalid email";
}
?>
filter_input() - Get and Filter Input
<?php
// Get and validate from $_GET
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);

if ($id !== false && $id !== null) {
    echo "Valid ID: $id";
}

// Get and sanitize from $_POST
$email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);

// With options
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT, array(
    'options' => array(
        'min_range' => 0,
        'max_range' => 120,
        'default' => 0
    )
));

// Available input types
// INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV
?>
filter_var_array() - Multiple Variables
<?php
// Define filters for multiple variables
$data = array(
    'name' => 'John Doe',
    'email' => 'john@example.com',
    'age' => '25',
    'website' => 'https://example.com'
);

$filters = array(
    'name' => FILTER_SANITIZE_STRING,
    'email' => FILTER_VALIDATE_EMAIL,
    'age' => array(
        'filter' => FILTER_VALIDATE_INT,
        'options' => array('min_range' => 1, 'max_range' => 120)
    ),
    'website' => FILTER_VALIDATE_URL
);

$result = filter_var_array($data, $filters);

// Check results
if ($result['email'] === false) {
    echo "Invalid email";
}
if ($result['age'] === false) {
    echo "Invalid age";
}
?>
filter_input_array() - Get Multiple Inputs
<?php
// Define filters for $_POST data
$filters = array(
    'username' => FILTER_SANITIZE_STRING,
    'email' => FILTER_SANITIZE_EMAIL,
    'age' => array(
        'filter' => FILTER_VALIDATE_INT,
        'flags' => FILTER_REQUIRE_SCALAR,
        'options' => array('min_range' => 18, 'max_range' => 100)
    )
);

// Filter all $_POST variables
$result = filter_input_array(INPUT_POST, $filters);

// Validate results
$errors = array();

if (!filter_var($result['email'], FILTER_VALIDATE_EMAIL)) {
    $errors[] = "Invalid email";
}

if ($result['age'] === false || $result['age'] === null) {
    $errors[] = "Invalid age";
}

if (empty($errors)) {
    echo "All inputs valid";
} else {
    foreach ($errors as $error) {
        echo $error . "<br>";
    }
}
?>

Practical Examples

Complete Registration Form Validation
<?php
// register.php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {

    // Define filters
    $filters = array(
        'username' => array(
            'filter' => FILTER_CALLBACK,
            'options' => function($value) {
                $value = trim($value);
                if (strlen($value) < 3 || strlen($value) > 20) {
                    return false;
                }
                if (!preg_match('/^[a-zA-Z0-9_]+$/', $value)) {
                    return false;
                }
                return $value;
            }
        ),
        'email' => FILTER_VALIDATE_EMAIL,
        'age' => array(
            'filter' => FILTER_VALIDATE_INT,
            'options' => array('min_range' => 18, 'max_range' => 120)
        ),
        'website' => array(
            'filter' => FILTER_VALIDATE_URL,
            'flags' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED
        ),
        'agree_terms' => FILTER_VALIDATE_BOOLEAN
    );

    // Filter inputs
    $inputs = filter_input_array(INPUT_POST, $filters);

    // Validation
    $errors = array();

    if ($inputs['username'] === false || $inputs['username'] === null) {
        $errors['username'] = "Username must be 3-20 alphanumeric characters";
    }

    if ($inputs['email'] === false) {
        $errors['email'] = "Invalid email address";
    }

    if ($inputs['age'] === false || $inputs['age'] === null) {
        $errors['age'] = "Age must be between 18 and 120";
    }

    if (isset($inputs['website']) && !empty($_POST['website']) && $inputs['website'] === false) {
        $errors['website'] = "Invalid website URL";
    }

    if (!$inputs['agree_terms']) {
        $errors['agree_terms'] = "You must agree to the terms";
    }

    // Process if no errors
    if (empty($errors)) {
        // Sanitize for display/storage
        $clean_username = htmlspecialchars($inputs['username'], ENT_QUOTES, 'UTF-8');
        $clean_email = htmlspecialchars($inputs['email'], ENT_QUOTES, 'UTF-8');

        // Save to database (use prepared statements!)
        echo "Registration successful!";
    } else {
        // Display errors
        foreach ($errors as $field => $error) {
            echo "<div class='alert alert-danger'>$error</div>";
        }
    }
}
?>
Search Form with Sanitization
<?php
// search.php
$search = filter_input(INPUT_GET, 'q', FILTER_SANITIZE_STRING);
$page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT, array(
    'options' => array('min_range' => 1, 'default' => 1)
));
$category = filter_input(INPUT_GET, 'category', FILTER_SANITIZE_STRING);

// Additional validation
if (strlen($search) > 100) {
    $search = substr($search, 0, 100);
}

// Remove extra whitespace
$search = preg_replace('/\s+/', ' ', trim($search));

// Escape for display
$safe_search = htmlspecialchars($search, ENT_QUOTES, 'UTF-8');

echo "Searching for: $safe_search";
echo "Page: $page";

// Use in database query with prepared statements
// $stmt = $pdo->prepare("SELECT * FROM products WHERE name LIKE ? LIMIT ?, 20");
// $stmt->execute(["%$search%", ($page - 1) * 20]);
?>
Custom Filter Callback
<?php
// Custom validation function
function validatePhone($phone) {
    // Remove formatting
    $phone = preg_replace('/[^0-9]/', '', $phone);

    // Check length
    if (strlen($phone) != 10) {
        return false;
    }

    // Format as (XXX) XXX-XXXX
    return sprintf("(%s) %s-%s",
        substr($phone, 0, 3),
        substr($phone, 3, 3),
        substr($phone, 6)
    );
}

// Use custom filter
$phone = filter_input(INPUT_POST, 'phone', FILTER_CALLBACK, array(
    'options' => 'validatePhone'
));

if ($phone === false) {
    echo "Invalid phone number";
} else {
    echo "Formatted phone: $phone";
}
?>

Session Summary

Key Points
  • PHP filters provide built-in validation and sanitization functions
  • Validation filters check if data meets criteria (returns value or FALSE)
  • Sanitization filters remove or encode unwanted characters
  • filter_var() filters a single variable
  • filter_input() gets and filters external input directly
  • filter_var_array() and filter_input_array() handle multiple values
  • Custom callbacks can be used for complex validation logic
  • Always combine filters with proper error handling and security practices
Next Session Preview

In the next session, we will explore Error Handling and Exceptions in PHP, learning how to gracefully handle errors and implement robust error management in our applications.