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.
19.3 Converting Between Data Types
19.5 Initializing and Manipulating Arrays
19.7 String Processing with Regular Expressions
19.7.1 Searching for Expressions
19.7.5 Finding Multiple Instances of a Pattern
19.8 Form Processing and Business Logic
19.8.2 Using PHP to Process HTML5 Forms
Summary | Self-Review Exercises | Answers to Self-Review Exercises | Exercises
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.
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.
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 (;
).
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.
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>
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.
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>
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.
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.
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.
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.
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.
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>
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 (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.
Figure 19.6 contains the operator precedence chart for PHP. The operators are shown from top to bottom in decreasing order of precedence.
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) print
s 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>
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 print
s 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
.
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>
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>
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 print
s 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).
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.
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.
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.
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).
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.
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.
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.
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>
The form
’s action
attribute (line 18) indicates that when the user clicks the Register button, the form
data will be post
ed 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 post
ed by form.html
and sends HTML5 back to the client.
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>
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.
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).
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 post
s form data consisting of a selected database column to the server. The script in Fig. 19.16 processes the form data.
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>
database.php
Script database.php
(Fig. 19.16) builds a SQL query with the post
ed field name then queries the MySQL database. Line 25 concatenates the post
ed 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>
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.
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.
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.
cookies.php
Script cookies.php
(Fig. 19.18) calls function setcookie
(lines 8–10) to set the cookies to the values post
ed 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>
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.
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>
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>
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.
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.
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 post
s 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 -->
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.
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).
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>
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/).
• 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.
• 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.
• 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.
• 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.
• 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.)
• 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.
• 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.
• 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.
• 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.
• 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.
• 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.
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.
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.
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.]
3.139.238.76