Web Development

Cookies

To create cookies, use the setcookie function.

<?php
	// creates a temporary cookie
	setcookie('cookie_name', 'cookie_value');
?>
<?php
	// creates a permanent cookie
	setcookie('cookie_name', 'cookie_value', 2147483646);
	// 2147483646 is the expiration time and this makes it practically permanent
?>
<?php
	// creates the same cookie but for pages that begin with '/path/'
	setcookie('cookie_name', 'cookie_value', 2147483646, '/path/');
?>
<?php
	// creates the same cookie but for the domain www.acme.com
	setcookie('cookie_name', 'cookie_value', 2147483646, '/path/', 'www.acme.com');
?>
<?php
	// creates the same cookie except it will only be sent over SSL connections
	setcookie('cookie_name', 'cookie_value', 2147483646, '/path/', 'www.acme.com', true);
?>

To read a cookie use the $_COOKIE array.

<?php
	if (isset($_COOKIE['cookie_name'])) {
		 print $_COOKIE['cookie_name'];
	}
?>

To loop through all the cookies, use a foreach loop.

<?php
	foreach ($_COOKIE as $name => $value) {
		 print "$name = $value<br />";
	}
?>

To delete cookies, use the setcookie function. Do not specify a value for the cookie and set expiration time to 1.

<?php
	// deletes a cookie
	setcookie('cookie_name', '', 1);
?>

Cookie Authentication

Use cookies to store authentication information which can be verified to know that the current user is logged in. The key to making this work is the secret code.

<?php
$script = $_SERVER['SCRIPT_NAME'];
$secret_code = '8d10db78cd374e87bccb306f0b8848b2'; // this should be unique to each site
print '<html><head><title>LOGIN EXAMPLE</title></head><body>';
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
	if (isset($_GET['logout'])) {

		setcookie('auth', '', 1);
		print '<p>You have been logged out. <a href="'.$script.'">login</a></p>';

	} else if (isset($_COOKIE['auth'])) {

		list($cookie_username, $cookie_hash) = split(',', $_COOKIE['auth']);
		// using secret code
		if(md5($cookie_username.$secret_code) == $cookie_hash) {
			print '<p>'.htmlentities($cookie_username).', you can <a href="'.$script.'?logout=">logout</a></p>';
		} else {
			print '<p>oops... bad cookie</p>';
		}

	} else {
		// draw the login form
		print '<form method="post" action="'.$script.'">';
		print '<input type="text" name="username" placeholder="enter username" /><br />';
		print '<input type="password" name="password" placeholder="enter password" /><br />';
		print '<input type="submit" value="login" />';
		print '</form>';
	}

} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {

	$fieldspresent = (isset($_POST['username']) & isset($_POST['password']));

	if ($fieldspresent) {

		$username = $_POST['username'];
		$password = $_POST['password'];

		if ($username != '' && $password != '') {
			// setcookie() uses md5() to create the hash using the secret code
			setcookie('auth', $username.','.md5($username.$secret_code));
			print '<p>Hello, '.htmlentities($username).'! <a href="'.$script.'">refresh</a></p>';

		} else {
			print '<p>Login failure <a href="'.$script.'">back</a></p>';
		}

	} else {
		print '<p>POST error</p>';
	}

}
print '</body></html>';
?>

A class doing the authenticating cleans up the code considerably.

<?php
class Auth {
	private $loggedin;

	public function logged_in() {
		return $this->loggedin;
	}

	protected function is_validated($username, $password) {
		// normally, check a database for this user
		if (isset($username) & isset($password)) {
			if ($username != '' && $password != '') {
				return true;
			}
		}
		return false;
	}

	public function __construct($username, $password, $method) {
		$secret_code = '8d10db78cd374e87bccb306f0b8848b2';
		$this->loggedin = false;
		if ($method == 'GET') {
			if (isset($_GET['logout'])) {
				setcookie('auth', '', 1);
			} else if (isset($_COOKIE['auth'])) {
				list($cookie_username, $cookie_hash) = split(',', $_COOKIE['auth']);
				if(md5($cookie_username.$secret_code) == $cookie_hash) {
					$this->loggedin = true;
				}
			}
		} else if ($method == 'POST') {
			if ($this->is_validated($username, $password)) {
				setcookie('auth', $username.','.md5($username.$secret_code));
				$this->loggedin = true;
			}
		}
	}
}

$script = $_SERVER['SCRIPT_NAME'];
$auth = new Auth($_POST['username'], $_POST['password'], $_SERVER['REQUEST_METHOD']);
if ($auth->logged_in()) {
	page_header();
	print '<p>Hello, '.htmlentities($_POST['username']).', you can <a href="'.$script.'?logout=">logout</a></p>';
	page_footer();
} else {
	page_header();
	page_loginform();
	page_footer();
}

function page_header() { ?>
<html>
	<head>
		<title>LOGIN EXAMPLE</title>
	</head>
	<body>
<?php
}

function page_loginform() { ?>
<form method="post" action="<?php echo $script ?>">
	<input type="text" name="username" placeholder="enter username" /><br />
	<input type="password" name="password" placeholder="enter password" /><br />
	<input type="submit" value="login" />
</form>
<?php
}

function page_footer() { ?>
	</body>
</html>
<?php
}
?>

Query Strings

Construct a query string based on an array. Use the http_build_query function to encode the string for use in a URI.

<?php
	$arr = array('first_name' => 'John', 'last_name' => 'Smith', 'age' => 25, 'address' => '123 Abc Ln');
	$query_str = http_build_query($arr);
	$url = '/index.php?'.$query_str;
	print '<a href="'.$url.'">click here</a>';
?>

Access the Body of a Request

This is raw data read from php://input which is a stream.

<?php
	$request_body = file_get_contents('php://input');
	print $request_body;
?>

HTTP Headers

To read an HTTP header, use getallheaders.

<?php
$headers = getallheaders();
print '<pre>';
	foreach($headers as $key => $value) {
		print "$key => $value\r\n";
	}
print '</pre>';
?>

To set an HTTP header, use header.

<?php
	header('Content-Type: image/gif');
?>

Redirect to a New URI

Use the header function to set the Location header.

<?php
	header('Location: http://www.prowaretech.com/');
	exit(); // exit so as to stop sending any other data to the browser
?>

Compress Web Output

Modify the php.ini file to have this line.

zlib.output_compression_level=5 ; choose a compression level between 1 and 9

Form Validation

Checking Date/Time

To check a certain date is valid use checkdate.

<?php
	$valid = checkdate($POST['month'], $_POST['day'], $_POST['year']);
	if($valid) {
		print $POST['month'].'/'.$_POST['day'].'/'.$_POST['year'];
	} else {
		print 'not a valid date';
	}
?>

Checking Fields for Email Addresses

To check the for validly formatted email addresses, use filter_input with the FILTER_VALIDATE_EMAIL filter.

<?php
	$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
	if($email === false) {
		print 'invalid email';
	}
	// do something with $email
?>

Checking Fields for Numbers

To check that integers have been entered, use filter_input with the FILTER_VALIDATE_INT filter.

<?php
	$code = filter_input(INPUT_POST, 'product_code', FILTER_VALIDATE_INT);
	if($code === false) {
		print 'not an integer';
	}
	// do something with $code
?>

To check that floats have been entered, use filter_input again but with the FILTER_VALIDATE_FLOAT filter.

<?php
	$float = filter_input(INPUT_POST, 'price', FILTER_VALIDATE_INT);
	if($float === false) {
		print 'not a float';
	}
	// do something with $float
?>

Requiring Fields

To check that a value has been entered, use filter_has_var.

<?php
	if(!filter_has_var(INPUT_COOKIE, 'user')) {
		print 'not logged in';
	}
?>

The first argument tells where to look for the required field. INPUT_POST examines the request body that was POST'd. INPUT_GET examines the query string. INPUT_COOKIE examines the cookies, INPUT_SERVER examines the server variables and INPUT_ENV examines environment variables. Required fields will most likely exist in INPUT_COOKIE, INPUT_POST and INPUT_GET.

To check that, if a value has been entered then its length should be 10 characters, use filter_has_var and filter_input.

<?php
	if( filter_has_var(INPUT_POST, 'phone') && (strlen(filter_input(INPUT_POST, 'phone', FILTER_SANITIZE_STRING)) < 10) ) {
		print 'phone is not required but must be ten numbers if entered';
	}
?>

To check that, if a value has been entered and that it is an array, use filter_has_var and filter_input.

<?php
	if( !(filter_has_var(INPUT_POST, 'preferences') && filter_input(INPUT_POST, 'preferences', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY)) ) {
		print 'must select more than one preference';
	}
?>

Checking <SELECT> Drop-Down Menus

Use an array to create the drop-down and then use it to validate the input using in_array.

<?php
	$choices = array('cat', 'dog', 'pig');
	print '<select name="animal">';
	foreach($choices as $choice) {
		print "<option>$choice</option>";
	}
	print '</select>';

	// then when a POST occurs check its field against the array
	if(!in_array($_POST['animal'], $choices)) {
		print 'no animal selected';
	}
?>

Or check the array against its keys using array_key_exists.

<?php
	$choices = array(1 => 'cat', 2 => 'dog', 3 => 'pig');
	print '<select name="animal">';
	foreach($choices as $key => $choice) {
		print "<option value='$key'>$choice</option>";
	}
	print '</select>';

	// then when a POST occurs check its field against the array keys
	if(!array_key_exists($_POST['animal'], $choices)) {
		print 'no animal selected';
	}
?>

Checking Checkboxes

To make sure only valid checkboxes are checked, use filter_has_var.

<?php
	$value = 'true';
	print "<input type='checkbox' name='locked' value='$value' /> locked?";

	// And after a POST request
	if(filter_has_var(INPUT_POST, 'locked')) {
		if($_POST['locked'] == $value) {
			print 'you locked it';
		} else {
			print 'notice: invalid value submitted';
		}
	} else {
		print 'not locked';
	}
?>

To check an array or group of checkboxes, use array_intersect.

<?php
	$choices = array(1 => 'cat', 2 => 'dog', 3 => 'pig');
	foreach($choices as $key => $choice) {
		print "<input type='checkbox' name='animal[]' value='$key' /> $choice<br />";
	}

	// And after a POST request
	if(array_intersect($_POST['animal'], array_keys($choices)) != $_POST['animal']) {
		print 'no valid choice of animal made';
	}
?>

A full example:

<html>
	<head>
		<title>CHECKBOX EXAMPLE</title>
	</head>
	<body>
<?php
	$choices = array(1 => 'cat', 2 => 'dog', 3 => 'pig');
	if ($_SERVER['REQUEST_METHOD'] == 'GET') {
?>
	<form method="post" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>">
<?php
	foreach($choices as $key => $choice) {
		print "<input type='checkbox' name='animal[]' value='$key' /> $choice<br />";
	}
?>
		<input type="submit" value="submit" />
	</form>
<?php
	} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
		if(filter_has_var(INPUT_POST, 'animal')) {
			if(array_intersect($_POST['animal'], array_keys($choices)) != $_POST['animal']) {
				print 'invalid data';
			} else {
				foreach($_POST['animal'] as $choice) {
					print $choices[$choice].'<br />';
				}
			}
		} else {
			print 'nothing';
		}
	}
?>
	</body>
</html>

Checking Radio Buttons

To make sure a valid value is submitted, use array_key_exists.

<?php
	$choices = array(1 => 'cat', 2 => 'dog', 3 => 'pig');
	foreach($choices as $key => $choice) {
		print "<input type='radio' name='animal' value='$key' /> $choice<br />";
	}

	// then when a POST occurs check it against the array keys
	if(!array_key_exists($_POST['animal'], $choices)) {
		print 'no animal selected';
	}
?>

A full example:

<html>
	<head>
		<title>RADIO BUTTON EXAMPLE</title>
	</head>
	<body>
<?php
	$choices = array(1 => 'cat', 2 => 'dog', 3 => 'pig');
	if ($_SERVER['REQUEST_METHOD'] == 'GET') {
?>
	<form method="post" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>">
<?php
	foreach($choices as $key => $choice) {
		print "<input type='radio' name='animal' value='$key' /> $choice<br />";
	}
?>
		<input type="submit" value="submit" />
	</form>
<?php
	} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
		if(!array_key_exists($_POST['animal'], $choices)) {
			print 'invalid data';
		} else {
			print $choices[$_POST['animal']].' selected';
		}
	}
?>
	</body>
</html>

Check a Credit Card Expiration Date

To check the expiration date:

<?php
	$expiration = mktime(0, 0, 0, $_POST['expires_month'], 1, $_POST['expires_year']);
	if(time() > $expiration) {
		print 'credit card expired';
	}
?>

Prevent Cross-Site Scripting

Use htmlentities to prevent users from entering JavaScript code in a website that allows users to upload text, like blogs.

<?php
	print htmlentities('<script>document.location.href = "http://somedomain.com";</script>');
?>

Uploading Files

To upload multiple files, specify the attribute multiple and put open and close brackets [] around the name of the input element so that PHP will know that it should be treated as an array.

<?php
	if($_SERVER['REQUEST_METHOD'] == 'GET') {
?>
	<form method="post"
		action="<?php echo $_SERVER['SCRIPT_NAME'] ?>"
		enctype="multipart/form-data">
		<input type="file" multiple name="uploaded_files[]" />
		<input type="submit" value="submit" />
	</form>
<?php
	} else if($_SERVER['REQUEST_METHOD'] == 'POST') {
		$str = "";
		$i = 0;
		$count = count($_FILES['uploaded_files']['name']);
		while($i < $count) {
			if($_FILES['uploaded_files']['error'][$i] == UPLOAD_ERR_OK) {
				$filename = basename($_FILES['uploaded_files']['name'][$i]);
				if(move_uploaded_file($_FILES['uploaded_files']['tmp_name'][$i], $filename)) {
					$str .= "<a target='_blank' href='$filename'>$filename</a> ";
				} else {
					$str .= '[could not move file from temp location to permanent location] ';
				}
			}
			$i++;
		}
		print $str;
	}
?>

Prevent Multiple Form Submissions

Users can accidentally submit a form twice. Use a unique id to prevent processing the same data twice. Also, use JavaScript to disable the submit button.

<?php
	$dbh = dba_open(__DIR__.'/submitted_forms.db','c','db4') or die($php_errormsg);
	if($_SERVER['REQUEST_METHOD'] == 'GET') {
		$token = uniqid();
		dba_insert($token, 0, $dbh);
?>
	<form method="post"
			action="<?php echo $_SERVER['SCRIPT_NAME'] ?>"
			onsubmit="submitbutton.disabled=true;">
		<input type="text" name="username" placeholder="enter username" >
		<input type="hidden" name="token" value="<?php echo $token ?>" />
		<input type="submit" name="submitbutton" />
	</form>
<?php
	} else if($_SERVER['REQUEST_METHOD'] == 'POST') {
		if(isset($_POST['token'])) {
			if(!dba_exists($_POST['token'], $dbh)) {
				print 'invalid request';
			} else {
				if(0 == dba_fetch($_POST['token'], $dbh)) {
					dba_replace($_POST['token'], 1, $dbh);
					// process form
					print 'form processed';
				} else {
					print 'form already submitted';
				}
			}
		}
	}
	dba_close($dbh);
?>
<< < [Page 5 of 6] > >>