HOWTO · PHP

How to Sanitize Input in PHP

Choose PHP input handling for the field, output context, or database operation instead of relying on a universal sanitizer.

On this page

There is no universal step that makes every untrusted value safe. Decide what the value represents, validate it against that requirement, normalize it only when the application has a clear rule for doing so, encode it for the context where it will be displayed, and use parameterized queries when sending it to a database. These operations solve different problems: validation accepts or rejects a value, sanitization transforms it, and output encoding represents characters safely for a particular context. None of them alone guarantees data integrity or protects every use of a value.

What sanitizing PHP input can and cannot do

Input handling starts with the field’s contract. An age, email address, display name, and search term have different valid forms. Validation checks whether a value meets that contract; normalization makes an intentional, documented transformation such as trimming surrounding whitespace. A sanitizer may remove or transform characters, but that can silently change what a user submitted and does not make the result suitable for every later use.

Keep the original value separate from any normalized or encoded representation when the application needs to retain it. Do not remove characters merely because they look unusual: names and other legitimate text can contain punctuation or non-ASCII characters. Choose handling at the point of use as well. HTML output needs HTML encoding, while SQL values need query parameters. Those protections are not interchangeable.

Escape HTML when displaying user input

Encode text when inserting it into an HTML text node or a quoted attribute. For ordinary HTML output, htmlspecialchars() converts characters with HTML meaning, including ampersands, angle brackets, and quotes when the appropriate flags are used. htmlentities() also encodes characters that have named HTML entities. Neither function is a general-purpose HTML sanitizer: encoding a value for a text node does not make it safe to insert into JavaScript, CSS, a URL, or raw HTML markup. Use the encoder and rules for the exact output context.

This self-contained example encodes a name for an HTML text node:

<?php
$name = 'Ada & Sam';
echo htmlspecialchars($name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), PHP_EOL;
Ada &amp; Sam

The supplied runtime evidence confirms this output. It is a string intended for an HTML text context, not a value to reuse as SQL or JavaScript.

Validate and normalize input with filter_var()

filter_var() applies a selected validation or filtering operation; it is not an HTML sanitizer. For example, filter_var($email, FILTER_VALIDATE_EMAIL) returns the accepted email value or false when it does not match the filter. filter_var($count, FILTER_VALIDATE_INT) can validate an integer, with options available when the application needs a particular range. Check the return value explicitly, since false indicates validation failure.

Sanitizing filters can transform input rather than prove that it is valid. FILTER_SANITIZE_EMAIL, for instance, removes characters that are not allowed by that filter; it does not establish that the resulting address belongs to a user or can receive mail. If the application chooses to normalize input, define the rule and then validate the result. Avoid relying on FILTER_SANITIZE_STRING as a general solution; removing markup does not provide context-appropriate output encoding or make arbitrary content safe.

Use prepared statements for SQL

Use parameterized queries to keep SQL syntax separate from user-supplied values. With PDO, prepare a query containing a placeholder and pass the value separately when executing it. For example, the pattern is $statement = $pdo->prepare('SELECT id, email FROM Users WHERE lastname = :lastname'); followed by $statement->execute(['lastname' => $lastname]);. This is an illustrative fragment: $pdo must already be connected to the intended database, and the database service and schema are outside this example.

PDO does not sanitize arbitrary input. Parameter binding is the protection against SQL injection for values in the query; it does not validate that a value makes sense for the application. Validate values according to their field rules, and use a separate query construction strategy for identifiers such as table or column names, which cannot generally be supplied as value parameters. MySQLi also supports prepared statements; use its parameter-binding API when working with that interface.

Handle profile fields by their expected type

Apply a distinct rule to each profile field. Validate an email address and confirm ownership through an application flow if needed; trim a display name only if that is the intended policy; validate a postal code against the relevant region rather than assuming one global format. For a numeric field, parse and check the allowed range before using it. Preserve legitimate punctuation and Unicode where the field permits them.

When showing stored profile values in a page, encode them at output time for the specific HTML context, even if they were validated when submitted. When querying for a profile, pass values through prepared statements. Keeping validation, normalization, database parameterization, and output encoding as separate decisions makes the handling easier to reason about and prevents one transformation from being mistaken for universal protection.