19. PHP

Be careful when reading health books; you may die of a misprint.

—Mark Twain

Reckoners without their host must reckon twice.

—John Heywood

There was a door to which I found no key; There was the veil through which I might not see.

—Omar Khayyam

Objectives

In this chapter you will:

• Manipulate data of various types.

• Use operators, arrays and control statements.

• Use regular expressions to search for text that matches a patterns.

• Construct programs that process form data.

• Store data on the client using cookies.

• Create programs that interact with MySQL databases.

Outline

19.1 Introduction

19.2 Simple PHP Program

19.3 Converting Between Data Types

19.4 Arithmetic Operators

19.5 Initializing and Manipulating Arrays

19.6 String Comparisons

19.7 String Processing with Regular Expressions

19.7.1 Searching for Expressions

19.7.2 Representing Patterns

19.7.3 Finding Matches

19.7.4 Character Classes

19.7.5 Finding Multiple Instances of a Pattern

19.8 Form Processing and Business Logic

19.8.1 Superglobal Arrays

19.8.2 Using PHP to Process HTML5 Forms

19.9 Reading from a Database

19.10 Using Cookies

19.11 Dynamic Content

19.12 Web Resources

Summary | Self-Review Exercises | Answers to Self-Review Exercises | Exercises

19.1. Introduction

PHP, or PHP: Hypertext Preprocessor, has become the most popular server-side scripting language for creating dynamic web pages. PHP was created by Rasmus Lerdorf to track users at his website. In 1995, Lerdorf released it as a package called the “Personal Home Page Tools.” Two years later, PHP 2 featured built-in database support and form handling. In 1997, PHP 3 was released after a substantial rewrite, which resulted in a large increase in performance and led to an explosion of PHP use. The release of PHP 4 featured the new Zend Engine from Zend, a PHP software company. This version was considerably faster and more powerful than its predecessor, further increasing PHP’s popularity. It’s estimated that over 15 million domains now use PHP, accounting for more than 20 percent of web pages.1 Currently, PHP 5 features the Zend Engine 2, which provides further speed increases, exception handling and a new object-oriented programming model.2 More information about the Zend Engine can be found at www.zend.com.

2 Z. Suraski, “The OO Evolution of PHP,” 16 March 2004, Zend <devzone.zend.com/node/view/id/1717>.

1 “History of PHP,” 30 June 2007, PHP <us.php.net/history>.

PHP is an open-source technology that’s supported by a large community of users and developers. PHP is platform independent—implementations exist for all major UNIX, Linux, Mac and Windows operating systems. PHP also supports many databases, including MySQL.

After introducing the basics of the PHP scripting language, we discuss form processing and business logic, which are vital to e-commerce applications. Next, we build a three-tier web application that queries a MySQL database. We also show how PHP can use cookies to store information on the client that can be retrieved during future visits to the website. Finally, we revisit the form-processing example to demonstrate some of PHP’s more dynamic capabilities.

Notes Before Proceeding

To run a PHP script, PHP must first be installed on your system. We assume that you’ve followed the XAMPP installation instructions in Chapter 17. This ensures that the Apache web server, MySQL DBMS and PHP are configured properly so that you can test PHP web applications on your local computer. For the examples that access a database, this chapter also assumes that you’ve followed the instructions in Chapter 18 for setting up a MySQL user account and for creating the databases we use in this chapter. All examples and exercises in this chapter have been verified using PHP 5.3.5—the version installed by XAMPP at the time of publication.

Before continuing, take the examples folder for this chapter (ch19) and copy it into the XAMPP installation folder’s htdocs subfolder. This is the folder from which XAMPP serves documents, images and scripts.

19.2. Simple PHP Program

The power of the web resides not only in serving content to users, but also in responding to requests from users and generating web pages with dynamic content. Interactivity between the user and the server has become a crucial part of web functionality, making PHP—a language written specifically for handling client requests—a valuable tool.

PHP code is embedded directly into text-based documents, such as HTML, though these script segments are interpreted by the server before being delivered to the client. PHP script file names end with .php.

Figure 19.1 presents a simple PHP script that displays a welcome message. PHP code is inserted between the delimiters <?php and ?> and can be placed anywhere in HTML markup. Line 7 declares variable $name and assigns it the string "Paul". All variables are preceded by a $ and are created the first time they’re encountered by the PHP interpreter. PHP statements terminate with a semicolon (;).


Image Common Programming Error 19.1

Variable names in PHP are case sensitive. Failure to use the proper mixture of cases to refer to a variable will result in a logic error, since the script will create a new variable for any name it doesn’t recognize as a previously used variable.



Image Common Programming Error 19.2

Forgetting to terminate a statement with a semicolon (;) is a syntax error.



 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.1: first.php -->
 4   <!-- Simple PHP program. -->
 5   <html>
 6   <?php                                               
 7      $name = "Paul"; // declaration and initialization
 8   ?><!-- end PHP script -->                           
 9      <head>
10         <meta charset = "utf-8">
11         <title>Simple PHP document</title>
12      </head>
13      <body>
14         <!-- print variable name's value -->
15         <h1><?php print( "Welcome to PHP, $name!" ); ?></h1>
16      </body>
17   </html>

Image

Fig. 19.1. Simple PHP program.

Line 7 also contains a single-line comment, which begins with two slashes (//). Text to the right of the slashes is ignored by the interpreter. Multiline comments begin with delimiter /* on the first line of the comment and end with delimiter */ at the end of the last line of the comment.

Line 15 outputs the value of variable $name by calling function print. The value of $name is printed, not the string "$name". When a variable is encountered inside a double-quoted ("") string, PHP interpolates the variable. In other words, PHP inserts the variable’s value where the variable name appears in the string. Thus, variable $name is replaced by Paul for printing purposes. All operations of this type execute on the server before the HTML5 document is sent to the client. You can see by viewing the source of a PHP document that the code sent to the client does not contain any PHP code.

PHP variables are loosely typed—they can contain different types of data (e.g., integers, doubles or strings) at different times. Figure 19.2 introduces PHP’s data types.

Image

Fig. 19.2. PHP types.

19.3. Converting Between Data Types

Converting between different data types may be necessary when performing arithmetic operations with variables. Type conversions can be performed using function settype. Figure 19.3 demonstrates type conversion of some types introduced in Fig. 19.2.


 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.3: data.php -->
 4   <!-- Data type conversion. -->
 5   <html>
 6      <head>
 7         <meta charset = "utf-8">
 8         <title>Data type conversion</title>
 9         <style type = "text/css">
10            p      { margin: 0; }
11            .head  { margin-top: 10px; font-weight: bold; }
12            .space { margin-top: 10px; }
13         </style>
14      </head>
15      <body>
16         <?php
17            // declare a string, double and integer
18            $testString = "3.5 seconds";
19            $testDouble = 79.2;         
20            $testInteger = 12;          
21         ?><!-- end PHP script -->
22
23         <!-- print each variable's value and type -->
24         <p class = "head">Original values:</p>
25         <?php
26            print( "<p>$testString is a(n) " . gettype( $testString )
27               . "</p>" );
28            print( "<p>$testDouble is a(n) " . gettype( $testDouble )
29               . "</p>" );
30            print( "<p>$testInteger is a(n) " . gettype( $testInteger )
31               . "</p>" );
32         ?><!-- end PHP script -->
33         <p class = "head">Converting to other data types:</p>
34         <?php
35            // call function settype to convert variable
36            // testString to different data types
37            print( "<p>$testString " );      
38            settype( $testString, "double" );
39            print( " as a double is $testString</p>" );
40            print( "<p>$testString " );
41            settype( $testString, "integer" );
42            print( " as an integer is $testString</p>" );
43            settype( $testString, "string" );
44            print( "<p class = 'space'>Converting back to a string results in
45               $testString</p>" );
46
47            // use type casting to cast variables to a different type
48            $data = "98.6 degrees";
49            print( "<p class = 'space'>Before casting: $data is a " .
50               gettype( $data ) . "</p>" );
51            print( "<p class = 'space'>Using type casting instead:</p>
52               <p>as a double: " . (double) $data . "</p>" .
53               "<p>as an integer: " . (integer) $data . "</p>";
54            print( "<p class = 'space'>After casting: $data is a " .
55                 gettype( $data ) . "</p>" );
56         ?><!-- end PHP script -->
57      </body>
58   </html>

Image

Fig. 19.3. Data type conversion.

Functions gettype and settype

Lines 18–20 assign a string to variable $testString, a floating-point number to variable $testDouble and an integer to variable $testInteger. Variables are typed based on the values assigned to them. For example, variable $testString becomes a string when assigned the value "3.5 seconds". Lines 26–31 print the value of each variable and its type using function gettype, which returns the current type of its argument. When a variable is in a print statement but not part of a string, enclosing the variable name in double quotes is unnecessary. Lines 38, 41 and 43 call settype to modify the type of each variable. Function settype takes two arguments—the variable whose type is to be changed and the variable’s new type.

Calling function settype can result in loss of data. For example, doubles are truncated when they’re converted to integers. When converting from a string to a number, PHP uses the value of the number that appears at the beginning of the string. If no number appears at the beginning, the string evaluates to 0. In line 38, the string "3.5 seconds" is converted to a double, storing 3.5 in variable $testString. In line 41, double 3.5 is converted to integer 3. When we convert this variable to a string (line 43), the variable’s value becomes "3"—much of the original content from the variable’s declaration in line 14 is lost.

Casting

Another option for conversion between types is casting (or type casting). Unlike settype, casting does not change a variable’s content—it creates a temporary copy of a variable’s value in memory. Lines 52–53 cast variable $data’s value (declared in line 48) from a string to a double and an integer. Casting is useful when a different type is required in a specific operation but you would like to retain the variable’s original value and type. Lines 49–55 show that the type and value of $data remain unchanged even after it has been cast several times.

String Concatenation

The concatenation operator (.) combines multiple strings in the same print statement, as demonstrated in lines 49–55. A print statement may be split over multiple lines—all data that’s enclosed in the parentheses and terminated by a semicolon is printed to the XHTML document.


Image Error-Prevention Tip 19.1

Function print can be used to display the value of a variable at a particular point during a program’s execution. This is often helpful in debugging a script.


19.4. Arithmetic Operators

PHP provides several arithmetic operators, which we demonstrate in Fig. 19.4. Line 15 declares variable $a and assigns to it the value 5. Line 19 calls function define to create a named constant. Function define takes two arguments—the name and value of the constant. An optional third argument accepts a bool value that specifies whether the constant is case insensitive—constants are case sensitive by default.


Image Common Programming Error 19.3

Assigning a value to a constant after it’s declared is a syntax error.


Line 22 adds constant VALUE to variable $a. Line 26 uses the multiplication assignment operator *= to yield an expression equivalent to $a = $a * 2 (thus assigning $a the value 20). Arithmetic assignment operators—like the ones described in Chapter 6—are syntactical shortcuts. Line 34 adds 40 to the value of variable $a.

Uninitialized variables have undefined values that evaluate differently, depending on the context. For example, when an undefined value is used in a numeric context (e.g., $num in line 51), it evaluates to 0. In contrast, when an undefined value is interpreted in a string context (e.g., $nothing in line 48), it evaluates to the string "undef". When you run a PHP script that uses an undefined variable, the PHP interpreter outputs warning messages in the web page. You can adjust the level of error and warning messages in the PHP configuration files for your platform (e.g., the php.ini file on Windows). For more information, see the online documentation for PHP at php.net.


 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.4: operators.php -->
 4   <!-- Using arithmetic operators. -->
 5   <html>
 6      <head>
 7         <meta charset = "utf-8">
 8         <style type = "text/css">
 9            p { margin: 0; }
10         </style>
11         <title>Using arithmetic operators</title>
12      </head>
13      <body>
14         <?php
15            $a = 5;
16            print( "<p>The value of variable a is $a</p>" );
17
18            // define constant VALUE
19            define( "VALUE", 5 );
20
21            // add constant VALUE to variable $a
22            $a = $a + VALUE;
23            print( "<p>Variable a after adding constant VALUE is $a</p>" );
24
25            // multiply variable $a by 2
26            $a *= 2;
27            print( "<p>Multiplying variable a by 2 yields $a</p>" );
28
29            // test if variable $a is less than 50
30            if ( $a < 50 )
31               print( "<p>Variable a is less than 50</p>" );
32
33            // add 40 to variable $a
34            $a += 40;
35            print( "<p>Variable a after adding 40 is $a</p>" );
36
37            // test if variable $a is 50 or less
38            if ( $a < 51 )
39               print( "<p>Variable a is still 50 or less</p>" );
40            elseif ( $a < 101 ) // $a >= 51 and <= 100
41               print( "<p>Variable a is now between 50 and 100,
42                  inclusive</p>" );
43            else // $a > 100
44               print( "<p>Variable a is now greater than 100</p>" );
45
46            // print an uninitialized variable
47            print( "<p>Using a variable before initializing:
48               $nothing</p>" ); // nothing evaluates to ""
49
50            // add constant VALUE to an uninitialized variable
51            $test = $num + VALUE; // num evaluates to 0
52            print( "<p>An uninitialized variable plus constant
53               VALUE yields $test</p>" );
54
55            // add a string to an integer
56            $str = "3 dollars";
57            $a += $str;        
58            print( "<p>Adding a string to variable a yields $a</p>" );
59         ?><!-- end PHP script -->
60      </body>
61   </html>

Image

Fig. 19.4. Using arithmetic operators.


Image Error-Prevention Tip 19.2

Initialize variables before they’re used to avoid subtle errors. For example, multiplying a number by an uninitialized variable results in 0.


Strings are converted to integers or doubles when they’re used in arithmetic operations. In line 57, a copy of the value of variable str, "3 dollars", is converted to the integer 3 for use in the calculation. The type and value of variable $str are left unchanged.

Keywords

Keywords (examples from Fig. 19.4 include if, elseif and else) may not be used as function, method, class or namespace names. Figure 19.5 lists the PHP keywords.

Image

Fig. 19.5. PHP keywords.

Keywords

Figure 19.6 contains the operator precedence chart for PHP. The operators are shown from top to bottom in decreasing order of precedence.

Image

Fig. 19.6. PHP operator precedence and associativity.

19.5. Initializing and Manipulating Arrays

PHP provides the capability to store data in arrays. Arrays are divided into elements that behave as individual variables. Array names, like other variables, begin with the $ symbol. Figure 19.7 demonstrates initializing and manipulating arrays. Individual array elements are accessed by following the array’s variable name with an index enclosed in square brackets ([]). If a value is assigned to an array element of an array that does not exist, then the array is created (line 18). Likewise, assigning a value to an element where the index is omitted appends a new element to the end of the array (line 21). The for statement (lines 24–25) prints each element’s value. Function count returns the total number of elements in the array. In this example, the for statement terminates when the counter ($i) is equal to the number of array elements.


 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.7: arrays.php -->
 4   <!-- Array manipulation. -->
 5   <html>
 6      <head>
 7         <meta charset = "utf-8">
 8         <title>Array manipulation</title>
 9         <style type = "text/css">
10            p    { margin: 0; }
11            .head { margin-top: 10px; font-weight: bold; }
12         </style>
13      </head>
14      <body>
15         <?php
16            // create array first
17            print( "<p class = 'head'>Creating the first array</p>" );
18            $first[ 0 ] = "zero";
19            $first[ 1 ] = "one"
20            $first[ 2 ] = "two"
21            $first[] = "three";  
22
23            // print each element's index and value
24            for ( $i = 0; $i < count( $first ); ++$i ) 
25               print( "Element $i is $first[$i]</p>" );
26
27            print( "<p class = 'head'>Creating the second array</p>" );
28
29            // call function array to create array second
30            $second = array( "zero", "one", "two", "three" );
31
32            for ( $i = 0; $i < count( $second ); ++$i ) 
33               print( "Element $i is $second[$i]</p>" );
34
35            print( "<p class = 'head'>Creating the third array</p>" );
36
37            // assign values to entries using nonnumeric indices
38            $third[ "Amy" ] = 21;  
39            $third[ "Bob" ] = 18;  
40            $third[ "Carol" ] = 23;
41
42            // iterate through the array elements and print each
43            // element's name and value
44            for ( reset( $third ); $element = key( $third ); next( $third ) )
45              print( "<p>$element is $third[$element]</p>" );                
46
47            print( "<p class = 'head'>Creating the fourth array</p>" );
48
49            // call function array to create array fourth using
50            // string indices
51            $fourth = array(                                       
52               "January"   => "first",   "February" => "second",   
53               "March"     => "third",   "April"    => "fourth",   
54               "May"       => "fifth",   "June"     => "sixth",    
55               "July"      => "seventh", "August"   => "eighth",   
56               "September" => "ninth",   "October"  => "tenth",    
57               "November"  => "eleventh","December" => "twelfth" );
58
59            // print each element's name and value
60            foreach ( $fourth as $element => $value )         
61               print( "<p>$element is the $value month</p>" );
62         ?><!-- end PHP script -->
63      </body>
64   </html>

Image

Fig. 19.7. Array manipulation.

Line 30 demonstrates a second method of initializing arrays. Function array creates an array that contains the arguments passed to it. The first item in the argument list is stored as the first array element (recall that the first element’s index is 0), the second item is stored as the second array element and so on. Lines 32–33 display the array’s contents.

In addition to integer indices, arrays can have float or nonnumeric indices (lines 38–40). An array with noninteger indices is called an associative array. For example, indices Amy, Bob and Carol are assigned the values 21, 18 and 23, respectively.

PHP provides functions for iterating through the elements of an array (line 44). Each array has a built-in internal pointer, which points to the array element currently being referenced. Function reset sets the internal pointer to the first array element. Function key returns the index of the element currently referenced by the internal pointer, and function next moves the internal pointer to the next element and returns the element. In our script, the for statement continues to execute as long as function key returns an index. Function next returns false when there are no more elements in the array. When this occurs, function key cannot return an index, $element is set to false and the for statement terminates. Line 45 prints the index and value of each element.

The array $fourth is also associative. To override the automatic numeric indexing performed by function array, you can use operator =>, as demonstrated in lines 51–57. The value to the left of the operator is the array index and the value to the right is the element’s value.

The foreach control statement (lines 60–61) is specifically designed for iterating through arrays, especially associative arrays, because it does not assume that the array has consecutive integer indices that start at 0. The foreach statement starts with the array to iterate through, followed by the keyword as, followed by two variables—the first is assigned the index of the element, and the second is assigned the value of that index. (If there’s only one variable listed after as, it’s assigned the value of the array element.) We use the foreach statement to print the index and value of each element in array $fourth.

19.6. String Comparisons

Many string-processing tasks can be accomplished by using the equality and comparison operators, demonstrated in Fig. 19.8. Line 16 declares and initializes array $fruits. Lines 19–38 iterate through each element in the $fruits array.

Lines 23 and 25 call function strcmp to compare two strings. The function returns -1 if the first string alphabetically precedes the second string, 0 if the strings are equal, and 1 if the first string alphabetically follows the second. Lines 23–28 compare each element in the $fruits array to the string "banana", printing whether each is greater than, less than or equal to the string.

Relational operators (==, !=, <, <=, > and >=) can also be used to compare strings. Lines 32–37 use relational operators to compare each element of the array to the string "apple".


 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.8: compare.php -->
 4   <!-- Using the string-comparison operators. -->
 5   <html>
 6      <head>
 7         <meta charset = "utf-8">
 8         <title>String Comparison</title>
 9         <style type = "text/css">
10            p { margin: 0; }
11         </style>
12      </head>
13      <body>
14         <?php
15            // create array fruits
16            $fruits = array( "apple", "orange", "banana" );
17
18            // iterate through each array element
19            for ( $i = 0; $i < count( $fruits ); ++$i )
20            {
21               // call function strcmp to compare the array element
22               // to string "banana"
23               if ( strcmp( $fruits[ $i ], "banana" ) < 0 )
24                  print( "<p>" . $fruits[ $i ] . " is less than banana " );
25               elseif ( strcmp( $fruits[ $i ], "banana" ) > 0 )
26                  print( "<p>" . $fruits[ $i ] . " is greater than banana ");
27               else
28                  print( "<p>" . $fruits[ $i ] . " is equal to banana " );
29
30               // use relational operators to compare each element
31               // to string "apple"
32               if ( $fruits[ $i ] < "apple" )
33                  print( "and less than apple!</p>" );
34               elseif ( $fruits[ $i ] > "apple" )
35                  print( "and greater than apple!</p>" );
36               elseif ( $fruits[ $i ] == "apple" )
37                  print( "and equal to apple!</p>" );
38            } // end for
39         ?><!-- end PHP script -->
40      </body>
41   </html>

Image

Fig. 19.8. Using the string-comparison operators.

19.7. String Processing with Regular Expressions

PHP can process text easily and efficiently, enabling straightforward searching, substitution, extraction and concatenation of strings. Text manipulation is usually done with regular expressions—a series of characters that serve as pattern-matching templates (or search criteria) in strings, text files and databases. Function preg_match uses regular expressions to search a string for a specified pattern using Perl-compatible regular expressions (PCRE). Figure 19.9 demonstrates regular expressions.


 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.9: expression.php -->
 4   <!-- Regular expressions. -->
 5   <html>
 6      <head>
 7         <meta charset = "utf-8">
 8         <title>Regular expressions</title>
 9         <style type = "text/css">
10            p { margin: 0; }
11         </style>
12      </head>
13      <body>
14         <?php
15            $search = "Now is the time";
16            print( "<p>Test string is: '$search'</p>" );
17
18            // call preg_match to search for pattern 'Now' in variable search
19            if ( preg_match( "/Now/", $search ) )
20               print( "<p>'Now' was found.</p>" );
21
22            // search for pattern 'Now' in the beginning of the string
23            if ( preg_match( "/^Now/", $search ) )
24               print( "<p>'Now' found at beginning of the line.</p>" );
25
26            // search for pattern 'Now' at the end of the string
27            if ( !preg_match( "/Now$/", $search ) )
28               print( "<p>'Now' was not found at the end of the line.</p>" );
29
30            // search for any word ending in 'ow'
31            if ( preg_match( "/([a-zA-Z]*ow)/i", $search, $match ) )
32               print( "<p>Word found ending in 'ow': " .
33                  $match[ 1 ] . "</p>" );
34
35            // search for any words beginning with 't'
36            print( "<p>Words beginning with 't' found: " );
37
38            while ( preg_match( "/(t[[:alpha:]]+)/", $search, $match ) )
39            {
40               print( $match[ 1 ] . " " );
41
42               // remove the first occurrence of a word beginning
43               // with 't' to find other instances in the string
44               $search = preg_replace("/" . $match[ 1 ] . "/", "", $search);
45            } // end while
46
47            print( "</p>" );
48        ?><!-- end PHP script -->
49      </body>
50   </html>

Image

Fig. 19.9. Regular expressions.

19.7.1. Searching for Expressions

Line 15 assigns the string "Now is the time" to variable $search. The condition in line 19 calls function preg_match to search for the literal characters "Now" inside variable $search. If the pattern is found, preg_match returns the length of the matched string—which evaluates to true in a boolean context—and line 20 prints a message indicating that the pattern was found. We use single quotes ('') inside the string in the print statement to emphasize the search pattern. Anything enclosed in single quotes is not interpolated, unless the single quotes are nested in a double-quoted string literal, as in line 16). For example, '$name' in a print statement would output $name, not variable $name’s value.

Function preg_match takes two arguments—a regular-expression pattern to search for and the string to search. The regular expression must be enclosed in delimiters—typically a forward slash (/) is placed at the beginning and end of the regular-expression pattern. By default, preg_match performs a case-sensitive pattern matches. To perform case-insensitive pattern matches you simply place the letter i after the regular-expression pattern’s closing delimiter, as in "/([a-zA-Z]*ow)/i" (line 31).

19.7.2. Representing Patterns

In addition to literal characters, regular expressions can include metacharacters, such as ^, $ and ., that specify patterns. The caret (^) metacharacter matches the beginning of a string (line 23), while the dollar sign ($) matches the end of a string (line 27). The period (.) metacharacter matches any single character except newlines, but can be made to match newlines with the s modifier. Line 23 searches for the pattern "Now" at the beginning of $search. Line 27 searches for "Now" at the end of $search. Note that Now$ is not a variable—it’s a pattern that uses $ to search for the characters "Now" at the end of a string.

Line 31, which contains a bracket expression, searches (from left to right) for the first word ending with the letters ow. Bracket expressions are lists of characters enclosed in square brackets ([]) that match any single character from the list. Ranges can be specified by supplying the beginning and the end of the range separated by a dash (-). For instance, the bracket expression [a-z] matches any lowercase letter and [A-Z] matches any uppercase letter. In this example, we combine the two to create an expression that matches any letter. The  before and after the parentheses indicates the beginning and end of a word, respectively—in other words, we’re attempting to match whole words.

The expression [a-zA-Z]*ow inside the parentheses (line 31) represents any word ending in ow. The quantifier * matches the preceding pattern zero or more times. Thus, [a-zA-Z]*ow matches any number of letters followed by the literal characters ow. Quantifiers are used in regular expressions to denote how often a particular character or set of characters can appear in a match. Some PHP quantifiers are listed in Fig. 19.10.

Image

Fig. 19.10. Some regular expression quantifiers.

19.7.3. Finding Matches

The optional third argument to function preg_match is an array that stores matches to the regular expression. When the expression is broken down into parenthetical sub-expressions, preg_match stores the first encountered instance of each expression in this array, starting from the leftmost parenthesis. The first element (i.e., index 0) stores the string matched for the entire pattern. The match to the first parenthetical pattern is stored in the second array element, the second in the third array element and so on. If the parenthetical pattern is not encountered, the value of the array element remains uninitialized. Because the statement in line 31 is the first parenthetical pattern, Now is stored in variable $match[1] (and, because it’s the only parenthetical statement in this case, it’s also stored in $match[0]).

Searching for multiple instances of a single pattern in a string is slightly more complicated, because the preg_match function returns only the first instance it encounters. To find multiple instances of a given pattern, we must make multiple calls to preg_match, and remove any matched instances before calling the function again. Lines 38–45 use a while statement and the preg_replace function to find all the words in the string that begin with t. We’ll say more about this function momentarily.

19.7.4. Character Classes

The pattern in line 38, /(t[[:alpha:]]+)/i, matches any word beginning with the character t followed by one or more letters. The pattern uses the character class [[:alpha:]] to recognize any letter—this is equivalent to the [a-zA-Z]. Figure 19.11 lists some character classes that can be matched with regular expressions.

Image

Fig. 19.11. Some regular expression character classes.

Character classes are enclosed by the delimiters [: and :]. When this expression is placed in another set of brackets, such as [[:alpha:]] in line 38, it’s a regular expression matching a single character that’s a member of the class. A bracketed expression containing two or more adjacent character classes in the class delimiters represents those character sets combined. For example, the expression [[:upper:][:lower:]]* represents all strings of uppercase and lowercase letters in any order, while [[:upper:]][[:lower:]]* matches strings with a single uppercase letter followed by any number of lowercase characters. The expression ([[:upper:]][[:lower:]])* represents all strings that alternate between uppercase and lowercase characters (starting with uppercase and ending with lowercase).

19.7.5. Finding Multiple Instances of a Pattern

The quantifier + matches one or more consecutive instances of the preceding expression. The result of the match is stored in $match[1]. Once a match is found, we print it in line 40. We then remove it from the string in line 44, using function preg_replace. This function takes three arguments—the pattern to match, a string to replace the matched string and the string to search. The modified string is returned. Here, we search for the word that we matched with the regular expression, replace the word with an empty string, then assign the result back to $search. This allows us to match any other words beginning with the character t in the string and print them to the screen.

19.8. Form Processing and Business Logic

19.8.1. Superglobal Arrays

Knowledge of a client’s execution environment is useful to system administrators who want to access client-specific information such as the client’s web browser, the server name or the data sent to the server by the client. One way to obtain this data is by using a superglobal array. Superglobal arrays are associative arrays predefined by PHP that hold variables acquired from user input, the environment or the web server, and are accessible in any variable scope. Some of PHP’s superglobal arrays are listed in Fig. 19.12.

Image

Fig. 19.12. Some useful superglobal arrays.

Superglobal arrays are useful for verifying user input. The arrays $_GET and $_POST retrieve information sent to the server by HTTP get and post requests, respectively, making it possible for a script to have access to this data when it loads another page. For example, if data entered by a user into a form is posted to a script, the $_POST array will contain all of this information in the new script. Thus, any information entered into the form can be accessed easily from a confirmation page, or a page that verifies whether fields have been entered correctly.

19.8.2. Using PHP to Process HTML5 Forms

Forms enable web pages to collect data from users and send it to a web server for processing. Such capabilities allow users to purchase products, request information, send and receive web-based e-mail, create profiles in online networking services and take advantage of various other online services. The HTML5 form in Fig. 19.13 gathers information to add a user to a mailing list.


 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.13: form.html -->
 4   <!-- HTML form for gathering user input. -->
 5   <html>
 6      <head>
 7         <meta charset = "utf-8">
 8         <title>Sample Form</title>
 9         <style type = "text/css">
10            label  { width: 5em; float: left; }
11         </style>
12      </head>
13      <body>
14         <h1>Registration Form</h1>
15         <p>Please fill in all fields and click Register.</p>
16
17         <!-- post form data to form.php -->
18         <form method = "post" action = "form.php">
19            <h2>User Information</h2>
20
21            <!-- create four text boxes for user input -->
22            <div><label>First name:</label>
23               <input type = "text" name = "fname"></div>
24            <div><label>Last name:</label>
25               <input type = "text" name = "lname"></div>
26            <div><label>Email:</label>
27               <input type = "text" name = "email"></div>
28            <div><label>Phone:</label>
29               <input type = "text" name = "phone"
30                  placeholder = "(555) 555-5555"></div>
31            </div>
32
33            <h2>Publications</h2>
34            <p>Which book would you like information about?</p>
35
36            <!-- create drop-down list containing book names -->
37            <select name = "book">
38               <option>Internet and WWW How to Program</option>
39               <option>C++ How to Program</option>
40               <option>Java How to Program</option>
41               <option>Visual Basic How to Program</option>
42            </select>
43
44            <h2>Operating System</h2>
45            <p>Which operating system do you use?</p>
46
47            <!-- create five radio buttons -->
48            <p><input type = "radio" name = "os" value = "Windows"
49                  checked>Windows
50               <input type = "radio" name = "os" value = "Mac OS X">Mac OS X
51               <input type = "radio" name = "os" value = "Linux">Linux
52               <input type = "radio" name = "os" value = "Other">Other</p>
53
54            <!-- create a submit button -->
55            <p><input type = "submit" name = "submit" value = "Register"></p>
56         </form>
57      </body>
58   </html>

Image

Fig. 19.13. HTML5 form for gathering user input.

The form’s action attribute (line 18) indicates that when the user clicks the Register button, the form data will be posted to form.php (Fig. 19.14) for processing. Using method = "post" appends form data to the browser request that contains the protocol (i.e., HTTP) and the URL of the requested resource (specified by the action attribute). Scripts located on the web server’s machine can access the form data sent as part of the request.

We assign a unique name (e.g., email) to each of the form’s controls. When Register is clicked, each field’s name and value are sent to the web server. Script form.php accesses the value for each field through the superglobal array $_POST, which contains key/value pairs corresponding to name–value pairs for variables submitted through the form. [Note: The superglobal array $_GET would contain these key–value pairs if the form had been submitted using the HTTP get method. In general, get is not as secure as post, because it appends the information directly to the URL, which is visible to the user.] Figure 19.14 processes the data posted by form.html and sends HTML5 back to the client.


Image Good Programming Practice 19.1

Use meaningful HTML5 object names for input fields. This makes PHP scripts that retrieve form data easier to understand.



 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.14: form.php -->
 4   <!-- Process information sent from form.html. -->
 5   <html>
 6      <head>
 7         <meta charset = "utf-8">
 8         <title>Form Validation</title>
 9         <style type = "text/css">
10            p       { margin: 0px; }
11            .error  { color: red }
12            p.head  { font-weight: bold; margin-top: 10px; }
13         </style>
14      </head>
15      <body>
16         <?php
17            // determine whether phone number is valid and print
18            // an error message if not
19            if (!preg_match( "/^([0-9]{3}) [0-9]{3}-[0-9]{4}$/",
20               $_POST["phone"]))                                  
21            {
22               print( "<p class = 'error'>Invalid phone number</p>
23                  <p>A valid phone number must be in the form
24                  (555) 555-5555</p><p>Click the Back button,
25                  enter a valid phone number and resubmit.</p>
26                  <p>Thank You.</p></body></html>" );
27               die(); // terminate script execution
28            }
29         ?><!-- end PHP script -->
30         <p>Hi <?php print( $_POST["fname"] ); ?>. Thank you for
31            completing the survey. You have been added to the
32            <?php print( $_POST["book"] ); ?>mailing list.</p>
33         <p class = "head">The following information has been saved
34            in our database:</p>
35         <p>Name: <?php print( $_POST["fname"] );
36            print( $_POST["lname"] ); ?></p>
37         <p>Email: <?php print( "$email" ); ?></p>
38         <p>Phone: <?php print( "$phone" ); ?></p>
39         <p>OS: <?php print( $_POST["os"] ); ?></p>
40         <p class = "head">This is only a sample form.
41            You have not been added to a mailing list.</p>
42      </body>
43   </html>

Image
Image

Fig. 19.14. Process information sent from form.html.

Lines 19–20 determine whether the phone number entered by the user is valid. We get the phone number from the $_POST array using the expression $_POST["phone"], where "phone" is the name of the corresponding input field in the form. The validation in this example requires the phone number to begin with an opening parenthesis, followed by an area code, a closing parenthesis, a space, an exchange, a hyphen and a line number. It’s crucial to validate information that will be entered into databases or used in mailing lists. For example, validation can be used to ensure that credit card numbers contain the proper number of digits before the numbers are encrypted and sent to a merchant. This script implements the business logic, or business rules, of our application.


Image Software Engineering Observation 19.1

Use business logic to ensure that invalid information is not stored in databases. Validate important or sensitive form data on the server, since JavaScript may be disabled by the client. Some data, such as passwords, must always be validated on the server side.


In lines 19–20, the expression ( matches the opening parenthesis of the phone number. We want to match the literal character (, so we escape its normal meaning by preceding it with the backslash character (). This parenthesis in the expression must be followed by three digits ([0-9]{3}), a closing parenthesis, three more digits, a literal hyphen and four additional digits. Note that we use the ^ and $ symbols to ensure that no extra characters appear at either end of the string.

If the regular expression is matched, the phone number has a valid format, and an HTML5 document is sent to the client that thanks the user for completing the form. We extract each input element’s value from the $_POST array in lines (30–39). Otherwise, the body of the if statement executes and displays an error message.

Function die (line 27) terminates script execution. This function is called if the user did not enter a correct telephone number, since we do not want to continue executing the rest of the script. The function’s optional argument is a string or an integer. If it’s a string, it’s printed as the script exits. If it’s an integer, it’s used as a return status code (typically in command-line PHP shell scripts).

19.9. Reading from a Database

PHP offers built-in support for many databases. Our database examples use MySQL. We assume that you’ve followed the XAMPP installation instructions in Chapter 17 (XAMPP includes MySQL) and that you’ve followed the Chapter 18 instructions for setting up a MySQL user account and for creating the databases we use in this chapter.

The example in this section uses a Products database. The user selects the name of a column in the database and submits the form. A PHP script then builds a SQL SELECT query, queries the database to obtain the column’s data and outputs the data in an HTML5 document that’s displayed in the user’s web browser. Chapter 18 discusses how to build SQL queries.

Figure 19.15 is a web page that posts form data consisting of a selected database column to the server. The script in Fig. 19.16 processes the form data.

HTML5 Document

Line 12 of Fig. 19.15 begins an HTML5 form, specifying that the data submitted from the form will be sent to the script database.php (Fig. 19.16) in a post request. Lines 16–22 add a select box to the form, set the name of the select box to select and set its default selection to *. Submitting * specifies that all rows and columns are to be retrieved from the database. Each of the database’s column names is set as an option in the select box.


 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.15: data.html -->
 4   <!-- Form to query a MySQL database. -->
 5   <html>
 6      <head>
 7         <meta charset = "utf-8">
 8         <title>Sample Database Query</title>
 9      </head>
10      <body>
11         <h1>Querying a MySQL database.</h1>
12         <form method = "post" action = "database.php">
13            <p>Select a field to display:
14               <!-- add a select box containing options -->
15               <!-- for SELECT query -->
16               <select name = "select">
17                  <option selected>*</option>
18                  <option>ID</option>
19                  <option>Title</option>
20                  <option>Category</option>
21                  <option>ISBN</option>
22               </select></p>
23            <p><input type = "submit" value = "Send Query"></p>
24         </form>
25      </body>
26   </html>

Image

Fig. 19.15. Form to query a MySQL database.

database.php

Script database.php (Fig. 19.16) builds a SQL query with the posted field name then queries the MySQL database. Line 25 concatenates the posted field name to a SELECT query. Lines 28–29 call function mysql_connect to connect to the MySQL database. We pass three arguments—the server’s hostname, a username and a password. The host name localhost is your computer. The username and password specified here were created in Chapter 18. Function mysql_connect returns a database handle—a representation of PHP’s connection to the database—which we assign to variable $database. If the connection to MySQL fails, the function returns false and we call die to output an error message and terminate the script. Line 33 calls function mysql_select_db to select and open the database to be queried (in this case, products). The function returns true on success or false on failure. We call die if the database cannot be opened.


 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.16: database.php -->
 4   <!-- Querying a database and displaying the results. -->
 5   <html>
 6      <head>
 7         <meta charset = "utf-8">
 8         <title>Search Results</title>
 9      <style type = "text/css">
10            body  { font-family: sans-serif;
11                    background-color: lightyellow; }
12            table { background-color: lightblue;
13                    border-collapse: collapse;
14                    border: 1px solid gray; }
15            td    { padding: 5px; }
16            tr:nth-child(odd) {
17                    background-color: white; }
18         </style>
19      </head>
20      <body>
21         <?php
22            $select = $_POST["select"]; // creates variable $select
23
24            // build SELECT query
25            $query = "SELECT " . $select . " FROM books";
26
27            // Connect to MySQL
28            if ( !( $database = mysql_connect( "localhost",
29               "iw3htp", "password" ) ) )                  
30               die( "Could not connect to database </body></html>" );
31
32            // open Products database
33            if ( !mysql_select_db( "products", $database ) )
34               die( "Could not open products database </body></html>" );
35
36            // query Products database
37            if ( !( $result = mysql_query( $query, $database ) ) )
38            {
39               print( "<p>Could not execute query!</p>" );
40               die( mysql_error() . "</body></html>" );
41            } // end if
42
43            mysql_close( $database );
44         ?><!-- end PHP script -->
45         <table>
46            <caption>Results of "SELECT <?php print( "$select" ) ?>
47               FROM books"</caption>
48            <?php
49               // fetch each record in result set
50               while ( $row = mysql_fetch_row( $result ) )
51               {
52                  // build table to display results
53                  print( "<tr>" );
54
55                  foreach ( $row as $key => $value )
56                     print( "<td>$value</td>" );   
57
58                  print( "</tr>" );
59               } // end while
60            ?><!-- end PHP script -->
61         </table>
62         <p>Your search yielded
63            <?php print( mysql_num_rows( $result ) ) ?> results.</p>
64         <p>Please email comments to <a href = "mailto:[email protected]">
65               Deitel and Associates, Inc.</a></p>
66      </body>
67   </html>

Image

Fig. 19.16. Querying a database and displaying the results.

To query the database, line 37 calls function mysql_query, specifying the query string and the database to query. If the query fails, the function returns false. Function die is then called with a call to function mysql_error as an argument. Function mysql_error returns any error strings from the database. If the query succeeds, mysql_query returns a resource containing the query result, which we assign to variable $result. Once we’ve stored the data in $result, we call mysql_close in line 43 to close the connection to the database. Function mysql_query can also execute SQL statements such as INSERT or DELETE that do not return results.

Lines 50–59 iterate through each record in the result set and construct an HTML5 table containing the results. The loop’s condition calls the mysql_fetch_row function to return an array containing the values for each column in the current row of the query result ($result). The array is stored in variable $row. Lines 55–56 construct individual cells for each column in the row. The foreach statement takes the name of the array ($row), iterates through each index value of the array and stores the value in variable $value. Each element of the array is then printed as an individual cell. When the result has no more rows, false is returned by function mysql_fetch_row, which terminates the loop.

After all the rows in the result have been displayed, the table’s closing tag is written (line 61). Lines 62–63 display the number of rows in $result by calling mysql_num_rows with $result as an argument.

19.10. Using Cookies

A cookie is a piece of information that’s stored by a server in a text file on a client’s computer to maintain information about the client during and between browsing sessions. A website can store a cookie on a client’s computer to record user preferences and other information that the website can retrieve during the client’s subsequent visits. For example, a website can use cookies to store clients’ zip codes, so that it can provide weather reports and news updates tailored to the user’s region. Websites also can use cookies to track information about client activity. Analysis of information collected via cookies can reveal the popularity of websites or products. Marketers can use cookies to determine the effectiveness of advertising campaigns.

Websites store cookies on users’ hard drives, which raises issues regarding security and privacy. Websites should not store critical information, such as credit card numbers or passwords, in cookies, because cookies are typically stored in text files that any program can read. Several cookie features address security and privacy concerns. A server can access only the cookies that it has placed on the client. For example, a web application running on www.deitel.com cannot access cookies that the website www.pearson.com has placed on the client’s computer. A cookie also has an expiration date, after which the web browser deletes it. Users who are concerned about the privacy and security implications of cookies can disable cookies in their browsers. But, disabling cookies can make it difficult or impossible for the user to interact with websites that rely on cookies to function properly.

The information stored in a cookie is sent back to the web server from which it originated whenever the user requests a web page from that particular server. The web server can send the client HTML5 output that reflects the preferences or information that’s stored in the cookie.

HTML5 Document

Figure 19.17 presents an HTML5 document containing a form in which the user specifies a name, height and favorite color. When the user clicks the Write Cookie button, the cookies.php script (Fig. 19.18) executes.

Writing Cookies: cookies.php

Script cookies.php (Fig. 19.18) calls function setcookie (lines 8–10) to set the cookies to the values posted from cookies.html. The cookies defined in function setcookie are sent to the client at the same time as the information in the HTTP header; therefore, setcookie needs to be called before any other output. Function setcookie takes the name of the cookie to be set as the first argument, followed by the value to be stored in the cookie. For example, line 8 sets the name of the cookie to "Name" and the value to variable $Name, which is passed to the script from cookies.html. The optional third argument indicates the expiration date of the cookie. In this example, we set the cookies to expire in five days by taking the current time, which is returned by function time, and adding the constant FIVE_DAYS—the number of seconds after which the cookie is to expire (60 seconds per minute * 60 minutes per hour * 24 hours per day * 5 = 5 days). If no expiration date is specified, the cookie lasts only until the end of the current session—that is, when the user closes the browser. This type of cookie is known as a session cookie, while one with an expiration date is a persistent cookie. If only the name argument is passed to function setcookie, the cookie is deleted from the client’s computer. Lines 13–35 send a web page to the client indicating that the cookie has been written and listing the values that are stored in the cookie.


 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.17: cookies.html -->
 4   <!-- Gathering data to be written as a cookie. -->
 5   <html>
 6      <head>
 7         <meta charset = "utf-8">
 8         <title>Writing a cookie to the client computer</title>
 9         <style type = "text/css">
10            label { width: 7em; float: left; }
11         </style>
12      </head>
13      <body>
14         <h2>Click Write Cookie to save your cookie data.</h2>
15         <form method = "post" action = "cookies.php">
16            <div><label>Name:</label>
17               <input type = "text" name = "name"><div>
18            <div><label>Height:</label>
19               <input type = "text" name = "height"></div>
20            <div><label>Favorite Color:</label>
21               <input type = "text" name = "Color"></div>
22            <p><input type = "submit" value = "Write Cookie">
23         </form>
24      </body>
25   </html>

Image

Fig. 19.17. Gathering data to be written as a cookie.


Image Software Engineering Observation 19.2

Some clients do not accept cookies. When a client declines a cookie, the browser application normally informs the user that the site may not function correctly without cookies enabled.



Image Software Engineering Observation 19.3

Cookies should not be used to store e-mail addresses, passwords or private data on a client’s computer.



 1   <!-- Fig. 19.18: cookies.php -->
 2   <!-- Writing a cookie to the client. -->
 3   <?php
 4      define( "FIVE_DAYS", 60 * 60 * 24 * 5 ); // define constant
 5
 6      // write each form field's value to a cookie and set the
 7      // cookie's expiration date
 8      setcookie( "name", $_POST["name"], time() + FIVE_DAYS );
 9      setcookie( "height", $_POST["height"], time() + FIVE_DAYS );
10      setcookie( "color", $_POST["color"], time() + FIVE_DAYS );
11   ?><!-- end PHP script -->
12
13   <!DOCTYPE html>
14
15   <html>
16      <head>
17         <meta charset = "utf-8">
18         <title>Cookie Saved</title>
19         <style type = "text/css">
20            p { margin: 0px; }
21         </style>
22      </head>
23      <body>
24         <p>The cookie has been set with the following data:</p>
25
26         <!-- print each form field's value -->
27         <p>Name: <?php print( $Name ) ?></p>
28         <p>Height: <?php print( $Height ) ?></p>
29         <p>Favorite Color:
30            <span style = "color: <?php print( "$Color" ) ?> ">
31            <?php print( "$Color" ) ?></span></p>
32         <p>Click <a href = "readCookies.php">here</a>
33            to read the saved cookie.</p>
34      </body>
35   </html>

Image

Fig. 19.18. Writing a cookie to the client.

Reading an Existing Cookie

Figure 19.19 reads the cookie that was written in Fig. 19.18 and displays the cookie’s information in a table. PHP creates the superglobal array $_COOKIE, which contains all the cookie values indexed by their names, similar to the values stored in array $_POST when an HTML5 form is posted (see Section 19.8).

Lines 18–19 of Fig. 19.19 iterate through the $_COOKIE array using a foreach statement, printing out the name and value of each cookie in a paragraph. The foreach statement takes the name of the array ($_COOKIE) and iterates through each index value of the array ($key). In this case, the index values are the names of the cookies. Each element is then stored in variable $value, and these values become the individual cells of the table. Try closing your browser and revisiting readCookies.php to confirm that the cookie has persisted.


 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.19: readCookies.php -->
 4   <!-- Displaying the cookie's contents. -->
 5   <html>
 6      <head>
 7         <meta charset = "utf-8">
 8         <title>Read Cookies</title>
 9         <style type = "text/css">
10            p { margin: 0px; }
11         </style>
12      </head>
13      <body>
14         <p>The following data is saved in a cookie on your computer.</p>
15         <?php
16            // iterate through array $_COOKIE and print
17            // name and value of each cookie
18            foreach ($_COOKIE as $key => $value )
19               print( "<p>$key: $value</p>" );   
20         ?><!-- end PHP script -->
21      </body>
22   </html>

Image

Fig. 19.19. Displaying the cookie’s contents.

19.11. Dynamic Content

PHP can dynamically change the HTML5 it outputs based on a user’s input. We now build on Section 19.8’s example by combining the HTML5 form of Fig. 19.13 and the PHP script of Fig. 19.14 into one dynamic document. The form in Fig. 19.20 is created using a series of loops, arrays and conditionals. We add error checking to each of the text input fields and inform the user of invalid entries on the form itself, rather than on an error page. If an error exists, the script maintains the previously submitted values in each form element. Finally, after the form has been successfully completed, we store the input from the user in a MySQL database. Once again, we assume that you’ve followed the XAMPP installation instructions in Chapter 17 (XAMPP includes MySQL) and that you’ve followed the Chapter 18 instructions for setting up a MySQL user account and for creating the database MailingList that we use in this example.

Variables

Lines 19–28 create variables that are used throughout the script to fill in form fields and check for errors. Lines 19–24 use the isset function to determine whether the $_POST array contains keys representing the various form fields. These keys exist only after the form is submitted. If function isset returns true, then the form has been submitted and we assign the value for each key to a variable. Otherwise, we assign the empty string to each variable.

Arrays

Lines 31–41 create three arrays, $booklist, $systemlist and $inputlist, that are used to dynamically create the form’s input fields. We specify that the form created in this document is self-submitting (i.e., it posts to itself) by setting the action to the script 'dynamicForm.php' in line 125. [Note: We enclose HTML5 attribute values in the string argument of a print statement in single quotes so that they do not interfere with the double quotes that delimit the string. We could alternatively have used the escape sequence " to print double quotes instead of single quotes.] Line 44 uses function isset to determine whether the Register button has been pressed, in which case the $_POST array will contain the key "submit" (the name of the button in the form). If it has, each of the text input fields’ values is validated. If an error is detected (e.g., a text field is blank or the phone number is improperly formatted), the corresponding entry in array $formerrors is set to true and variable $iserror is set to true. If the Register button has not been pressed, we skip ahead to line 115.


 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.20: dynamicForm.php -->
 4   <!-- Dynamic form. -->
 5   <html>
 6      <head>
 7         <meta charset = "utf-8">
 8         <title>Registration Form</title>
 9         <style type = "text/css">
10            p       { margin: 0px; }
11            .error  { color: red }
12            p.head  { font-weight: bold; margin-top: 10px; }
13            label   { width: 5em; float: left; }
14         </style>
15      </head>
16      <body>
17         <?php
18            // variables used in script
19            $fname = isset($_POST[ "fname" ]) ? $_POST[ "fname" ] : "";
20            $lname = isset($_POST[ "lname" ]) ? $_POST[ "lname" ] : "";
21            $email = isset($_POST[ "email" ]) ? $_POST[ "email" ] : "";
22            $phone = isset($_POST[ "phone" ]) ? $_POST[ "phone" ] : "";
23            $book = isset($_POST[ "book" ]) ? $_POST[ "book" ] : "";   
24            $os = isset($_POST[ "os" ]) ? $_POST[ "os" ] : "";         
25            $iserror = false;
26            $formerrors =
27               array( "fnameerror" => false, "lnameerror" => false,
28                  "emailerror" => false, "phoneerror" => false );
29
30            // array of book titles
31            $booklist = array( "Internet and WWW How to Program",
32               "C++ How to Program", "Java How to Program",
33               "Visual Basic How to Program" );
34
35            // array of possible operating systems
36            $systemlist = array( "Windows", "Mac OS X", "Linux", "Other" );
37
38            // array of name values for the text input fields
39            $inputlist = array( "fname" => "First Name",
40               "lname" => "Last Name", "email" => "Email",
41               "phone" => "Phone" );
42
43            // ensure that all fields have been filled in correctly
44            if ( isset( $_POST["submit"] ) )
45            {
46               if ( $fname == "" )
47               {
48                  $formerrors[ "fnameerror" ] = true;
49                  $iserror = true;
50               } // end if
51
52               if ( $lname == "" )
53               {
54                  $formerrors[ "lnameerror" ] = true;
55                  $iserror = true;
56               } // end if
57
58               if ( $email == "" )
59               {
60                  $formerrors[ "emailerror" ] = true;
61                  $iserror = true;
62               } // end if
63
64               if ( !preg_match( "/^([0-9]{3}) [0-9]{3}-[0-9]{4}$/",
65                  $phone ) )
66               {
67                  $formerrors[ "phoneerror" ] = true;
68                  $iserror = true;
69               } // end if
70
71               if ( !$iserror )
72               {
73                  // build INSERT query
74                  $query = "INSERT INTO contacts " .                     
75                     "( LastName, FirstName, Email, Phone, Book, OS ) " .
76                     "VALUES ( '$lname', '$fname', '$email', " .         
77                     "'" . mysql_real_escape_string( $phone ) .          
78                     "', '$book', '$os' )";                              
79
80                  // Connect to MySQL
81                  if ( !( $database = mysql_connect( "localhost",
82                     "iw3htp", "password" ) ) )
83                     die( "<p>Could not connect to database</p>" );
84
85                  // open MailingList database
86                  if ( !mysql_select_db( "MailingList", $database ) )
87                     die( "<p>Could not open MailingList database</p>" );
88
89                  // execute query in MailingList database
90                  if ( !( $result = mysql_query( $query, $database ) ) )
91                  {
92                     print( "<p>Could not execute query!</p>" );
93                     die( mysql_error() );
94                  } // end if
95
96                  mysql_close( $database );
97
98                  print( "<p>Hi $fname. Thank you for completing the survey.
99                        You have been added to the $book mailing list.</p>
100                    <p class = 'head'>The following information has been
101                       saved in our database:</p>
102                    <p>Name: $fname $lname</p>
103                    <p>Email: $email</p>
104                    <p>Phone: $phone</p>
105                    <p>OS: $os</p>
106                    <p><a href = 'formDatabase.php'>Click here to view
107                       entire database.</a></p>
108                    <p class = 'head'>This is only a sample form.
109                       You have not been added to a mailing list.</p>
110                    </body></html>" );
111                 die(); // finish the page
112              } // end if
113           } // end if
114
115           print( "<h1>Sample Registration Form</h1>
116              <p>Please fill in all fields and click Register.</p>" );
117
118           if ( $iserror )
119           {
120              print( "<p class = 'error'>Fields with * need to be filled
121                 in properly.</p>" );
122           } // end if
123
124           print( "<!-- post form data to dynamicForm.php -->
125              <form method = 'post' action = 'dynamicForm.php'>
126              <h2>User Information</h2>
127
128              <!-- create four text boxes for user input -->" );
129           foreach ( $inputlist as $inputname => $inputalt )
130           {
131              print( "<div><label>$inputalt:</label><input type = 'text'
132                 name = '$inputname' value = '" . $$inputname . "'>" );
133
134              if ( $formerrors[ ( $inputname )."error" ] == true )
135                 print( "<span class = 'error'>*</span>" );       
136
137              print( "</div>" );
138           } // end foreach
139
140           if ( $formerrors[ "phoneerror" ] )
141              print( "<p class = 'error'>Must be in the form
142                 (555)555-5555" );
143
144           print( "<h2>Publications</h2>
145              <p>Which book would you like information about?</p>
146
147              <!-- create drop-down list containing book names -->
148              <select name = 'book'>" );
149
150           foreach ( $booklist as $currbook )
151           {
152              print( "<option" .
153                 ($currbook == $book ? " selected>" : ">") .
154                 $currbook . "</option>" );
155           } // end foreach
156
157           print( "</select>
158              <h2>Operating System</h2>
159              <p>Which operating system do you use?</p>
160
161              <!-- create five radio buttons -->" );
162
163           $counter = 0;
164
165           foreach ( $systemlist as $currsystem )
166           {
167              print( "<input type = 'radio' name = 'os'
168                 value = '$currsystem' " );
169
170              if ( ( !$os && $counter == 0 ) || ( $currsystem == $os ) )
171                 print( "checked" );                                    
172
173              print( ">$currsystem" );
174              ++$counter;
175           } // end foreach
176
177           print( "<!-- create a submit button -->
178              <p class = 'head'><input type = 'submit' name = 'submit'
179              value = 'Register'></p></form></body></html>" );
180     ?><!-- end PHP script -->

Image
Image

Fig. 19.20. Dynamic form.

Dynamically Creating the Form

Line 71 determines whether any errors were detected. If $iserror is false (i.e., there were no input errors), lines 74–111 display the page indicating that the form was submitted successfully—we’ll say more about these lines later. If $iserror is true, lines 74–111 are skipped, and the code from lines 115–179 executes. These lines include a series of print statements and conditionals to output the form, as seen in Fig. 19.20(a).

Lines 129–138 iterate through each element in the $inputlist array. In line 132 the value of $$inputname is assigned to the text field’s value attribute. If the form has not yet been submitted, this will be the empty string "". The notation $$variable specifies a variable variable, which allows the code to reference variables dynamically. You can use this expression to obtain the value of the variable whose name is equal to the value of $variable. PHP first determines the value of $variable, then appends this value to the leading $ to form the identifier of the variable you wish to reference dynamically. (The expression $$variable can also be written as ${$variable} to convey this procedure.) For example, in lines 129–138, we use $$inputname to reference the value of each form-field variable. During the iteration of the loop, $inputname contains the name of one of the text input elements, such as "email". PHP replaces $inputname in the expression $$inputname with the string representing that element’s name forming the expression ${"email"}. The entire expression then evaluates to the value of the variable $email. Thus, the variable $email, which stores the value of the e-mail text field after the form has been submitted, is dynamically referenced. This dynamic variable reference is added to the string as the value of the input field (using the concatenation operator) to maintain data over multiple submissions of the form.

Lines 134–135 add a red asterisk next to the text input fields that were filled out incorrectly. Lines 140–142 display the phone number format instructions in red if the user entered an invalid phone number.

Lines 150–155 and 165–175 generate options for the book drop-down list and operating-system radio buttons, respectively. In both cases, we ensure that the previously selected or checked element (if one exists) remains selected or checked over multiple attempts to correctly fill out the form. If any book was previously selected, line 153 adds selected to its option tag. Lines 170–171 select an operating system radio button under two conditions. If the form is begin displayed for the first time, the first radio button is selected. Otherwise, if the $currsystem variable’s value matches what’s stored in the $os variable (i.e., what was submitted as part of the form), that specific radio button is selected.

Inserting Data into the Database

If the form has been filled out correctly, lines 74–95 place the form information in the MySQL database MailingList using an INSERT statement. Line 77 uses the function mysql_real_escape_string to insert a backslash () before any special characters in the passed string. We must use this function so that MySQL does not interpret the parentheses in the phone number as having a special meaning aside from being part of a value to insert into the database. Lines 98–110 generate the web page indicating a successful form submission, which also provides a link to formDatabase.php (Fig. 19.21).

Displaying the Database’s Contents

The script in Fig. 19.21 displays the contents of the MailingList database using the same techniques that we showed in Fig. 19.16.


 1   <!DOCTYPE html>
 2
 3   <!-- Fig. 19.21: formDatabase.php -->
 4   <!-- Displaying the MailingList database. -->
 5   <html>
 6      <head>
 7         <meta charset = "utf-8">
 8         <title>Search Results</title>
 9         <style type = "text/css">
10            table  { background-color: lightblue;
11                     border: 1px solid gray;
12                     border-collapse: collapse; }
13            th, td { padding: 5px; border: 1px solid gray; }
14            tr:nth-child(even) { background-color: white; }
15            tr:first-child { background-color: lightgreen; }
16         </style>
17      </head>
18      <body>
19         <?php
20            // build SELECT query
21            $query = "SELECT * FROM contacts";
22
23            // Connect to MySQL
24            if ( !( $database = mysql_connect( "localhost",
25               "iw3htp", "password" ) ) )
26               die( "<p>Could not connect to database</p></body></html>" );
27
28            // open MailingList database
29            if ( !mysql_select_db( "MailingList", $database ) )
30               die( "<p>Could not open MailingList database</p>
31                  </body></html>" );
32
33            // query MailingList database
34            if ( !( $result = mysql_query( $query, $database ) ) )
35            {
36               print( "<p>Could not execute query!</p>" );
37               die( mysql_error() . "</body></html>" );
38            } // end if
39         ?><!-- end PHP script -->
40
41         <h1>Mailing List Contacts</h1>
42         <table>
43            <caption>Contacts stored in the database</caption>
44            <tr>
45               <th>ID</th>
46               <th>Last Name</th>
47               <th>First Name</th>
48               <th>E-mail Address</th>
49               <th>Phone Number</th>
50               <th>Book</th>
51               <th>Operating System</th>
52            </tr>
53            <?php
54               // fetch each record in result set
55               for ( $counter = 0; $row = mysql_fetch_row( $result );
56                  ++$counter )
57               {
58                  // build table to display results
59                  print( "<tr>" );
60
61                  foreach ( $row as $key => $value )
62                     print( "<td>$value</td>" );
63
64                  print( "</tr>" );
65               } // end for
66
67               mysql_close( $database );
68            ?><!-- end PHP script -->
69         </table>
70      </body>
71   </html>

Image

Fig. 19.21. Displaying the MailingList database.

19.12. Web Resources

www.deitel.com/PHP/

The Deitel PHP Resource Center contains links to some of the best PHP information on the web. There you’ll find categorized links to PHP tools, code generators, forums, books, libraries, frameworks and more. Also check out the tutorials for all skill levels, from introductory to advanced. Be sure to visit the related Resource Centers on HTML5 (www.deitel.com/html5/) and CSS 3 (www.deitel.com/css3/).

Summary

Section 19.1 Introduction

• PHP (p. 665), or PHP: Hypertext Preprocessor, has become one of the most popular server-side scripting languages for creating dynamic web pages.

• PHP is open source and platform independent—implementations exist for all major UNIX, Linux, Mac and Windows operating systems. PHP also supports a large number of databases.

Section 19.2 Simple PHP Program

• PHP code is embedded directly into HTML5 documents and interpreted on the server.

• PHP script file names end with .php.

• In PHP, code is inserted between the scripting delimiters <?php and ?> (p. 666). PHP code can be placed anywhere in HTML5 markup, as long as the code is enclosed in these delimiters.

• Variables are preceded by a $ (p. 666) and are created the first time they’re encountered.

• PHP statements terminate with a semicolon (;, p. 666).

• Single-line comments (p. 667) which begin with two forward slashes (//). Text to the right of the delimiter is ignored by the interpreter. Multiline comments begin with delimiter /* and end with delimiter */.

• When a variable is encountered inside a double-quoted ("") string, PHP interpolates (p. 667) the variable—it inserts the variable’s value where the variable name appears in the string.

• All operations requiring PHP interpolation execute on the server before the HTML5 document is sent to the client.

Section 19.3 Converting Between Data Types

• PHP variables are loosely typed—they can contain different types of data at different times.

• Type conversions can be performed using function settype (p. 667). This function takes two arguments—a variable whose type is to be changed and the variable’s new type.

• Variables are automatically converted to the type of the value they’re assigned.

• Function gettype (p. 669) returns the current type of its argument.

• Calling function settype can result in loss of data. For example, doubles are truncated when they’re converted to integers.

• When converting from a string to a number, PHP uses the value of the number that appears at the beginning of the string. If no number appears at the beginning, the string evaluates to 0.

• Another option for conversion between types is casting (or type casting, p. 669). Casting does not change a variable’s content—it creates a temporary copy of a variable’s value in memory.

• The concatenation operator (., p. 670) combines multiple strings.

• A print statement split over multiple lines prints all the data that’s enclosed in its parentheses.

Section 19.4 Arithmetic Operators

• Function define (p. 670) creates a named constant. It takes two arguments—the name and value of the constant. An optional third argument accepts a boolean value that specifies whether the constant is case insensitive—constants are case sensitive by default.

• Uninitialized variables have undefined values. In a numeric context, an undefined value evaluates to 0. In a string context, it evaluates to "undef").

• Keywords may not be used as function, method, class or namespace names.

Section 19.5 Initializing and Manipulating Arrays

• PHP provides the capability to store data in arrays. Arrays are divided into elements that behave as individual variables. Array names, like other variables, begin with the $ symbol.

• Individual array elements are accessed by following the array’s variable name with an index enclosed in square brackets ([]).

• If a value is assigned to an array that does not exist, then the array is created. Likewise, assigning a value to an element where the index is omitted appends a new element to the end of the array.

• Function count (p. 674) returns the total number of elements in the array.

• Function array (p. 676) creates an array that contains the arguments passed to it. The first item in the argument list is stored as the first array element (index 0), the second item is stored as the second array element and so on.

• Arrays with nonnumeric indices are called associative arrays (p. 676). You can create an associative array using the operator =>, where the value to the left of the operator is the array index and the value to the right is the element’s value.

• PHP provides functions for iterating through the elements of an array. Each array has a built-in internal pointer (p. 676), which points to the array element currently being referenced. Function reset (p. 676) sets the internal pointer to the first array element. Function key (p. 676) returns the index of the element currently referenced by the internal pointer, and function next (p. 676) moves the internal pointer to the next element.

• The foreach statement (p. 677), designed for iterating through arrays, starts with the array to iterate through, followed by the keyword as (p. 677), followed by two variables—the first is assigned the index of the element and the second is assigned the value of that index. (If only one variable is listed after as, it’s assigned the value of the array element.)

Section 19.6 String Comparisons

• Many string-processing tasks can be accomplished using the equality and relational operators.

• Function strcmp (p. 677) compares two strings. The function returns -1 if the first string alphabetically precedes the second string, 0 if the strings are equal, and 1 if the first string alphabetically follows the second.

Section 19.7 String Processing with Regular Expressions

• A regular expression (p. 678) is a series of characters used for pattern-matching templates in strings, text files and databases.

• Function preg_match (p. 678) uses regular expressions to search a string for a specified pattern. If a pattern is found, it returns the length of the matched string.

• Anything enclosed in single quotes in a print statement is not interpolated (unless the single quotes are nested in a double-quoted string literal).

• Function preg_match receives a regular expression pattern to search for and the string to search.

• Regular expressions can include metacharacters (p. 680) that specify patterns. For example, the caret (^) metacharacter matches the beginning of a string, while the dollar sign ($) matches the end of a string. The period (.) metacharacter matches any single character except newlines.

• Bracket expressions (p. 680) are lists of characters enclosed in square brackets ([]) that match any single character from the list. Ranges can be specified by supplying the beginning and the end of the range separated by a dash (-).

• Quantifiers (p. 680) are used in regular expressions to denote how often a particular character or set of characters can appear in a match.

• The optional third argument to function preg_match is an array that stores matches to each parenthetical statement of the regular expression. The first element stores the string matched for the entire pattern, and the remaining elements are indexed from left to right.

• To find multiple instances of a pattern, multiple calls to preg_match, and remove matched instances before calling the function again by using a function such as preg_replace (p. 681).

• Character classes (p. 681), or sets of specific characters, are enclosed by the delimiters [: and :]. When this expression is placed in another set of brackets, it’s a regular expression matching all of the characters in the class.

• A bracketed expression containing two or more adjacent character classes in the class delimiters represents those character sets combined.

• Function preg_replace (p. 681) takes three arguments—the pattern to match, a string to replace the matched string and the string to search. The modified string is returned.

Section 19.8 Form Processing and Business Logic

• Superglobal arrays (p. 682) are associative arrays predefined by PHP that hold variables acquired from user input, the environment or the web server and are accessible in any variable scope.

• The arrays $_GET and $_POST (p. 685) retrieve information sent to the server by HTTP get and post requests, respectively.

• A script located on a web server can access the form data posted to the script as part of a request.

• Function die (p. 687) terminates script execution. The function’s optional argument is a string to display or an integer to return as the script exits.

Section 19.9 Reading from a Database

• Function mysql_connect (p. 688) connects to the MySQL database. It takes three arguments—the server’s hostname, a username and a password, and returns a database handle (p. 688)—a representation of PHP’s connection to the database, or false if the connection fails.

• Function mysql_select_db (p. 688) specifies the database to be queried, and returns a bool indicating whether or not it was successful.

• To query the database, we call function mysql_query (p. 690), specifying the query string and the database to query. This returns a resource containing the result of the query, or false if the query fails. It can also execute SQL statements such as INSERT or DELETE that do not return results.

• Function mysql_error returns any error strings from the database.

Section 19.10 Using Cookies

• A cookie (p. 691) is a text file that a website stores on a client’s computer to maintain information about the client during and between browsing sessions.

• A server can access only the cookies that it has placed on the client.

• Function setcookie (p. 691) takes the name of the cookie to be set as the first argument, followed by the value to be stored in the cookie. The optional third argument indicates the expiration date of the cookie. A cookie without a third argument is known as a session cookie, while one with an expiration date is a persistent cookie. If only the name argument is passed to function setcookie, the cookie is deleted from the client’s computer.

• Cookies defined in function setcookie are sent to the client at the same time as the information in the HTTP header; therefore, it needs to be called before any HTML5 is printed.

• The current time is returned by function time (p. 691).

• When using Internet Explorer, cookies are stored in a Cookies directory on the client’s machine. In Firefox, cookies are stored in a file named cookies.txt.

• The superglobal array $_COOKIE (p. 693) contains all the cookie values indexed by their names.

Section 19.11 Dynamic Content

• Function isset (p. 695) allows you to find out if a variable has a value.

• A variable variable ($$variable, p. 700) allows the code to reference variables dynamically. You can use this expression to obtain the value of the variable whose name is equal to the value of $variable.

• The mysql_real_escape_string function (p. 700) inserts a backslash () before any special characters in the passed string.

Self-Review Exercises

19.1 State whether each of the following is true or false. If false, explain why.

a. PHP script is never in the same file as HTML5 script.

b. PHP variable names are case sensitive.

c. The settype function only temporarily changes the type of a variable.

d. Conversion between data types happens automatically when a variable is used in a context that requires a different data type.

e. The foreach statement is designed specifically for iterating over arrays.

f. Relational operators can only be used for numeric comparison.

g. The quantifier +, when used in a regular expression, matches any number of the preceding pattern.

h. Function die never takes arguments.

i. Cookies are stored on the server computer.

j. The * arithmetic operator has higher precedence than the + operator.

19.2 Fill in the blanks in each of the following statements:

a. PHP scripts typically have the file extension ________.

b. The two numeric types that PHP variables can store are ________ and ________.

c. ________ are divided into elements, each of which acts like an individual variable.

d. Function ________ returns the total number of elements in an array.

e. A(n) ________ in a regular expression matches a predefined set of characters.

f. Data submitted through the HTTP post method is stored in array ________.

g. Function ________ terminates script execution.

h. ________ can be used to maintain state information on a client’s computer.

Answers to Self-Review Exercises

19.1

a. False. PHP is directly embedded directly into HTML5.

b. True.

c. False. Function settype permanently changes the type of a variable.

d. True.

e. True.

f. False. Relational operators can also be used for alphabetic comparison.

g. False. The quantifier + matches one or more of the preceding pattern.

h. False. Function die has an optional argument—a string to be printed as the script exits.

i. False. Cookies are stored on the client’s computer.

j. True.

19.2

a. .php.

b. int or integer, float or double.

c. Arrays.

d. count.

e. character class.

f. $_POST.

g. die.

h. Cookies.

Exercises

19.3 Identify and correct the error in each of the following PHP code examples:

a. <?php print( "Hello World" ); >

b.

<?phps
   $name = "Paul";
   print( "$Name" );
?><!-- end PHP script -->

19.4 Write a PHP regular expression pattern that matches a string that satisfies the following description: The string must begin with the (uppercase) letter A. Any three alphanumeric characters must follow. After these, the letter B (uppercase or lowercase) must be repeated one or more times, and the string must end with two digits.

19.5 Describe how input from an HTML5 form is retrieved in a PHP program.

19.6 Describe how cookies can be used to store information on a computer and how the information can be retrieved by a PHP script. Assume that cookies are not disabled on the client.

19.7 Write a PHP script named states.php that creates a variable $states with the value "Mississippi Alabama Texas Massachusetts Kansas". The script should perform the following tasks:

a. Search for a word in $states that ends in xas. Store this word in element 0 of an array named $statesArray.

b. Search for a word in $states that begins with k and ends in s. Perform a case-insensitive comparison. Store this word in element 1 of $statesArray.

c. Search for a word in $states that begins with M and ends in s. Store this element in element 2 of the array.

d. Search for a word in $states that ends in a. Store this word in element 3 of the array.

e. Search for a word in $states at the beginning of the string that starts with M. Store this word in element 4 of the array.

f. Output the array $statesArray to the screen.

19.8 Write a PHP script that tests whether an e-mail address is input correctly. Verify that the input begins with series of characters, followed by the @ character, another series of characters, a period (.) and a final series of characters. Test your program, using both valid and invalid e-mail addresses.

19.9 Write a PHP script that obtains a URL and its description from a user and stores the information into a database using MySQL. Create and run a SQL script with a database named URL and a table named Urltable. The first field of the table should contain an actual URL, and the second, which is named Description, should contain a description of the URL. Use www.deitel.com as the first URL, and input Cool site! as its description. The second URL should be www.php.net, and the description should be The official PHP site. After each new URL is submitted, print the contents of the database in a table. [Note: Follow the instructions in Section 18.5.2 to create the Url database by using the URLs.sql script that’s provided with this chapter’s examples in the dbscripts folder.]

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.238.76