If the script is called without one or more inputs, it shows error messages.. For example, say the user forgot to enter the operator, in such a case the output looks as shown in Figure 1
Trang 1Listing 1-6 (Continued)
// Setup the template block
$t->set_block(“page”, “mainBlock” , “main”);
// Set the template variable = value
$t->set_var(“ERRORS”, $errors);
$t->set_var(“NUM1”, $num1);
$t->set_var(“NUM2”, $num2);
$t->set_var(“OPERATOR”, $operator);
$t->set_var(“RESULT”, $result);
// Parse the template block with all // predefined key=values
$t->parse(“main”, “mainBlock”, false);
// Parse the entire template and // print the output
$t->pparse(“OUT”, “page”);
?>
The script can be called using a URL such as the following:
http://yourserver/ch1/calc.php?num1=123&operator=%2B&num2=0 The calc.php script produces an output screen, as shown in Figure 1-1, using the calc.htmltemplate stored in ch1/templates.
Figure 1-1: Output of the calc.phpscript.
If the script is called without one or more inputs, it shows error messages For example, say the user forgot to enter the operator, in such a case the output looks
as shown in Figure 1-2.
Trang 2Figure 1-2: Output of the calc.phpscript (calling without an operator).
Similarly, if the operator is division (/) and the second number is 0, then the divide by zero error message is shown, as in Figure 1-3.
Figure 1-3: Output of calc.phpscript (divide by zero error message).
So this script is able to catch input errors and even a run-time error caused by bad user input (divide by zero) But, sadly, this script is violating a design principle
of a practical PHP application Notice the following lines in the script:
$errors = “<li>You did not enter number 1.”;
// lines skipped
$errors = “<li>You did not enter number 2.”;
// lines skipped
$errors = “<li>You did not enter the operator.”;
// lines skipped
$errors = “Divide by zero is not allowed.”;
Trang 3These error messages are in English and have HTML tags in them This means if the end user wasn’t fond of the way the messages were shown, he or she would have to change them in the code and potentially risk modification of the code that may result in bugs Also, what if the end user spoke, say, Spanish, instead of English? This also means that the end user would have to change the code A bet-ter solution is shown in Listing 1-7 and Listing 1-8.
Listing 1-7: calc2.php
<?php // Enable all error reporting error_reporting(E_ALL);
require_once(‘calc2.conf’);
require_once(‘calc2.errors’);
// Get inputs from GET or POST request
$num1 = (! empty($_REQUEST[‘num1’])) ? $_REQUEST[‘num1’] : null;
$num2 = (! empty($_REQUEST[‘num2’])) ? $_REQUEST[‘num2’] : null;
$operator = (! empty($_REQUEST[‘operator’])) ?
$_REQUEST[‘operator’] : null;
// Set errors to null
$errors = null;
// If number 1 is not given, error occurred
if ($num1 == null) {
$errors = $ERRORS[LANGUAGE][‘NUM1_MISSING’];
} // If number 2 is not given, error occured
if ($num2 == null) {
$errors = $ERRORS[LANGUAGE][‘NUM2_MISSING’];
} // If operator is not given, error occured
if (empty($operator)) {
$errors = $ERRORS[LANGUAGE][‘OPERATOR_MISSING’];
} // Set result to null
$result = null;
Trang 4// If operation is + do addition: num1 + num2
if (!strcmp($operator, ‘+’)) {
$result = $num1 + $num2;
// If operation is - do subtraction: num1 - num2 } else if(! strcmp($operator, ‘-’)) {
$result = $num1 - $num2;
// If operation is * do multiplication: num1 * num2 } else if(! strcmp($operator, ‘*’)) {
$result = $num1 * $num2;
// If operation is / do division: num1 / num2 } else if(! strcmp($operator, ‘/’)) {
// If second number is 0, show divide by zero exception
if (! $num2) {
$errors = $ERRORS[LANGUAGE][‘DIVIDE_BY_ZERO’];
} else {
$result = sprintf(“%.2f”, $num1 / $num2);
} } // Create a new template object
$t = new Template($TEMPLATE_DIR);
// Set the template file for this object to application’s template
$t->set_file(“page”, $OUT_TEMPLATE);
// Setup the template block
$t->set_block(“page”, “mainBlock” , “main”);
// Set the template variable = value
$t->set_var(“ERRORS”, $errors);
$t->set_var(“NUM1”, $num1);
$t->set_var(“NUM2”, $num2);
$t->set_var(“OPERATOR”, $operator);
$t->set_var(“RESULT”, $result);
// Parse the template block with all predefined key=values
$t->parse(“main”, “mainBlock”, false);
// Parse the entire template and print the output
$t->pparse(“OUT”, “page”);
?>
Trang 5The difference between calc.php and calc2.php is that calc2.php doesn’t have any error messages hard-coded in the script The calc.php error messages have been replaced with the following:
$errors = $ERRORS[LANGUAGE][NUM1_MISSING];
$errors = $ERRORS[LANGUAGE][NUM2_MISSING];
$errors = $ERRORS[LANGUAGE][OPERATOR_MISSING];
$errors = $ERRORS[LANGUAGE][DIVIDE_BY_ZERO];
The calc2.phpscript loads error messages from the calc2.errorsfile using the following line:
require_once(‘calc2.errors’);
The calc.errorsfile is shown in Listing 1-8.
Listing 1-8: calc2.errors
<?php
// US English
$ERRORS[‘US’][‘NUM1_MISSING’] = “<li>You did not enter number 1.”;
$ERRORS[‘US’][‘NUM2_MISSING’] = “<li>You did not enter number 2.”;
$ERRORS[‘US’][‘OPERATOR_MISSING’] = “<li>You did not enter the operator.”;
$ERRORS[‘US’][‘DIVIDE_BY_ZERO’] = “Divide by zero is not allowed.”;
// Spanish (translated using Google // Uncomment the following lines to get Spanish error messages // Also, set LANGUAGE in calc2.conf to ES
// $ERRORS[‘ES’][‘NUM1_MISSING’] = “<li>Usted no incorporo el numero 1”; // $ERRORS[‘ES’][‘NUM2_MISSING’] = “<li>Usted no incorporo el numero 2.”; // $ERRORS[‘ES’][‘OPERATOR_MISSING’] = “<li>Usted no inscribio a operador ”; // $ERRORS[‘ES’][‘DIVIDE_BY_ZERO’] = “Dividase por cero no se permite.”;
?>
The calc2.errors file loads a multidimensional associative array called
$ERRORS The first dimension is the language and the second dimension is error code For example:
$ERRORS[‘US’][‘NUM1_MISSING’] = “<li>You did not enter number 1.”;
‘US’is shorthand code for the U.S English language The NUM1_MISSING is a code that has the “<li>You did not enter number 1.” error message associated with it When the calc2.phpscript executes a line such as the following:
$errors = $ERRORS[LANGUAGE][‘NUM1_MISSING’];