You cannot define the embedded block first. The next line in Listing 1-2 sets a template variable NAME to the value of $name variable: $t->set_var(“NAME”, $name); In Listing 1-3, you will see a line such as the following: <td> {NAME} </td> Here the template variable is {NAME}. When setting the value for this template variable using the set_var() method, you didn’t have to use the curly braces, as it is automatically assumed. Now that the script has set the value for the only template variable in the tem- plate, you can parse the block as done in the next line: $t->parse(“main”, “mainBlock”, false); This line calls the parse() method of the $t template object to parse the mainBlock, which is internally named as “main.” The third parameter is set to false, because we don’t intend to loop through this block. Because nested blocks are often used in loops, you’d have to set the third parameter to true to ensure that the block is parsed properly from iteration to iteration. Finally, the only remaining thing to do is print and parse the entire page: $t->pparse(“OUT”, “page”); This prints the output page. What all this additional code bought us is an implementation that uses an exter- nal HTML template, which the end user can modify without knowing anything about the PHP code. This is a great achievement, because most of the time the end user is interested in updating the interface look and feel as his or her site goes through transitions over time. Using external configuration files An external configuration file separates code from information that is end-user configurable. By separating end-user editable information to a separate configuration file we reduce the risk of unintentional modification of core application code. Experienced commercial developers will tell you that this separation is a key timesaver when customers make support calls about PHP applications. As a developer, you can instruct the end user to only modify the configuration file and never to change anything in the core application files. This means any problem created at the end- user site is confined to the configuration file and can be identified easily by the developer. Chapter 1: Features of Practical PHP Applications 11 03 549669 ch01.qxd 4/4/03 9:24 AM Page 11 In Listing 1-2, we had the following lines: $PHPLIB_DIR = $_SERVER[‘DOCUMENT_ROOT’] . ‘/phplib’; ini_set( ‘include_path’, ‘:’ . $PHPLIB_DIR . ‘:’ . ini_get(‘include_path’)); include(‘template.inc’); include(‘template.inc’); $TEMPLATE_DIR = $_SERVER[‘DOCUMENT_ROOT’] . ‘/ch1/templates’; $OUT_TEMPLATE = ‘listing2out.html’; These lines are configuration data for the script. Ideally, these lines should be stored in an external configuration file. For example, Listing 1-4 shows a modified version of Listing 1-2. Listing 1-4: Modified Version of Listing 1-2 <?php require_once(‘app_name.conf’); // Enable all reporting error_reporting(E_ALL); // Get name from GET or POST request $name = (! empty($_REQUEST[‘name’])) ? $_REQUEST[‘name’] : null; // 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(“NAME”, $name); 12 Part I: Designing PHP Applications 03 549669 ch01.qxd 4/4/03 9:24 AM Page 12 // 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”); ?> Notice that all the configuration lines from the Listing 1-2 script have been removed with the following line: require_once(‘app_name.conf’); The require_once() function loads the configuration file. The configuration lines now can be stored in the app_name.conf file, as shown in Listing 1-5. Listing 1-5: Configuration File for Listing 1-4 Script <?php // Set PHPLIB path $PHPLIB_DIR = $_SERVER[‘DOCUMENT_ROOT’] . ‘/phplib’; // Add PHPLIB path to PHP’s include path ini_set( ‘include_path’, ‘:’ . $PHPLIB_DIR . ‘:’ . ini_get(‘include_path’)); // Include the PHPLIB template class include(‘template.inc’); // Setup this application’s template // directory path $TEMPLATE_DIR = $_SERVER[‘DOCUMENT_ROOT’] . ‘/ch1/templates’; // Setup the output template filename $OUT_TEMPLATE = ‘listing2out.html’; ?> Another great advantage of a configuration file is that it allows you to define global constants as follows: define(YOUR_CONSTANT, value); Chapter 1: Features of Practical PHP Applications 13 03 549669 ch01.qxd 4/4/03 9:24 AM Page 13 For example, to define a constant called VERSION with value 1.0.0 you can add the following line in your configuration file: define(VERSION, ‘1.0.0’); Because constants are not to be modified by design, centralizing then in a con- figuration file makes a whole lot of sense. Using customizable messages To understand the importance of customizable messages that are generated by an application, let’s look at a simple calculator script. Listing 1-6 shows the script, called calc.php. The configuration file used by calc.php is calc.conf, which is similar to Listing 1-5 and not shown here. This script expects the user to enter two numbers (num1, num2) and an operator (+ for addition, – for subtraction, * for multiplication, or / for division). If it doesn’t get one or more of these required inputs, it prints error messages which are stored in an $errors variable. Listing 1-6: calc.php <?php // Enable all error reporting error_reporting(E_ALL); require_once(‘calc.conf’); // 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 .= “<li>You did not enter number 1.”; } 14 Part I: Designing PHP Applications 03 549669 ch01.qxd 4/4/03 9:24 AM Page 14 // If number 2 is not given, error occurred if ($num2 == null) { $errors .= “<li>You did not enter number 2.”; } // If operator is not given, error occurred if (empty($operator)) { $errors .= “<li>You did not enter the operator.”; } // Set result to null $result = null; // 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 .= “Divide by zero is not allowed.”; } 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); Continued Chapter 1: Features of Practical PHP Applications 15 03 549669 ch01.qxd 4/4/03 9:24 AM Page 15 . Listing 1-4 Script < ?php // Set PHPLIB path $PHPLIB_DIR = $_SERVER[‘DOCUMENT_ROOT’] . ‘/phplib’; // Add PHPLIB path to PHP s include path ini_set( ‘include_path’, ‘:’ . $PHPLIB_DIR . ‘:’ . ini_get(‘include_path’)); //. Features of Practical PHP Applications 11 03 549669 ch01.qxd 4/4/03 9:24 AM Page 11 In Listing 1-2, we had the following lines: $PHPLIB_DIR = $_SERVER[‘DOCUMENT_ROOT’] . ‘/phplib’; ini_set( ‘include_path’,. look at a simple calculator script. Listing 1-6 shows the script, called calc .php. The configuration file used by calc .php is calc.conf, which is similar to Listing 1-5 and not shown here. This script