Introduction
An essential task for most web applications is the ability to take user input. We will look at several common tasks in PHP like:
- How to access GET query parameters from the URL
- How to use forms to submit GET and POST values
- Understanding the security implications of accepting user data and how to protect yourself
- Creating a form to submit GET or POST requests
- Handling checkbox and multi-select fields
- Handing file uploads
Important security concerns
Before we look at accepting and processing user input, it is very important to be aware of the security risks involved.
There is one rule to remember: Never trust user input.
- If you output any of the data back to the web page, you open yourself up to cross-site scripting (XSS) attacks and potential cross-site request forgery (CSRF) attacks.
- If you use the input as part of a file path you open yourself up to local and remote file inclusion attacks (LFI/RFI).
- If you use the data in a database query, you risk SQL injection that can corrupt your database, cause data loss, or even expose sensitive data.
- If the data is logged it could lead to log tainting that could lead to exploitation.
- Users can send any data they want and are not only limited to the options you provided in the form.
Always sanitize and validate user input
If you output the user input (also called "reflecting") be sure to sanitize any HTML or script elements. This is also called "escaping" the text. You can use the htmlspecialchars() for this.
If you store the user input in a database, be sure you use a prepared statement and never use the data to create a raw string query.
If you use the user input as part of a file path for loading a file or accessing a URL,
you must be very careful to ensure there is no directory traversal. Ensure users cannot use
../
, absolute paths, or other directory manipulation techniques. Be sure
that a user cannot manipulate the input to access a directory or file they are not supposed to.
One function to assist with that is basename().
Using GET method
With GET, the parameters are passed in the URL and available via $_GET
.
This is convenient when you want the data exposed.
It is particularly useful if you want someone to be able to bookmark the URL.
For example if it is a search query that they want to bookmark or share.
It is a bad idea for forms with sensitive information like passwords
or credit card numbers. The password would be visible in the URL
and could even be stored in the browser history.
Web servers also tend to log the URL being accessed which would include
the data, but they don't typically log the POST content.
Example url with GET parameters:
http://localhost:8000/index.php?some_key=some_value&other_key=other_value
You can manually craft a URL with the GET query parameters
or you can use a form with method="GET"
like this:
<html>
<body>
<form method="GET">
<input type="text" name="my_field" value="some text" />
<input type="submit" value="Submit" />
</form>
</body>
</html>
You can access the GET query parameters with a special constant named $_GET
.
Here is an example:
<html>
<body>
<?php
if (isset($_GET['my_field'])) {
// Exists
echo "Value provided: " . $_GET['my_field'];
} else {
// Does not exist
echo 'No value provided.';
}
?>
<form method="GET">
<input type="text" name="my_field" value="some text" />
<input type="submit" value="Submit" />
</form>
</body>
</html>
Using POST method
Post is more secure than GET because it is not exposed in the URL.
Data is available via $_POST
It is still part of the HTTP request though and is passed in plain-text
unless you are explicitly using SSL/TLS.
The POST content is passed in the body of the request as opposed to
the header like a GET request.
POST is the method you want to use for passwords and other
data you do not want in the visible URL.
<html>
<body>
<?php
if (isset($_POST['my_field'])) {
// Exists
echo "Value provided: " . $_POST['my_field'];
} else {
// Does not exist
echo 'No value provided.';
}
?>
<form method="POST">
<input type="text" name="my_field" value="some text" />
<input type="submit" value="Submit" />
</form>
</body>
</html>
Handling checkboxes and mutli-select fields
Any field that can have multiple selections will return an array with all of the values.
<?php
foreach ($_POST['my_checkboxes'] as $checkbox_value) {
echo $checkbox_value;
}
In the HTML forms, checkbox names have square brackets like this:
<input type="checkbox" name="my_checkboxes[]" value="A" />
<input type="checkbox" name="my_checkboxes[]" value="B" />
<input type="checkbox" name="my_checkboxes[]" value="C" />
Multi-select fields look like this:
<select name="my_multiselect" multiple="multiple">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
Handling file uploads
A common task with forms is to upload a file. There are a couple things to be aware of when you want to upload a file
- The form needs to be POST method
- The form needs to have the propery
enctype="multipart/form-data"
- The
file_uploads
setting must beOn
in the server'sphp.ini
file. This is usually on by default already. - The input field should be of type
file
Here is an example:
<form method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name="my_file">
<input type="submit" value="Submit">
</form>
You can also submit multiple files as an array:
<form method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name="my_files[]">
<input type="file" name="my_files[]">
<input type="file" name="my_files[]">
<input type="submit" value="Submit">
</form>
In the PHP backend, you won't access this file via $_POST
.
Instead, you will use the constant $_FILES
. $_FILES
is an
associative array with keys named after the file input name.
Each file will have a few values:
name
- Original filename that user named ittype
- MIME type, like "text/plain".size
- Number of bytestmp_name
- The path to the temporary file uploaded to the servererror
- If there was any error
For example, we could access $_FILES['my_file']['tmp_name']
.
Typically you will move the temporary file to a permanent location on the server. You can do this with the move_uploaded_file() function.
For example:
move_uploaded_file($_FILES['my_file']['tmp_name'], __DIR__ . '/uploads/file.txt')
To learn more about files and directories in PHP check out my tutorial, Working with Files and Directories with PHP.
Conclusion
After reading this you should be feel comfortable doing the following in PHP:
- How to access GET query parameters from the URL
- How to use forms to submit GET and POST values
- Understanding the security implications of accepting user data and how to protect yourself
- Creating a form to submit GET or POST requests
- Handling checkbox and multi-select fields
- Handing file uploads