Of course, validating user input is really important for dynamic websites. Invalid user input can make errors in processing. Therefore, validating inputs is a must. The awesome language, PHP has numerous in-built functions to validate user inputs.
In this tutorial, you will learn about 4 major tasks.
Before creating a HTML form you have to decide a HTTP method to use in your HTTP request. Among bunch of HTTP request methods, developers normally use GET and POST methods for forms. So... GET or POST?
If you are sending sensitive data such as passwords, emails with HTTP request you must use POST. If you are retrieving data from the server, you can use GET method.
Let's create the HTML form. Here I have chosen POST method and the action script, act.php
<form method="POST" action="act.php">
<!-- some form elements here -->
</form>
Browser will send the form data to act.php after submitting the form. I have created act.php as following. First, it will validate the request method.
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// the request method is fine
} else {
exit('Invalid Request');
}
You can change 'POST' with your selected HTTP method. So, if act.php is requested with any other method, it will show an error. That's how the request method validation is done.
Next, we have to check the user inputs to avoid processing errors. Let's see how an error can occur. Assume that you have php code to assign POST variable to a local variable as following.
<?php
$email = $_POST['email'];
If email variable is not set, PHP will throw an error like following.
Undefined Index: Email
Therefore we have to check whether the inputs variables are set.
The empty function in PHP is really important in this case. It checks whether the argument is empty or not. It will return true in following cases.
if (!empty($_POST['email'])) {
$email = $_POST['email'];
}
In the above example, $email variable is declared if $_POST['email'] is not empty. So, the error mentioned earlier won't trigger. But, if the email is compulsory, we have to throw an error if it's empty. The last subtopic of this tutorial will explain you to do that in an object oriented way.
The isset function is better to use for boolean values because empty function returns true on false. Isset function checks whether the variable is set (or declared) and not null.
if (isset($_POST['boolean'])) {
$boolean = $_POST['boolean'];
}
First, we have to prevent XSS attacks (Cross-Site Scripting). Assume that we have following code in our HTML page to let users to input their username.
<form method="POST" action="">
<input type="text" name="username">
<input type="submit" name="submit">
</form>
Now assume an attacker inputs following HTML code as the username.
<script>location.href='https://www.attacker.com'</script>
Then he submits the form. We save his username in the database without any validation. Then, we make a page to show usernames of the users. So, PHP will echo out above HTML code as his username. So, every user who visits this page will be redirected to https://www.attacker.com. Simply, this is called as XSS attacks.
It's pretty simple to protect a website from XSS attacks using PHP. The htmlspecialchars() function escapes HTML codes. So,
<script>location.href='https://www.attacker.com'</script>
will be changed to
<script>location.href='https://www.attacker.com'</script>
Let's see an example:
<?php
if (!empty($_POST['username']) && !empty($_POST['email'])) {
$username = htmlspecialchars($_POST['username']);
$email = htmlspecialchars($_POST['email']);
}
There is one more thing to do with user inputs. We need to remove extra spaces and padding. So that extra spaces won't take space in your database if you are saving those inputs in a database. trim() function removes extra spaces.
<?php
if (!empty($_POST['username']) && !empty($_POST['email'])) {
$username = trim(htmlspecialchars($_POST['username']));
$email = trim(htmlspecialchars($_POST['email']));
}
Note: We will create a function to do both at once in the last part of this tutorial.
PHP has filter_var() function to validate variables. We can set it's second parameter to different values and use it to validate emails, URLs, integers, booleans, etc. This function returns false on failure or invalid input.
1. Validating Emails
We can simply validate an email using filter_var() function and FILTER_VALIDATE_EMAIL flag. It returns false if the email is invalid.
<?php
if (!empty($_POST['email'])) {
$email = trim(htmlspecialchars($_POST['email']));
$email = filter_var($email, FILTER_VALIDATE_EMAIL);
if ($email === false) {
exit('Invalid Email');
}
}
2. Validating URLs
Here we use FILTER_VALIDATE_URL flag with filter_var() function. It returns false if the URL is not in the correct format and returns the URL on success.
<?php
if (!empty($_POST['url'])) {
$url = trim(htmlspecialchars($_POST['url']));
$url = filter_var($url, FILTER_VALIDATE_URL);
if ($url === false) {
exit('Invalid URL');
}
}
3. Validating Integers
Here we use FILTER_VALIDATE_INT flag with filter_var() function. This method can be used to validate any integer value such as a primary integer key (userId, groupId, etc.) in database, timestamp, etc. The advantage of using this function is, it converts string numbers ("25") to actual integers (25). So that we can treat integer inputs as integer without any hesitation after sending the input through this function.
<?php
if (!empty($_POST['number'])) {
$number = $_POST['number'];
$number = filter_var($number, FILTER_VALIDATE_INT);
if ($number === false) {
exit('Invalid Integer');
}
}
When sending an input through the function,
Note: All false values means that they are not integers.
4. Validating Booleans
Here we use FILTER_VALIDATE_BOOLEAN flag with filter_var() function. This flag enables some amazing attributes to the function. It returns true on strings like 'on', 'yes', 'true' (Case-Insensitive), on boolean true. All other inputs will return false.
Many browsers send string "on" if a checkbox is ticked by user. This string is hard to work with. Let's see an example how to convert it to a boolean.
<?php
if (!empty($_POST['check'])) {
$check = $_POST['check'];
$check = filter_var($check, FILTER_VALIDATE_BOOLEAN);
}
After sending the input through filter_var() function with FILTER_VALIDATE_BOOLEAN flag, "on" (string) will be converted to true. Thereafter, we can treat the input as a boolean.
We have discussed many functions to validate inputs. But, writing them all over and over again is not a good practice. So, in the next step we will be creating a class to validate inputs in a more convenient way.
I assume that you have basic knowledge on Object Oriented Programming. If not, you can follow our tutorial.
Our class must prevent XSS attacks and validate inputs. I have named the class as Input.
<?php
class Input {
}
I have used static functions for each case as they make it easy to call. It has following functions.
So, the full code will be like following.
<?php
class Input {
static $errors = true;
static function check($arr, $on = false) {
if ($on === false) {
$on = $_REQUEST;
}
foreach ($arr as $value) {
if (empty($on[$value])) {
self::throwError('Data is missing', 900);
}
}
}
static function int($val) {
$val = filter_var($val, FILTER_VALIDATE_INT);
if ($val === false) {
self::throwError('Invalid Integer', 901);
}
return $val;
}
static function str($val) {
if (!is_string($val)) {
self::throwError('Invalid String', 902);
}
$val = trim(htmlspecialchars($val));
return $val;
}
static function bool($val) {
$val = filter_var($val, FILTER_VALIDATE_BOOLEAN);
return $val;
}
static function email($val) {
$val = filter_var($val, FILTER_VALIDATE_EMAIL);
if ($val === false) {
self::throwError('Invalid Email', 903);
}
return $val;
}
static function url($val) {
$val = filter_var($val, FILTER_VALIDATE_URL);
if ($val === false) {
self::throwError('Invalid URL', 904);
}
return $val;
}
static function throwError($error = 'Error In Processing', $errorCode = 0) {
if (self::$errors === true) {
throw new Exception($error, $errorCode);
}
}
}
Let's see some examples of usage of our class.
You can copy the above code to a new file and include that file in your script. If you are interested in autoloading classes, you can check our tutorial.
As in the above code, I have created the method throwError to throw errors. It throws error if the static variable error is true. If you don't need errors to be thrown, you can set error to false.
Input::$error = false;
I have created check function to check inputs. There are two arguments in the function. First one is an array of elements that is needed to be checked. Second one is the Super Global Array that holds the Inputs. ($_POST for POST method, $_GET for GET method. Default is $_REQUEST)
Input::check(['email', 'password'], $_POST);
This code will check whether email and password are in $_POST and they are not empty. If they are empty it will throw an error.
You can use other functions in the class to validate followings.
// validate an integer
$number = Input::int($_POST['number']);
// validate a string
$name = Input::str($_POST['name']);
// convert to boolean
$bool = Input::bool($_POST['boolean']);
// validate an email
$email = Input::email($_POST['email']);
// validate a URL
$url = Input::url($_POST['url']);
This tutorial showed you how to check and validate user inputs and prevent XSS attacks. The filter_var() function was described with it's filters with examples. This tutorial gained your knowledge on validating emails, URLs, integers, booleans and more. Finally we created a class to make validating more convenient. You can improve that class with your knowledge and make it more functional according to your needs.
If you have any kind of question to ask, comment below. Thank you for reading.