php form handling


The PHP superglobals $_REQUEST, $_GET and $_POST are used to collect form-data. When a user fills out the form and clicks the submit button, the form data is sent for processing to a PHP file stated in action attribute. If there's no action attribute in the form, the data will be preocessed in the same page. The form data is sent with the HTTP POST method. To display the submitted data you could simply echo all the variables. Here's a demo of a form.

Male Female
Nepali English Others
<form method="post">
	<div class="form-group">
		<label>Name</label>
		<input type="text" name="name">
	</div>

	<div class="form-group">
		<label>Gender</label>
		<input type="radio" name="gender" value="male"> Male
		<input type="radio" name="gender" value="female"> Female
	</div>

	<div class="form-group">
		<label>Language</label>
		<input type="checkbox" name="nepali" value="nepali"> Nepali
		<input type="checkbox" name="english" value="english"> English
		<input type="checkbox" name="others" value="others"> Others
	</div>

	<div class="form-group">
		<label>Country</label>
		<select name="country">
			<option value="nepal">Nepal</option>
			<option value="others">Others</option>
		</select>
	</div>

	<div class="form-group">
		<input type="submit" name="submit" value="Submit">
	</div>
</form>

Once the form is submitted, all the data will be retrieved with the codes below.

<?php
if(!empty($_POST) && $_SERVER['REQUEST_METHOD'] === 'post'){
	$name = $_POST['name'];
	$gender = $_POST['gender'];
	$country = $_POST['country'];

	if(isset($_POST['nepali'])){
		$nep = $_POST['nepali']
	}else{
		$nep = '';
	}

	if(isset($_POST['english'])){
		$eng = $_POST['english']
	}else{
		$eng = '';
	}

	if(isset($_POST['others'])){
		$oth = $_POST['others']
	}else{
		$oth = '';
	}

	echo $name . $gender . $country . $nep . $eng . $oth
}	
?>

This option makes the checkbox values empty at first. If those keys get some values they will be replaced else will be empty.

<?php
if(!empty($_POST) && $_SERVER['REQUEST_METHOD'] === 'post'){
	$name = $_POST['name'];
	$gender = $_POST['gender'];
	$country = $_POST['country'];
	$nep = '';
	$eng = '';
	$oth = '';

	if(isset($_POST['nepali'])){
		$nep = $_POST['nepali'];
	}

	if(isset($_POST['english'])){
		$eng = $_POST['english'];
	}

	if(isset($_POST['others'])){
		$oth = $_POST['others'];
	}
}
	echo $name . $gender . $country . $nep . $eng . $oth
?>

Next option would be to give same name to checkboxes but define the checkbox name as array as shown below.

<div class="form-group">
	<label>Language</label>
	<input type="checkbox" name="lang[]" value="nepali"> Nepali
	<input type="checkbox" name="lang[]" value="english"> English
	<input type="checkbox" name="lang[]" value="others"> Others
</div>

This will store the selected values in lang[] as shown below.

[lang] => Array
	(
		[0] => nepali
		[1] => english
		[2] => others
	)

Then the process required to prepare data for further processing is implode().

<?php
$language = $_POST['lang'];
$language = implode(',',$language);
echo $language;
?>

Result = nepali,english,others

File Uploads

For file uploads, the method to send data must be post and enctype information should also be added as the file will have multiple information.

<form method="post" enctype="multipart/form-data">
	<div class="form-group">
		<input type="file" name="upload">
	</div>
	<div class="form-group">
		<input type="submit" value="Upload" class="btn btn-sm btn-success">
	</div>
</form>

Now, the processing part. Let's have a look at all those informations that are passed while uploading files using print_r() function.

<?php
	echo "<pre>";
	print_r($_FILES);
	echo "</pre>";
?>

Result:

[upload] => Array
	(
		[name] => filename.extension
		[type] => filetype
		[tmp_name] => temporary location of file
		[error] => error number
		[size] => file size in bytes
	)

Now, we have all the informations regarding file being uploaded, no we can move the file from temporary location to permanent location.

<?php
if(!empty($_FILES)){
	$name = $_FILES['upload']['name'];
	$tmpName = $_FILES['upload']['tmp_name'];
	$error = $_FILES['upload']['error'];

	// create folder path
	$path = "Uploads/".$name;

	if($error == 0){
		move_uploaded_file($tmpName, $path);
	}else{
		echo 'Unable to uplaod file.';
	}
}
?>

Unique Filename

The file is uploaded now but what if another file with the same is uploaded? The existing file would be overwritten by the new one. That's why, we need to make the filename unique for each uploaded files.

<?php 
$fname = md5(time().rand());
$name = $fname.$name;
$path = "Uploads/".$name;
?>

Here, time() adds current timestamp and rand() generates a random number. md5 encrypts the number created. That helps the name become unique each time a filename is generated. Then, we can concatenate the random name along with the filename to create a new name or we can retrieve the file extension and concatenate it with the random name to create a new name.

Retrieving file extension

<?php
$ext = (pathinfo($name,PATHINFO_EXTENSION));
$fname = md5(time().rand()).'.'.$ext;
$path = 'Uploads/'.$fname;
?>

We can display the related error message while there is a problem in uploading using if else but the code would be too long. The easiest option would be to store all the error messages in an associative array and then print the specific one whenever there's an error by adding this variable uptop.

<?php
	$errorMsg = [
		1 => 'file size larger than maximum filesize allowed to upload',
		2 => 'maximum upload size',
		3 => 'partial upload',
		4 => 'no file',
		6 => 'no temporary directory',
		7 => 'can\'t write to disk',
		8 => 'upload stopped by extension'
	]

	if($error == 0){
		if(move_uploaded_file($tmpName, $path)){
		$message = 'File uploaded successfully';
	}else{
		$message = $errorMsg[$error];
	}
}

<?=$message?>
?> 

Multiple Files Upload

<form method="post" enctype="multipart/form-data">
	<input type="file" name="upload[]" multiple="">
	<input type="submit" value="Upload">
</form>
<?php
if(!empty($_FILES)){
	$files = $_FILES['upload'];

	foreach($files as $i => $f){
		$name = $f['name'][$i];
		$error = $f['error'][$i];
		$tmp = $f['tmp_name'][$i];

		$fname = md5(time().rand());
		$name = $fname.$name;
		$path = 'Uploads/'.$name;

		move_uploaded_file($name, $path);
	}
}
?>

Include and Require

include() is highly useful to add same sections in multiple pages with a single code rather than writing same block of codes in each page.

Syntax

include('path/filename');

require() also does the same. The only difference is include doesn't stop the further execution of the program while require terminates the execution of codes if the stated file is not found. both of them can be used as include_once() or required_once() to import other sections only once in a file.

Header

header() redirects a user from one page to another.

Syntax

header('Location: path/filename');