TU ESD 1
TUESD
1
Error Checking/Validation
2
3
Expected1
Warnings2
Errors come in three flavors
Fatal3
Expected you anticipateWarnings are look outsFatal are sayonara!
4
PHP error assistance
empty() is better suited for query strings unless numeric information is supplied
5
empty() + is_numeric() is a knock out
empty() is better suited for string queries than isset() unless numeric information is transmitted
6
error_reporting1
display_errors2
PHP error reporting
log_errors3
7
Setting the error_reporting1
Constant Name Value Description
E_ALL 8191 Report all errors and warnings
E_ERROR 1 Report all fatal runtime errors
E_WARNING 2 Report all nonfatal runtime errors (that is, warnings)
0 No reporting
/* In code */ error_reporting(E_ALL);
/* In php.ini */ error_reporting = E_ALL
8
Setting the display_errors2
/* In code */ ini_set('display_errors', '0');
/* In php.ini */ display_errors = Off
Decide whether to display errors or not
9
Setting the log_errors3
/* In code */ ini_set('log_errors', '1'); ini_set('error_log', '/logs/myerr.log');
/* In php.ini */ log_errors = On error_log = /logs/myerr.log
Should errors be logged or not
Advisable to turn on error logging for production sites as well as development sites.
10
log errors in code as well3
11
PHP handles errors procedurally
12
and object oriented
13
exceptions can be rethrown
14
Provide custom error/exception handlers
At the beginning of the script: set_exception_handler('my_exception_handler');
15
Required1
Correct type/format2
Comparison3
Range check4
Custom5
Input validation options
16
Notify the user accordingly
17
Alerts should be avoided
Use these sparingly for critical errors Fine during debugging
18
Offer textual hints
Textual hints work nicely
19
Use tooltips and popups
Pop-ups and tooltips always desirable (js or jQ)
20
Masks eliminate input ambiguity
Masks are not only for Mardi Gras
21
Use the proper widget for the job
Offer appropriate widget rather than text field
22
HTML5 offers simple validation
HTML: the lowest form
23
JS performs pre-validation
function init() { var form = $('sampleForm'); form.onsubmit = validateForm; } $(function() { init(); } );
JS - prevalidation
24
PHP is the validation
<?php /* turn on error reporting */ error_reporting(E_ALL); ini_set('display_errors','1'); ...
PHP always performed
25
<?php /* File: esd-validationForm.php */ ?>
<!DOCTYPE html><html><head> <title>Testing Validation with js and php </title> <style> .controls span { color: red; } </style></head><body>
<!-- Present form with controls to validate --><form method="POST" class="form-horizontal" id="sampleForm"> <fieldset> <legend>Form with Validations</legend>
26
<div class="control-group" id="controlCountry"> <label class="control-label" for="country">Country</label> <div class="controls"> <!-- Show a dropdown box --> <select id="country" name="country" class="input-xlarge"> <option value="0">Choose a country</option> <option value="1">Canada</option> <option value="2">France</option> <option value="3">Germany</option> <option value="4">United States</option> </select> <span class="help-inline" id="errorCountry"> </span> </div> </div>
27
<!-- email field --> <div class="control-group" id="controlEmail"> <label class="control-label" for="email"> Email</label> <div class="controls"> <input id="email" name="email" type="text" placeholder="enter an email" class="input-xlarge" required> <span class="help-inline" id="errorEmail"> </span> </div> </div>
28
<!-- password field --> <div class="control-group" id="controlPassword"> <label class="control-label" for="password">Password</label> <div class="controls"> <input id="password" name="password" type="password" placeholder="enter at least eight characters" class="input-xlarge" required> <span class="help-inline" id="errorPassword"></span> </div> </div>
29
<!-- submit button --> <div class="control-group"> <label class="control-label" for="singlebutton"></label> <div class="controls"> <button id="singlebutton" name="singlebutton" class="btn btn-primary">Register </button> </div> </div> </fieldset></form> <?php include 'esd-inc.validationJS.php'; ?></body></html>
30
<?php /* File: esc-inc.validationJS.php */ ?>
<script src="../js/jquery-1.11.0.js"></script><script> /* sets up event handlers */ function init() { var country = $('#country'); var email = $('#email'); var password = $('#password'); var sampleForm = $('#sampleForm'); // we will reference these repeatedly sampleForm.on('submit', function(e) { validateForm(e); } ); country.on('change', resetMessages); email.on('change', resetMessages); password.on('change', resetMessages); }// end init()
31
/* perform the validation checks */ function validateForm(e) { var hasError = false; // check country if ( country.selectedIndex <= 0 ) { addErrorMessage('Country', 'Select a country'); hasError = true; } // check email var emailReg = /(.+)@([^\.].*)\.([a-z]{2,})/; if (! emailReg.test(email.value)) { addErrorMessage('Email', 'Enter a valid email'); hasError = true; }
32
// check password var passReg = /^\w{8,16}$/; if (! passReg.test(password.value)) { addErrorMessage('Password', 'Enter a password between 8-15 characters'); hasError = true; }
// if any error occurs then cancel submit; due // to browser irregularities this has to be // done in two ways if (! hasError) return true; else { if (e.preventDefault) { e.preventDefault();} else { e.returnValue = false; } return false; } }// end validateForm()
33
function addErrorMessage(id, msg) { // get relevant span and div elements var spanId = 'error' + id; var span = $('#' + spanId); var divId = 'control' + id; var div = $('#' + divId); // add error message to error <span> element if (span) span.html(msg); // add error class to surrounding <div> if (div) div.className = div.className + " error"; }// end addErrorMessage()
34
/* Clear the error messages for the * specified element */ function clearErrorMessage(id) { // get relevant span and div elements var spanId = 'error' + id; var span = $('#' + spanId); var divId = 'control' + id; var div = $('#' + divId); // clear error message and set class // to error span and div elements if (span) span.html(""); if (div) div.className = "control-group"; }// end clearErrorMessage()
35
/* Clears error states if content changes */ function resetMessages() { if (country.selectedIndex > 0) { clearErrorMessage('Country'); } if (email.value.length > 0) { clearErrorMessage('Email'); } if (password.value.length > 0) { clearErrorMessage('Password'); } }// end resetMessage() // set up validation handlers when page is // downloaded and ready $(function() { init(); });</script>
esd-validationForm.php
36
esd-validationForm.php
37
esd-class.validationResult.php
38
<?php/* Represents the results of a validation */class ValidationResult { private $value; // user input value to be validated private $cssClassName; // css class name for display private $errorMessage; // error message to be displayed private $isValid = true; // was the value valid // constructor public function __construct($cssClassName, $value, $errorMessage, $isValid) { $this->cssClassName = $cssClassName; $this->value = $value; $this->errorMessage = $errorMessage; $this->isValid = $isValid; } // accessors public function getCssClassName() { return $this->cssClassName; } public function getValue() { return $this->value; } public function getErrorMessage() { return $this->errorMessage; } public function isValid() { return $this->isValid; }
esd-class.validationResult.php
39
/* Static method used to check a querystring * parameter and return a ValidationResult */ static public function checkParameter($queryName, $pattern, $errMsg) { $error = ""; $errClass = ""; $value = ""; $isValid = true; // first check if the parameter doesn't exist // or is empty if (empty($_POST[$queryName])) { $error = $errMsg; $errClass = "error"; $isValid = false; }
esd-class.validationResult.php
40
else { // now compare it against a regular expression $value = $_POST[$queryName]; if ( !preg_match($pattern, $value) ) { $error = $errMsg; $errClass = "error"; $isValid = false; } } return new ValidationResult($errClass, $value, $error, $isValid); }}
esd-inc.validationFormPHP.php
41
<?php // turn on error reporting to help // potential debugging error_reporting(E_ALL); ini_set('display_errors','1'); include_once('esd-class.ValidationResult.php'); // create default validation results $emailValid = new ValidationResult("", "", "", true); $passValid = new ValidationResult("", "", "", true); $countryValid = new ValidationResult("", "", "", true);
esd-inc.validationFormPHP.php
42
// if GET then just display form // if POST then user has submitted data, we need // to validate it if ($_SERVER["REQUEST_METHOD"] == "POST") { $emailValid = ValidationResult::checkParameter("email", '/(.+)@([^\.].*)\.([a-z]{2,})/', 'Enter a valid email [PHP]'); $passValid = ValidationResult::checkParameter("password", '/^\w{8,16}$/', 'Enter a password between 8-15 characters [PHP]'); $countryValid = ValidationResult::checkParameter("country", '/[1-4]/', 'Choose a country [PHP]');
esd-inc.validationFormPHP.php
43
// if no validation errors redirect to // another page if ($emailValid->isValid() && $passValid->isValid() && $countryValid->isValid() ) { header( 'Location: #' ); } }
esd-validationFormPHP.php
44
<?php include ('esd-inc.validationFormPHP.php'); ?><!DOCTYPE html><html><head> <title>PHP Form Validation</title> <style> .error { color: red; } </style></head><body><form method="POST" action="<?php echo $_SERVER["PHP_SELF"];?>" class="form-horizontal" id="sampleForm" > <fieldset> <legend>Form with Validations</legend> <!-- Country select list --> <div class="control-group <?php echo $countryValid->getCssClassName(); ?>" id="controlCountry">
esd-validationFormPHP.php
45
<label class="control-label" for="country">Country</label> <div class="controls"> <select id="country" name="country" class="input-xlarge"> <option value="0" <?php if($countryValid->getValue()==0) echo "selected";?>> Choose a country</option> <option value="1" <?php if($countryValid->getValue()==1) echo "selected";?>> Canada</option> <option value="2" <?php if($countryValid->getValue()==2) echo"selected"; ?>> France</option>
esd-validationFormPHP.php
46
<option value="3" <?php if($countryValid->getValue()==3)echo "selected"; ?>> Germany</option> <option value="4" <?php if($countryValid->getValue()==4)echo "selected"; ?>> United States</option> </select> <span class="help-inline" id="errorCountry"> <?php echo $countryValid->getErrorMessage(); ?></span> </div> </div> <!-- Email text box --> <div class="control-group <?php echo $emailValid->getCssClassName(); ?>" id="controlEmail"> <label class="control-label" for="email">Email</label>
esd-validationFormPHP.php
47
<div class="controls"> <input id="email" name="email" type="text" value="<?php echo $emailValid->getValue(); ?>" placeholder="enter an email" class="input-xlarge" required> <span class="help-inline" id="errorEmail"> <?php echo $emailValid->getErrorMessage(); ?></span> </div></div> <!-- Password text box --> <div class="control-group <?php echo $passValid->getCssClassName(); ?>" id="controlPassword"> <label class="control-label" for="password">Password</label> <div class="controls"> <input id="password" name="password" type="password" placeholder="enter at least eight characters" class="input-xlarge" required>
esd-validationFormPHP.php
48
<span class="help-inline" id="errorPassword"> <?php echo $passValid->getErrorMessage(); ?></span> </div></div> <!-- Submit button --> <div class="control-group"> <label class="control-label" for="singlebutton"></label> <div class="controls"> <button id="singlebutton" name="singlebutton" class="btn btn-primary"> Register</button> </div></div> </fieldset></form></body></html>
esd-validationFormPHP.php
49
esd-validationFormPHP.php
50
Managing State
51
52
HTTP1
PHP2
State is managed in two places
53
Use a query string to pass information1
links and method="GET" do the same thing
54
or client-side cookies1
Browser
name=value name=value
name=value name=value
cookies are associated with
domains not pages
55
4k size limit
stored number is limited
session: expire with session
persistent: have expiration date
can be turned off
Cookies have limitations
esd-cookies.php
56
<?php $name="Monkey"; $value="Coco"; $expires = time() + 5; /* Must be the first thing written. */ setcookie($name, $value, $expires);
/* To prevent js access (HttpOnly) use this */ setcookie($name, $value, $expires, null, null, null, true);
?> <!DOCTYPE html><html><meta charset="utf-8"><title>Using cookies</title>
esd-cookies.php
57
<body> <h1>This page is using cookies. Yum!</h1> <br> Refresh the page and you will see. <br></body><?php /* Always check if the cookie is set first. */ if (isset($_COOKIE['Monkey'])) { echo "The value stored in Monkey is {$_COOKIE['Monkey']}"; }?> </html>
<?php?>
58
<?php?>
59
60
Cookies can increase traffic loads1
amazon.com
cookies transmitted with images, css, scripts etc
images-amazon.com
this sites does not use cookies
61
Use sessions on the server2
Each browser session has its own session state
the state is stored as a serialized object
its then unserialized and loaded into
Sessions are ideal for shopping carts
Sessions can store any type of object
62
One session per user
There are more sessions on disk than in memory
63
Use session_start() first thing
session_start() must be called first
64
Session expires so check
65
Know how sessions really work
HTTP is still the underlying protocol used
being stateless, some form of identification is needed
PHP sessionID: 32-byte string
a sessionID is used
transmitted via a cookie
66
Sessions still need cookies
if cookies are disabled, then configure php.ini to send sessionID through the url
67
On a new session...
WS
an empty dictionary like collection is created
68
...on completion it is saved...
WS
the session is saved in the state provider
Session state provider
User session A
Memory
User session A
69
...and on recall it is retrieved
WS
the session is retrieved from the state provider
Session state provider
User session A
Memory
User session A
70
State provider options available
Memory: session must be served by same ws session lost if server restarts limited on shared hosts
File: session can be served by any ws session reconstructed if server restarts less efficient than memory provider
71
HTML5 Web Storage
meant to replace cookies
uses JS-only API
managed by the browser
not transmitted with each request/response
not limited to 4K size (< 5MB recommended)
two objects available: localStorage and sessionStorage
72
Two ways to write to storage
can use either .setItem or .property
localStorage is persistent
73
and two ways to read from it
can use either .getItem or .property