Form Input Sanitizing

sa sahaya jerish Updated 17 Oct 2026
7 min read ·Lesson 95 of 109
In this post

What Is Sanitizing? In simple terms: Sanitizing means cleaning input: removing extra spaces, unwanted characters, or formatting so the value is in a consistent shape — for example, turning +91 98765-4

What Is Sanitizing?

In simple terms: Sanitizing means cleaning input: removing extra spaces, unwanted characters, or formatting so the value is in a consistent shape — for example, turning +91 98765-43210 into 9876543210.

Technically: Sanitization transforms a value, while validation only checks it. PHP provides sanitizing filters (FILTER_SANITIZE_*) and many string functions (trim(), preg_replace(), strip_tags(), mb_strtolower()) that can be used for this purpose.

Sanitizing vs Validating vs Escaping

These three are often confused, but each has a different job:

StepQuestionExampleWhen
Normalize / sanitize"Can I bring this value into a standard shape?"Trim spaces, remove separators from a phone numberWhen receiving input
Validate"Is this value acceptable?"Is it a valid email? Is the age 18–100?After normalizing
Escape"How do I output this safely in this context?"htmlspecialchars() for HTML, prepared statements for SQLWhen using the value

The modern approach is: normalize lightly, validate strictly, escape on output. Sanitizing is not a security measure on its own; it does not replace validation or escaping.


Why "Sanitize Everything" Is a Bad Strategy

A common older practice was to strip or encode all input on arrival "to make it safe". This causes real problems:

  1. It changes the meaning of data. A name like O'Brien or a message containing <3 gets altered or corrupted.
  2. It hides invalid input. An invalid email that is "cleaned" into a different, valid-looking address is worse than rejecting it.
  3. It applies the wrong protection. Data stored in a database may later be shown in HTML, exported to CSV, or sent in JSON — each needs different escaping, which can only be applied at output time.

Example: Sanitizing Can Change Meaning

<?php
var_dump(filter_var(' asha (at) example.com ', FILTER_SANITIZE_EMAIL));
var_dump(filter_var('₹1,299/-', FILTER_SANITIZE_NUMBER_INT));

Output

string(17) "ashaatexample.com"
string(5) "1299-"
  • FILTER_SANITIZE_EMAIL removed the spaces and parentheses, producing a different string that is still not a valid email. Rejecting the input with a clear message would be better.
  • FILTER_SANITIZE_NUMBER_INT removed the rupee sign, comma, and slash but kept the minus sign, producing 1299-, which is not a valid number.

Sanitizing filters are useful in specific situations, but their output must still be validated.


The Sanitizing Filters

FilterWhat It Does
FILTER_SANITIZE_EMAILRemoves characters not allowed in email addresses
FILTER_SANITIZE_URLRemoves characters not allowed in URLs
FILTER_SANITIZE_NUMBER_INTKeeps only digits, +, and -
FILTER_SANITIZE_NUMBER_FLOATKeeps digits, +, -, and (with flags) ., ,, e/E
FILTER_SANITIZE_SPECIAL_CHARSHTML-encodes '"<>& and characters below ASCII 32
FILTER_SANITIZE_FULL_SPECIAL_CHARSEquivalent to htmlspecialchars() with ENT_QUOTES
FILTER_SANITIZE_ADD_SLASHESApplies addslashes() (PHP 7.3+)
FILTER_UNSAFE_RAWDoes nothing by default; flags can strip low/high characters

Deprecated: FILTER_SANITIZE_STRING and FILTER_SANITIZE_STRIPPED were deprecated in PHP 8.1. They tried to strip tags and encode quotes, which was confusing and insufficient for security. Use htmlspecialchars() when outputting, and strip_tags() only if you really need plain text.

Extracting a Number From Formatted Input

<?php
$price = filter_var('₹1,299.50', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);

var_dump($price);
var_dump(filter_var($price, FILTER_VALIDATE_FLOAT));

Output

string(7) "1299.50"
float(1299.5)

The sanitizing filter removes the currency symbol and thousands separator (commas are removed unless FILTER_FLAG_ALLOW_THOUSAND is set), and the validation filter then converts the string to a real float — or returns false if the result is still not a valid number. Sanitize first, then validate.


Useful Normalizations

Most real-world sanitizing is simple normalization with string functions.

Whitespace

<?php
function normalizeSpaces(string $value): string
{
    return preg_replace('/\s+/u', ' ', trim($value)) ?? '';
}

var_dump(normalizeSpaces("  Meena \t  Raj \n "));

Output

string(9) "Meena Raj"

Leading and trailing whitespace is removed, and internal runs of spaces, tabs, or newlines become single spaces. Use this for names, titles, and similar single-line fields — not for passwords or multi-line text such as addresses and messages.

Phone Numbers

<?php
function normalizeIndianMobile(string $input): ?string
{
    $digits = preg_replace('/\D+/', '', $input) ?? '';

    if (strlen($digits) === 12 && str_starts_with($digits, '91')) {
        $digits = substr($digits, 2);
    } elseif (strlen($digits) === 11 && str_starts_with($digits, '0')) {
        $digits = substr($digits, 1);
    }

    return preg_match('/^[6-9]\d{9}$/', $digits) === 1 ? $digits : null;
}

foreach (['+91 98765-43210', '098765 43210', '(987) 654-3210', '12345'] as $input) {
    echo str_pad($input, 17) . var_export(normalizeIndianMobile($input), true) . "\n";
}

Output

+91 98765-43210  '9876543210'
098765 43210     '9876543210'
(987) 654-3210   '9876543210'
12345            NULL
  1. Every non-digit is removed, so spaces, hyphens, brackets, and + disappear.
  2. A country code (91) or a leading trunk 0 is removed.
  3. The result is validated; invalid numbers return null instead of a "cleaned" wrong value.

Storing phone numbers in one consistent format makes searching, de-duplication, and sending SMS messages reliable.

Case

<?php
echo mb_strtolower('  Admin@Example.COM ') . "\n";
echo mb_convert_case('meena raj', MB_CASE_TITLE) . "\n";

Output

  admin@example.com 
Meena Raj

Normalize case for values compared case-insensitively (usernames, tags, codes). Be careful with names: forcing title case turns "McDonald" or "van der Berg" into incorrect forms, so it is usually better to keep names as typed.


strip_tags() — Removing HTML

<?php
$comment = '<b>Hello</b> <script>alert(1)</script>';

var_dump(strip_tags($comment));
var_dump(strip_tags('<p>Use <b>bold</b> and <i>italic</i>.</p>', '<b><i>'));

Output

string(14) "Hello alert(1)"
string(34) "Use <b>bold</b> and <i>italic</i>."
  • strip_tags() removes tags but keeps the text inside them — including the contents of <script>.
  • The second argument allows specific tags. However, allowed tags keep all their attributes, so <b onmouseover="..."> would remain dangerous.

strip_tags() is not an XSS defense. For plain text, store the text as entered and escape it with htmlspecialchars() when displaying it. For user-supplied rich text (formatted comments, blog posts), use a dedicated HTML sanitizer library such as HTML Purifier or Symfony HtmlSanitizer, which parse the HTML and keep only safe tags and attributes.


What Sanitizing Must Not Replace

ThreatCorrect Defense
SQL injectionPrepared statements with bound parameters — never addslashes() or escaping by hand
XSS (HTML output)htmlspecialchars() at output time, or an auto-escaping template engine
Command injectionAvoid shell commands; if unavoidable, escapeshellarg()
Invalid dataValidation with clear error messages

Practical Example: Normalizing a Profile Form

<?php
function normalizeProfile(array $input): array
{
    $text = fn(string $key): string => is_string($input[$key] ?? null) ? $input[$key] : '';

    $email = trim($text('email'));
    $at = strrpos($email, '@');

    return [
        'name' => preg_replace('/\s+/u', ' ', trim($text('name'))) ?? '',
        'email' => $at === false ? $email : substr($email, 0, $at) . '@' . strtolower(substr($email, $at + 1)),
        'phone' => preg_replace('/\D+/', '', $text('phone')) ?? '',
        'bio' => mb_substr(trim(strip_tags($text('bio'))), 0, 200),
        'website' => trim($text('website')),
    ];
}

$submitted = [
    'name' => "  Meena   Raj ",
    'email' => ' Meena@Example.COM ',
    'phone' => '98765-43210',
    'bio' => '<b>PHP</b> developer from <i>Madurai</i>.',
    'website' => ' https://example.com/meena ',
];

var_export(normalizeProfile($submitted));
echo "\n";

Output

array (
  'name' => 'Meena Raj',
  'email' => 'Meena@example.com',
  'phone' => '9876543210',
  'bio' => 'PHP developer from Madurai.',
  'website' => 'https://example.com/meena',
)

Step-by-Step Explanation

  1. The $text helper reads each field as a string, ignoring unexpected arrays.
  2. Names are trimmed and internal whitespace is collapsed.
  3. The email domain is lowercased; the local part is kept as typed.
  4. The phone number is reduced to digits.
  5. The bio is limited to plain text and 200 characters (mb_substr() counts characters, not bytes).
  6. The website is trimmed.

The normalized values are then validated (email format, phone pattern, allowed URL schemes) as shown in the previous lessons — normalization makes validation more forgiving of formatting differences, but it never replaces it.


Common Mistakes

Using Sanitizing Instead of Validation

Effect: Invalid input is silently changed into different, wrong values.

Fix: Sanitize lightly, then validate and report errors.

Escaping on Input

Effect: & and ' end up in the database, then get escaped again on output (&), and break CSV exports and APIs.

Fix: Store raw (validated) data; escape when outputting.

Using FILTER_SANITIZE_STRING

Effect: Deprecation notices and inconsistent behavior.

Fix: Use htmlspecialchars() on output or strip_tags() for plain text.

Trusting strip_tags() for Security

Effect: Attributes on allowed tags and leftover script text remain.

Fix: Escape plain text; use an HTML sanitizer for rich text.

Trimming or Altering Passwords

Effect: Users cannot log in with the password they chose.

Fix: Never sanitize passwords; hash them exactly as entered.


Best Practices

  • Normalize formatting (whitespace, case, separators) where it helps consistency.
  • Always validate after sanitizing, and reject values that cannot be fixed.
  • Store validated raw data and escape it for each output context.
  • Use prepared statements for SQL and a dedicated sanitizer for rich HTML.
  • Leave passwords and free-form text as the user entered them.

Official reference: https://www.php.net/manual/en/filter.filters.sanitize.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Home PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement PHP Home PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope PHP Casting Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence Continue Statement Modify Strings PHP If...Else...Elseif PHP If Modify Strings PHP If Operators PHP Functions Concatenate Strings PHP If...Else Slicing Strings User-defined Functions Slicing Strings PHP Shorthand if Escape Characters Default Argument Values PHP Nested if Pass by Reference String Interpolation Named Arguments PHP File Upload Variadic Functions Return Values Search in Strings Multibyte Strings Type Declarations in Functions PHP Numbers PHP Math PHP Floats PHP Random Numbers PHP Constants PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Cookies PHP Destructor PHP Access Modifiers Readonly Properties PHP Sessions PHP Inheritance Method Overriding PHP Filters The final Keyword CSRF Protection PHP Filters Advanced Session Security Secure Cookies PHP Magic Constants File Upload Security PHP Callback Functions PHP Operators Filesystem Security PHP JSON Arithmetic Operators Error Reporting in Production Hiding PHP Assignment Operators PHP Configuration (php.ini) Comparison Operators PHP Command Line (CLI) PHP Exceptions Increment / Decrement Operators Migrating to PHP 8 PHP Form Validation PHP Form Required PHP Form URL/E-mail Error Handling Form Input Sanitizing Escaping Output (htmlspecialchars) Custom Error Handler Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators
Ask about this post
AI Ask about this post

Ask questions about Form Input Sanitizing and get answers drawn from it.

Signed-in readers only.