PROWAREtech
PHP: Tips and Tricks - Page 5
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);
?>