PHP Basics

144
PHP Basics In this lesson of the PHP tutorial, you will learn... 1. How PHP works. 2. To write a simple PHP page. 3. To understand and work with simple PHP variables. 4. To use PHP operators. 5. To pass values from one page to another via the URL. How PHP Works When a user navigates in her browser to a page that ends with a .php extension, the request is sent to a web server, which directs the request to the PHP interpreter.

Transcript of PHP Basics

Page 1: PHP Basics

PHP BasicsIn this lesson of the PHP tutorial, you will learn...

1. How PHP works. 2. To write a simple PHP page.

3. To understand and work with simple PHP variables.

4. To use PHP operators.

5. To pass values from one page to another via the URL.

How PHP WorksWhen a user navigates in her browser to a page that ends with a .php extension, the request is sent to a web server, which directs the request to the PHP interpreter.

As shown in the diagram above, the PHP interpreter processes the page, communicating with file systems, databases, and email servers as necessary, and then delivers a web page to the web server to return to the browser.

Page 2: PHP Basics

The php.ini FileBefore we look at PHP syntax, we should briefly mention the php.ini file. This is a plain text file that is used to configure PHP. When the PHP interpreter is started, it reads the php.ini file to determine what settings to use. We will mention this file from time to time throughout the course, but for now, it is enough that you are aware of its existence.

Basic PHP SyntaxPHP Tags

PHP code must be contained in special tags so that the PHP interpreter can identify it. Depending on the PHP configuration, these tags can take several forms:

<?php PHP CODE GOES IN HERE?>

This is the most commonly used (and recommended) form. It is known as the XML style, because it can be used inside of an XML document without causing the document to become poorly formed.

<script language="php"> PHP CODE GOES IN HERE</script>

HTML or Script style tags.

<? PHP CODE GOES HERE?>

"Short" tags. (see footnote)

<% PHP CODE GOES HERE%>

ASP-style tags. (see footnote)

In this manual, we will use the first form shown as it is the most common and the most portable.

PHP Statements and Whitespace

PHP statements must be inside of PHP tags to be processed by the PHP interpreter. Each PHP statement must end with a semi-colon, which tells the PHP interpreter that the statement is complete. If a semi-colon does not appear at the end of a line, the interpreter will assume that the statement continues onto the next line.

Page 3: PHP Basics

The PHP interpreter condenses all sequential whitespace in PHP scripts to a single whitespace. This convenient feature allows PHP developers to structure their code in a readable format without being concerned about the effects of line breaks and tabs.

Comments

PHP has two forms of comments:

Single-line comments begin with a double slash (//). Multi-line comments begin with "/*" and end with "*/".

Syntax// This is a single-line comment

/* This is a multi-line comment.*/

PHP Functions

There are literally hundreds of built-in PHP functions that do everything from returning the current date and time on the server to pulling data out of a database. A function might take zero arguments (e.g, phpinfo(), which returns information on the PHP environment) or it might take several arguments (e.g, mail(), which takes three required and two optional arguments). The syntax for calling a function is straightforward:

Syntax

function_name(arguments);

The example below shows how the phpinfo() function works.

Code Sample: PhpBasics/Demos/PhpInfo.php<html><head><title>PHPINFO</title></head><body><?php //Output information on the PHP environment phpinfo();?></body></html>

Page 4: PHP Basics

Introduction to php.net

PHP functions are well documented at http://www.php.net. You can quickly look up documentation on a function by going to http://www.php.net/function_name. For example, to see documentation on phpinfo(), go to http://www.php.net/phpinfo. (see footnote)

Hello World!

It is an unwritten rule that every programming course must contain a "Hello World!" script. Here it is:

Code Sample: PhpBasics/Demos/HelloWorld.php<html><head><title>Hello World!</title></head><body><?php //Write out Hello World! echo 'Hello World!';?></body></html>Code Explanation

Notice the following about the above code:

Code between <?php and ?> is processed by the PHP interpreter. The echo command is used to print text back to the browser.

This code isn't very exciting. In fact, PHP doesn't buy us anything here as we could have just as easily output the result using straight HTML. There is nothing dynamic about this script. After learning about variables, we'll take a look at some more interesting examples.

VariablesPHP variables begin with a dollar sign ($) as shown below.

Syntax

$var_name = "Value";

Page 5: PHP Basics

Variable TypesVariable Type Explanation

Integer whole number

Double real number

String string of characters

Boolean true or false

Array list of items

Object instance of a class

Variable Names (Identifiers (see footnote)) consist of letters, digits, underscores and dollar signs cannot begin with a digit

are case sensitive

Type Strength

PHP is weakly typed, meaning that variables do not need to be assigned a type (e.g, Integer) at the time they are declared. Rather, the type of a PHP variable is determined by the value the variable holds and the way in which it is used.

Hello Variables!

Here is the "Hello World!" script again, but this time we use a variable.

Code Sample: PhpBasics/Demos/HelloVariables.php<?php $Greeting = 'Hello World!';?><html><head><title><?php echo $Greeting; ?></title></head><body><?php echo $Greeting;?></body></html>Code Explanation

Page 6: PHP Basics

This time the string "Hello World!" is stored in the $Greeting variable, which is output in the title and body of the page with an echo command.

Exercise: First PHP ScriptDuration: 5 to 10 minutes.

In this exercise, you will write a simple PHP script from scratch. The script will declare a variable called $Today that stores the day of the week.

1. Open a new document and save it as Today.php in the PhpBasics/Exercises folder. 2. Declare a variable called $Today that holds the current day of the week as literal text.

3. Output $Today in the title and body of the page.

4. Test your solution in a browser. The resulting HTML page should look like this:

Instead of assigning a literal string (e.g, "Monday") to $Today, use the built-in date() function so that the script won't have to be manually updated every day to stay current. For documentation, visit http://www.php.net/date.

Variable Scope

A variable's scope determines the locations from which the variable can be accessed. PHP variables are either superglobal, global, or local.

Variable Scope

Explanation

superglobalSuperglobal variables are predefined arrays, including $_POST and $_GET. They are accessible from anywhere on the page.

Page 7: PHP Basics

Variable Scope

Explanation

globalGlobal variables are visible throughout the script in which they are declared. However, they are not visible within functions in the script unless they are re-declared within the function as global variables.

functionVariables in the function scope are called local variables. Local variables are local to the function in which they are declared.

Superglobals

Again, superglobal variables are predefined arrays, including $_POST and $_GET and are accessible from anywhere on the page. The complete list of superglobals is shown below.

$_GET - variables passed into a page on the query string. $_POST - variables passed into a page through a form using the post method.

$_SERVER - server environment variables (e.g, $_SERVER['HTTP_REFERER'] returns the URL of the referring page).

$_COOKIE - cookie variables.

$_FILES - variables containing information about uploaded files.

$_ENV - PHP environment variables (e.g, $_ENV['HTTP_HOST'] returns the name of the host server. (see footnote)

$_REQUEST - variables passed into a page through forms, the query string and cookies.

$_SESSION - session variables.

The elements within superglobal variables can be accessed in three different ways, which the authors of PHP and MySQL Web Development refer to as short style, medium style, and long style. (see footnote)

Style Syntax (using $_GET) Notes

Short $varname Convenient, but it makes it difficult to distinguish

superglobal variables from other variables in the code.

Requires register_globals config setting to be on.

Medium $_GET['varname']

Recommended approach.

Happy medium between convenience and clarity.

Not available before v. 4.1.

Page 8: PHP Basics

Style Syntax (using $_GET) Notes

Long $HTTP_GET_VARS['varname']

Inconvenient to type.

Deprecated, but still supported in current versions.

Can be disabled via the register_long_arrays directive in the php.ini file.

Many of these superglobals will be covered later in the course.

Constants

Constants are like variables except that, once assigned a value, they cannot be changed. Constants are created using the define() function and by convention (but not by rule) are in all uppercase letters. Constants can be accessed from anywhere on the page.

Syntax

define('CONST_NAME',VALUE);

Variable-Testing and Manipulation Functions (see footnote)

PHP provides built-in functions for checking if a variable exists, checking if a variable holds a value, and removing a variable. (see footnote)

Function Explanation Example

isset() Checks to see if a variable exists. Returns true or false. isset($a)

unset() Removes a variable from memory. unset($a)

empty() Checks to see if a variable contains a non-empty, non-false value. empty($a)

PHP OperatorsOperators in PHP are similar to those found in many modern C-like programming languages.

Mathematical Operators

Operator Name Example

+ Addition $a + $b

Page 9: PHP Basics

Mathematical Operators

Operator Name Example

- Subtraction $a - $b

* Multiplication $a * $b

/ Division $a / $b

% Modulus $a % $b

String Operators

Operator Name Example

. Concatenation $a . $b'Hello' . ' world!'

Assignment Operators

Operator Name Example

= Assignment $a = 1;$c = 'Hello' . ' world!';

+=-=*=/=%=.=

Combination Assignment

$a += 1;$a -= 1;$a *= 2;$a /= 2;$a %= 2;$a .= ' world!';

++ Increment By One $a++;++$a;

-- Decrement By One $a--;--$a;

Other Operators

Operator Name Example

?: Ternary $foo = ($age >= 18) ? 'adult' : 'child';

@ Error Suppression $a = @(1/0);

Creating Dynamic Pages

Page 10: PHP Basics

Single Quotes vs. Double Quotes

In PHP, for simple strings you can use single quotes and double quotes interchangeably. However, there is one important difference of which you need to be aware. Text within single quotes will not be parsed for variables and escape sequences (see footnote). Compare the examples below.

Code Sample: PhpBasics/Demos/SingleQuotes.php<html><head><title>Single Quotes</title></head><body><?php $person = 'George'; echo '\tHello\n$person!!';?></body></html>

Because of the use of single quotes above, the string "\tHello\n$person!!" will be output literally, as shown below.

Code Sample: PhpBasics/Demos/DoubleQuotes.php<html><head><title>Single Quotes</title></head>

Page 11: PHP Basics

<body><?php $person = "George"; echo "\tHello\n$person!!";?></body></html>

This time, because of the double quotes, the string will be parsed for variables and special characters and will be output as shown below.

To see the effect of the special characters (\n and \t), you will have to view the source of the resulting page.

Passing Variables on the URL

A common way to pass values from the browser to the server is by appending them to the URL as follows:

Syntax

http://www.webucator.com/hello.php?greet=Hello&who=World

The part of the URL that follows the question mark is called the query string. One or more name-value pairs can be passed to the server in this way. Each name-value pair is separated by an ampersand (&). The processing page can read these name-value pairs and use them to determine its response.

Page 12: PHP Basics

The HTML page below shows an example of how these name-value pairs might be passed.

Code Sample: PhpBasics/Demos/HelloHi.html<html><head> <title>Preferred Greeting</title></head><body> Do you prefer a formal greeting or an informal greeting? <ul> <li><a href="HelloHi.php?greet=Hello">Formal</a></li> <li><a href="HelloHi.php?greet=Hi">Informal</a></li> <li><a href="HelloHi.php?greet=Howdy">Friendly</a></li> </ul></body></html>

Code Sample: PhpBasics/Demos/HelloHi.php<?php //Assign the passed variable to a variable with //a more convenient name. $greeting = $_GET['greet'];?>

<html><head> <title><?= $greeting ?> World!</title></head><body><?php echo "$greeting World!";?></body></html>Code Explanation

Notice the following about the code above.

Variable names begin with a dollar sign ($). Values passed in the query string are part of the $_GET array and can be accessed using the

following syntax: $_GET['fieldname'].

A shortcut for echo 'text to print'; is <?= 'text to print' ?>. (see footnote)

Exercise: Passing Variables via the Query StringDuration: 10 to 15 minutes.

In this exercise, you will write a script that says hello to different people based on what is passed through the query string.

Page 13: PHP Basics

1. Open PhpBasics/Exercises/HelloWho.html in your editor. You will see that it is the same as the demo we looked at earlier.

2. Modify HelloWho.html so that it has four links, each of which passes the name of one of the Beatles (Paul, John, George, and Ringo) to HelloWho.php, which is in the same directory.

3. Open PhpBasics/Exercises/HelloWho.php in your editor. Modify the code so that it outputs a greeting based on the link clicked on HelloWho.html.

4. Try it out in your browser.

Change the links so that each Beatle gets a custom greeting (e.g, Howdy Paul, Hi John, Bye George, Hey Ringo).

Where is the solution?

PHP Basics ConclusionIn this lesson of the PHP tutorial, you have learned how to write a simple PHP page, to recognize and look up documentation on PHP functions, to work with variables and to pass variables from one page to another via the query string.

Footnotes1. Must be enabled via the short_open_tag php.ini configuration file directive.2. Must be enabled via the asp_tags php.ini configuration file directive.

3. Another very good function reference is located at http://www.phpdig.net/ref/.

4. Variable, function and class names are all identifiers and all follow the rules above, with the exception that function names are not case sensitive.

5. Which environment variables are available depends on the specific server setup and configuration.

6. PHP & MySQL Web Development, Third Edition, p. 21-22

7. For a complete list of variable functions see http://www.php.net/manual/en/ref.variables.php.

8. To output the results of these functions to a browser, use the var_dump() function (e.g. var_dump(isset($a));).

Page 14: PHP Basics

9. Escape sequences are used for characters that cannot easily be output within strings. Common escape sequences are \n for a newline, \t for a tab, \\ for a backaslash, \" for a double quote, and \$ for a dollar sign.

10. Many PHP developers feel that it is best practice to avoid using this shortcut syntax for echo. One reason for this is that the shortcut syntax makes the resulting PHP file impossible to parse as XML.

Flow ControlIn this lesson of the PHP tutorial, you will learn...

1. To work with if-elseif-else conditions in PHP. 2. To work with switch/case statements in PHP.

3. To work with loops in PHP.

Conditional ProcessingConditional processing allows programmers to output different code based on specific conditions. There are two conditional structures in PHP - if-elseif-else and switch/case.

If Conditions

Simple if statementSyntax

if (conditions) Do this;

In the above code, the Do this; statement will either run or not run depending on whether or not the conditions are true. This syntax can only be used when the condition affects a single line of code. For a block of code, use the following syntax.

Syntax

if (conditions){ Do this; Then do this; And this too;}

Page 15: PHP Basics

The lines of code affected by the if condition are put in a code block, which is surrounded by curly brackets to indicate that all of the code either should or should not be executed, depending on the result of the if condition.

if-else statementSyntax

if (conditions){ Do this;}else{ Do that;}

if-elseif-else statementSyntax

if (conditions){ Do this;}elseif (other conditions){ Do that;}else{ Do this other thing;}

The two syntax blocks above show an if-else and an if-elseif-else statement, which can have any number of elseif blocks.

The following table shows PHP's comparison operators.

Comparison Operators

Operator Description

== Equals

!= Doesn't equal

> Is greater than

< Is less than

>= Is greater than or equal to

Page 16: PHP Basics

Comparison Operators

Operator Description

<= Is less than or equal to

=== Identical (same value and same type)

!== Not Identical

The following example demonstrates an if-elseif-else statement.

Code Sample: FlowControl/Demos/If.php<html><head><title>if-elseif-else</title></head><body><?php$Age = 21;if ($Age >= 21) { echo 'You can vote and drink!';} elseif ($Age >= 18){ echo 'You can vote, but can\'t drink.';} else { echo 'You cannot vote or drink.';}?></body></html>Code Explanation

The file is relatively simple. You can see the different results by changing the value of $Age.

Compound If Statements

More complex if statements often require that several conditions be checked. The table below shows and and or operators for checking multiple conditions and the not operator for negating a boolean value (i.e, turning true to false or vice versa).

Page 17: PHP Basics

Logical Operators

Operator Name Example

&& AND $a && $b

|| OR $a || $b

! NOT !$b

The following example shows these logical operators in practice.

Code Sample: FlowControl/Demos/If2.php<html><head><title>if-elseif-else</title></head><body><?php$Age = 21;$Citizen = false;if ($Age >= 21 && !$Citizen) { echo 'You can drink, but can\'t vote.';} elseif ($Age >= 21) { echo 'You can vote and drink!';} elseif ($Age >= 18 && $Citizen){ echo 'You can vote, but can\'t drink.';} else { echo 'You cannot vote or drink.';}?></body></html>

switch/case

A switch/case statement is similar to an if statement, except that it can only check for an equality comparison of a single expression. It cannot, for example, be used to check if one value is higher than another.

Syntax

switch (expression){

Page 18: PHP Basics

case 'a' : echo 'expression is a'; break; case 'b' : echo 'expression is b'; break; case 'c' : echo 'expression is c'; break; default : echo 'expression is unknown'; break;}

The break statement is important. Without it, after a single match is found, all following statements will execute.

The following example demonstrates a switch/case statement without break statements.

Code Sample: FlowControl/Demos/Switch.php<html><head><title>switch/case</title></head><body><?php$Quantity = 1;switch ($Quantity){ case 1 : echo 'Quantity is 1'; case 2 : echo 'Quantity is 2'; default : echo 'Quantity is not 1 or 2';}?></body></html>Code Explanation

The screenshot below shows the result.

Page 19: PHP Basics

Notice that, once a match is found, all remaining echo statements are output. The following example shows how this can be fixed by adding break statements.

Code Sample: FlowControl/Demos/SwitchWithBreak.php<html><head><title>switch/case</title></head><body><?php$Quantity = 1;switch ($Quantity){ case 1 : echo 'Quantity is 1'; break; case 2 : echo 'Quantity is 2'; break; default : echo 'Quantity is not 1 or 2';}?></body></html>Code Explanation

This time, only the first statement is output:

Page 20: PHP Basics

Exercise: Working with ConditionsDuration: 20 to 30 minutes.

In this exercise, you will create a page for handling a simple form submission.

1. Open FlowControl/Exercises/Greeting.html in your editor and review the code. This is the form that will be submitted. Filled out, it looks like this:

1. This form is submitted using the get method (see footnote), which means the form entries will be appended to the query string and will be accessible in the $_GET array.

2. Open FlowControl/Exercises/Greeting.php in your editor.

3. Insert a PHP block that checks to see if the user filled out both the LastName and the Gender fields in the form.

Page 21: PHP Basics

o If the user failed to fill out either one of the fields, write out an error message to the screen.

o If the user filled out both fields, return a gender-appropriate greeting such as "Hello Mr. Dunn!" or "Hello Ms. Dunn!" If the gender is not recognizable (e.g, not male or female), return an error message.

4. Try to use both an if condition and a switch statement in this exercise.

5. When you are done, test your solution in your browser.

It is likely that your solution does not take into account different cases for the gender. For example, "MALE" and "FEMALE" may not be recognized as valid genders. Try to find the function at http://www.php.net that can be used for converting the user's entry to all lowercase letters and use that function to make the gender check case insensitive.

LoopsAs the name implies, loops are used to loop (or iterate) over code blocks. The following section shows the syntax for different types of loops. Each loop will return "12345".

There are several types of loops in PHP.

while do...while

for

foreach (see footnote)

while

while loops are used to execute a block of code repeatedly while one or more conditions is true.

Syntax

$a=1;while ($a < 6){ echo $a; $a++;}

do...while

do...while loops are used to execute a block of code repeatedly until one or more conditions is found to be false. The difference between while loops and do...while loops is that the condition is

Page 22: PHP Basics

checked after the code block is executed. This means that, in a do...while loop, the code block will always be executed at least once.

Syntax

$a=1;do{ echo $a; $a++;}while ($a < 6);

for

A for loop takes three expressions separated by semi-colons and grouped in parentheses before the block to be iterated through.

1. The first expression is executed once before the loop starts. It is usually used to initialize the conditions.

2. The second expression is evaluated before each iteration through the loop. If it evaluates to false, the loop ends.

3. The third expression is executed at the end of each iteration through the loop. It is usually used to make changes that can affect the second expression.

Syntaxfor ($a=1; $a < 6; $a++){ echo $a;}

break and continue

To break out of a loop, insert a break statement.

Syntax

for ($a=1; $a < 6; $a++){ echo $a; if ($a > 3) { break; }}

To jump to the next iteration of a loop without executing the remaining statements in the block, insert a continue statement.

Page 23: PHP Basics

Syntax

for ($a=1; $a < 6; $a++){ if ($a == 3) { continue; } echo $a;}

Exercise: Working with LoopsDuration: 10 to 15 minutes.

1. Open FlowControl/Exercises/Loops.php in your editor. 2. Under the while header, use a while loop to output all the even numbers that are less than or

equal to 100.

3. Under the for header, use a for loop to output all the odd numbers that are less than or equal to 100.

In both loops, skip all numbers that are divisible by 3. Be careful not to get caught in an infinite loop.

ArraysIn this lesson of the PHP tutorial, you will learn...

1. To work with indexed arrays. 2. To work with associative arrays.

3. To work with two-dimensional arrays.

4. To work with array-manipulation functions.

Up to this point, we have dealt only with variables that store single values, called scalar variables. In this lesson, we will be covering arrays. Arrays are variables that store sets of values.

Indexed ArraysIndexed arrays are similar to tables with a single column. An indexed array can contain zero or more elements. In PHP, like in many programming languages, the first element of an array is in the "zeroeth" position. An array with no elements has a zero length.

Page 24: PHP Basics

Initializing Arrays

Arrays are initialized with the array() function, which can take a list of comma-delimited values that become the elements in the new array. The following lines of code initializes a zero-length array and then adds four elements to the array.

Syntax

$Beatles = array();$Beatles[0] = 'John';$Beatles[1] = 'Paul';$Beatles[2] = 'George';$Beatles[3] = 'Ringo';

The first line above is actually optional as the second line will create the array if one does not already exist. However, it is a better coding practice to explicitly initialize the array. The $Beatles array could also be created in a single line as follows.

Syntax

$Beatles = array('John','Paul','George','Ringo');

Appending to an Array

If you know how many elements are in an array, you can append to the array by specifying the index. For example, you could append to the $Beatles array shown above as follows:

Syntax

$Beatles[5] = 'Nat';

However, sometimes you don't know how many elements are in an array. Although you can easily figure this out, doing so requires an extra step. PHP provides an easy way of appending to an array of any length. Simply leave out the index.

Syntax

$Beatles[] = 'Nat';

Reading from Arrays

Reading from arrays is just a matter of pointing to a specific index or key.

Syntax

echo $Beatles[2]; //outputs George to the browser

Page 25: PHP Basics

Looping through Arrays

The following code will loop through the entire $Beatles array outputting each element to the browser.

Syntax

foreach ($Beatles as $Beatle){ echo "$Beatle<br>";}

The above code snippets are combined in the following example.

Code Sample: Arrays/Demos/IndexedArrays.php<html><head><title>Indexed Arrays</title></head>

<body><h1>Indexed Arrays</h1><?php $Beatles = array(); $Beatles[0] = 'John'; $Beatles[1] = 'Paul'; $Beatles[2] = 'George'; $Beatles[3] = 'Ringo'; echo $Beatles[2]; //outputs George to the browser $Beatles[] = 'Nat';?><hr/><?php foreach ($Beatles as $Beatle) { echo "$Beatle<br/>"; }?></body></html>

Exercise: Working with Indexed ArraysDuration: 10 to 15 minutes.

In this exercise, you will use arrays to create a table with a single column that lists all your favorite colors. (see footnote) As shown in the screenshot below, the background of each table row should be the same as the color named in the row.

Page 26: PHP Basics

1. Open Arrays/Exercises/ColorTable.php for editing. 2. Create an array that holds your favorite colors.

3. Inside of the open and close <table> tags, loop through the array outputting a table row for each element.

4. Test your solution in a browser.

Associative ArraysWhereas indexed arrays are indexed numerically, associative arrays are indexed using names. For example, instead of Ringo being indexed as 3, he could be indexed as "drummer".

Initializing Associative Arrays

Like with indexed arrays, we can intialize a zero-length associative array and then add elements.

Syntax

$Beatles = array();$Beatles['singer1'] = 'Paul';$Beatles['singer2'] = 'John';$Beatles['guitarist'] = 'George';$Beatles['drummer'] = 'Ringo';

Or the array could be created in a single line as follows.

Page 27: PHP Basics

Syntax

$Beatles = array('singer1' => 'John', 'singer2' => 'Paul', 'guitarist' => 'George', 'drummer' => 'Ringo');

Reading from Associative Arrays

Reading from associative arrays is as simple as reading from indexed arrays.

Syntax

echo $Beatles['drummer']; //outputs Ringo to the browser

Looping through Associative Arrays

The following code will loop through the entire $Beatles array outputting each element and its key to the browser.

Syntax

foreach ($Beatles as $key => $Beatle){ echo "<b>$key:</b> $Beatle<br>";}

The above code snippets are combined in the following example.

Code Sample: Arrays/Demos/AssociativeArrays.php<html><head><title>Associative Arrays</title></head>

<body><h1>Associative Arrays</h1><?php $Beatles = array('singer1' => 'John', 'singer2' => 'Paul', 'guitarist' => 'George', 'drummer' => 'Ringo');

echo $Beatles['drummer']; //outputs Ringo to the browser?><hr/><?php foreach ($Beatles as $key => $Beatle) { echo "<b>$key:</b> $Beatle<br/>"; }?>

Page 28: PHP Basics

</body></html>

Superglobal Arrays

The superglobal arrays are associative arrays. The file below outputs all the contents of the superglobal arrays using foreach loops.

Code Sample: Arrays/Demos/SuperGlobals.php<?php session_start();?><html><head><title>Superglobal Arrays</title></head>

<body><h1>Superglobal Arrays</h1><h2>$_COOKIE</h2><ol><?php foreach ($_COOKIE as $key => $item) { echo "<li><b>$key:</b> $item<br/></li>"; }?></ol><hr/><h2>$_ENV</h2><ol><?php foreach ($_ENV as $key => $item) { echo "<li><b>$key:</b> $item<br/></li>"; }?></ol><hr/><h2>$_FILES</h2><ol><?php foreach ($_FILES as $key => $item) { echo "<li><b>$key:</b> $item<br/></li>"; }?></ol><hr/><h2>$_GET</h2><ol><?php foreach ($_GET as $key => $item) { echo "<li><b>$key:</b> $item<br/></li>";

Page 29: PHP Basics

}?></ol><hr/><h2>$_POST</h2><ol><?php foreach ($_POST as $key => $item) { echo "<li><b>$key:</b> $item<br/></li>"; }?></ol><hr/><h2>$_REQUEST</h2><ol><?php foreach ($_REQUEST as $key => $item) { echo "<li><b>$key:</b> $item<br/></li>"; }?></ol><hr/><h2>$_SESSION</h2><ol><?php foreach ($_SESSION as $key => $item) { echo "<li><b>$key:</b> $item<br/></li>"; }?></ol><hr/><h2>$_SERVER</h2><ol><?php foreach ($_SERVER as $key => $item) { echo "<li><b>$key:</b> $item<br/></li>"; }?></ol></body></html>

Don't worry about the session_start() statement at the top. We'll cover that in detail later in the course.

Exercise: Working with Associative ArraysDuration: 10 to 15 minutes.

Page 30: PHP Basics

In this exercise, you will use arrays to create a table with two columns that lists all your favorite colors and their hexadecimal equivalents. The background of each table row should be the same as the color named in the row as shown in the screenshot below.

1. Open Arrays/Exercises/ColorTable2.php for editing. 2. Create an associative array that holds your favorite colors indexed by their hex codes,

which can be found at http://www.w3schools.com/html/html_colornames.asp.

3. After the existing table row, write code to loop through the array outputting a table row with two columns for each element in the array.

4. Test your solution in a browser.

Two-dimensional ArraysIn PHP, two-dimensional arrays are arrays that contain arrays. You can think of the outer array as containing the rows and the inner arrays as containing the data cells in those rows. For example, a two-dimensional array called $Rockbands could contain the names of the bands and some of the songs that they sing. Below is a grid that represents such a two-dimensional array.

Rockband Song1 Song2 Song3

Beatles Love Me Do Hey Jude Helter Skelter

Page 31: PHP Basics

Rockband Song1 Song2 Song3

Rolling Stones Waiting on a Friend Angie Yesterday's Papers

Eagles Life in the Fast Lane Hotel California Best of My Love

The following code creates this two-dimensional array. The internal arrays are highlighted. Note that the header row is not included.

Syntax

$Rockbands = array( array('Beatles','Love Me Do', 'Hey Jude','Helter Skelter'), array('Rolling Stones','Waiting on a Friend','Angie', 'Yesterday\'s Papers'), array('Eagles','Life in the Fast Lane','Hotel California', 'Best of My Love'))

Reading from Two-dimensional Arrays

To read an element from a two-dimensional array, you must first identify the index of the "row" and then identify the index of the "column." For example, the song "Angie" is in row 1, column 2, (see footnote) so it is identified as $Rockbands[1][2].

Looping through Two-dimensional Arrays

To loop through a two-dimensional array, you need to nest one loop inside of another. The following code will create an HTML table from our two-dimensional array.

Syntax

<table border="1"><?phpforeach($Rockbands as $Rockband){ echo "<tr>"; foreach($Rockband as $item) { echo "<td>$item</td>"; } echo "</tr>";}?></table>

The above code snippets are combined in the following example to output a Rockbands table.

Page 32: PHP Basics

Code Sample: Arrays/Demos/TwoDimensionalArrays.php<html><head><title>Two-dimensional Arrays</title></head>

<body><h1>Two-Dimensional Arrays</h1><?php$Rockbands = array( array('Beatles','Love Me Do', 'Hey Jude','Helter Skelter'), array('Rolling Stones','Waiting on a Friend','Angie','Yesterday\'s Papers'), array('Eagles','Life in the Fast Lane','Hotel California','Best of My Love'));?><table border="1"><tr> <th>Rockband</th> <th>Song 1</th> <th>Song 2</th> <th>Song 3</th></tr><?phpforeach($Rockbands as $Rockband){ echo '<tr>'; foreach($Rockband as $item) { echo "<td>$item</td>"; } echo '</tr>';}?></table></body></html>

Array Manipulation FunctionsThe following table shows some of the more common array manipulation functions.

Useful Array Functions (see footnote)

Function Explanation

sort() Sorts an array alphabetically. Elements will be assigned to new index numbers.

asort() Sorts associative arrays alphabetically by value. The index association remains intact.

ksort() Sorts associative arrays alphabetically by key. The index association remains intact.

rsort() Reverse sorts an array alphabetically. Elements will be assigned to new index

Page 33: PHP Basics

Useful Array Functions (see footnote)

Function Explanation

numbers.

arsort() Reverse sorts associative arrays alphabetically by value. The index association remains intact.

krsort() Reverse sorts associative arrays alphabetically by key. The index association remains intact.

shuffle() Randomly sorts the array. For the order to be sorted differently each time, the random number generator needs to be seeded with rsand().

array_reverse() Returns an array with the elements in reverse order.

array_walk() Applies a user function to every element of an array.

count() Returns the number of elements in an array.

explode() Converts a string to an array by splitting it on a specified separator.

is_array() Takes one parameter and returns true or false depending on whether the parameter passed is an array.

array_keys() Returns all the keys of an associative array as an array.

array_key_exists() Checks to see if a specified key exists in an array.

Arrays ConclusionArrays are an important feature of many modern programming languages. In this lesson, we have covered the most common uses of arrays.

PHP and HTML FormsIn this lesson of the PHP tutorial, you will learn...

1. To process form data with PHP.

HTML Forms

Page 34: PHP Basics

How HTML Forms Work

A very common way to pass data from one page to another is through HTML forms. There are two methods of submitting data through a form: the get method and the post method. The method used is determined by the value of the method attribute of the form tag. The default method is get.

Get Method

When the get method is used, data is sent to the server in name-value pairs as part of the query string. The get method is most commonly used by search pages and is useful when it is important to be able to bookmark the resulting page (i.e, the page that is returned after the form is submitted).

Post Method

When the post method is used, data is sent to the server in name-value pairs behind the scenes. The two major advantages of the post method are:

The name-value pairs are not visible in the location bar, so sensitive data such as passwords are not displayed on the screen.

Files, such as images and Office documents, can be uploaded via the form.

The major disadvantage is that the resulting page cannot be bookmarked.

A Sample HTML Form

The following is a sample HTML form for inserting an employee record into a database.

Code Sample: Forms/Demos/AddEmployee.php<html><head><title>Add Employee</title></head><body><h1>Add Employee</h1><form method="post" action="ProcessEmployee.php"><table> <tr> <td>First name:</td> <td><input type="text" name="FirstName" size="15"/></td> </tr> <tr> <td>Last name:</td> <td><input type="text" name="LastName" size="15"/></td> </tr> <tr> <td>Title:</td> <td><input type="text" name="Title" size="30"/></td>

Page 35: PHP Basics

</tr> <tr> <td>Title of Courtesy:</td> <td> <input type="radio" name="TitleOfCourtesy" value="Dr."/>Dr. <input type="radio" name="TitleOfCourtesy" value="Mr."/>Mr. <input type="radio" name="TitleOfCourtesy" value="Mrs."/>Mrs. <input type="radio" name="TitleOfCourtesy" value="Ms."/>Ms. </td> </tr> <tr> <td>Birth date:</td> <td> <select name="BirthMonth"> <option value="1">January</option> <option value="2">February</option> <option value="3">March</option> <option value="4">April</option> <option value="5">May</option> <option value="6">June</option> <option value="7">July</option> <option value="8">August</option> <option value="9">September</option> <option value="10">October</option> <option value="11">November</option> <option value="12">December</option> </select> <select name="BirthDay"> <?php for ($i=1; $i<=31; $i++) { echo "<option value='$i'>$i</option>"; } ?> </select> <select name="BirthYear"> <?php for ($i=2006; $i>=1900; $i=$i-1) { echo "<option value='$i'>$i</option>"; } ?> </select> </td> </tr> <tr> <td>Hire date:</td> <td> <select name="HireMonth"> <option value="1">January</option> <option value="2">February</option> <option value="3">March</option> <option value="4">April</option> <option value="5">May</option> <option value="6">June</option> <option value="7">July</option> <option value="8">August</option>

Page 36: PHP Basics

<option value="9">September</option> <option value="10">October</option> <option value="11">November</option> <option value="12">December</option> </select> <select name="HireDay"> <?php for ($i=1; $i<=31; $i++) { echo "<option value='$i'>$i</option>"; } ?> </select> <select name="HireYear"> <?php for ($i=2006; $i>=1992; $i=$i-1) { echo "<option value='$i'>$i</option>"; } ?> </select> </td> </tr> <tr> <td>Address:</td> <td><input type="text" name="Address" size="50"/></td> </tr> <tr> <td>City:</td> <td><input type="text" name="City" size="30"/></td> </tr> <tr> <td>Region:</td> <td><input type="text" name="Region" size="2"/></td> </tr> <tr> <td>Postal Code:</td> <td><input type="text" name="PostalCode" size="10"/></td> </tr> <tr> <td>Country:</td> <td><input type="text" name="Country" size="5"/></td> </tr> <tr> <td>Home Phone:</td> <td><input type="text" name="HomePhone" size="15"/></td> </tr> <tr> <td>Extension:</td> <td><input type="text" name="Extension" size="5"/></td> </tr> <tr> <td colspan="2">Notes:</td> </tr> <tr> <td colspan="2"> <textarea name="Notes" cols="50" rows="3"></textarea>

Page 37: PHP Basics

</td> </tr> <tr> <td>Manager:</td> <td> <select name="ReportsTo"> <option value="0">Choose...</option> <option value="1">Nancy Davolio</option> <option value="2">Andrew Fuller</option> <option value="3">Janet Leverling</option> <option value="4">Margaret Peacock</option> <option value="5">Steven Buchanan</option> <option value="6">Michael Suyama</option> <option value="7">Robert King</option> <option value="8">Laura Callahan</option> <option value="9">Anne Dodsworth</option> </select> </td> </tr> <tr> <td>Password:</td> <td><input type="password" name="Password1" size="10"/></td> </tr> <tr> <td>Repeat Password:</td> <td><input type="password" name="Password2" size="10"/></td> </tr> <tr> <td colspan="2"><input type="submit" value="Add Employee"/></td> </tr></table></form></body></html>

The above code, which contains some embedded PHP code, outputs a simple HTML form. Its action page is ProcessEmployee.php, which will eventually contain PHP code to process the submitted form.

Form Variables

Form variables are variables that are created when an HTML form is submitted using the post method. These variables are stored in the $_POST superglobal array. Here are a few things you should know about how HTML forms are processed:

1. If a text field or textarea is left blank, the variable is sent to the server with a value of "" (empty string).

2. Select menus always send a variable to the server (unless they have been disabled in some way).

3. If no radio button in a radio array is checked, no variable for that radio array is sent to the server.

Page 38: PHP Basics

4. If a checkbox is not checked, no value is sent to the server. If it is checked, the default value of "on" is sent unless otherwise set in the HTML.

5. If the submit button has a name (e.g, <input type="submit" name="Inserting" value="Add Employee"/>), when that submit button is clicked a variable by that name with the corresponding value will be sent to the server.

Exercise: Processing Form InputDuration: 40 to 50 minutes.

In this exercise, you will create a page that processes the form data. The form entry page, Exercises/AddEmployee.php, is already complete and is identical to Demos/AddEmployee.php above. Filled out, the form would look like this:

Page 39: PHP Basics

If everything is filled out correctly, the page should display as follows:

Page 40: PHP Basics

If all fields are left blank except for the password fields, which contain two different values, the page should display as follows:

Page 41: PHP Basics

1. Open Forms/Exercises/ProcessEmployee.php in your editor. 2. For each form entry (other than the dates, which we'll worry about later), create a simple

global variable to hold...

o either an error if the entry is not filled out or filled out incorrectly.

o or the value entered.

3. Output the variables as list items as shown in the screenshots above.

4. Save your work.

5. To test your solution, load Forms/Exercises/AddEmployee.php in the browser and fill out and submit the form.

Code Sample: Forms/Exercises/ProcessEmployee.php<?php //For each entry coming through the form, // create a simple global variable to hold... // - either an error if the entry is not filled or filled incorrectly // - or the value entered. //The first one is done for you.

if ($_POST['FirstName'] == '') { $FirstName = '<span style="color:red;">First name omitted.</span>';

Page 42: PHP Basics

} else { $FirstName = $_POST['FirstName']; }?><html><head><title>Process Employee</title></head><body> <h1>Process Employee</h1> <ul> <?php //Output the variables as list items. //Part of the first one is done for you. echo "<li><b>Name:</b> $FirstName</li>"; ?> </ul></body></html>

If there are any errors, include a link at the bottom that directs the user to the form. If there are no errors, include a form full of hidden fields containing the values entered and a submit button that reads "Confirm".

String ManipulationIn this lesson of the PHP tutorial, you will learn...

1. To format strings. 2. To work with string manipulation functions.

3. To make strings safe for outputting to the browser.

4. To understand the benefits and dangers of magic quotes.

Formatting StringsConcatenation

Concatenation is a programming word for adding strings together. In PHP, the concatenation operator is a dot (.). Generally, concatenation is used to combine literal text with variables or values returned from functions. The example below illustrates this.

Code Sample: Strings/Demos/Concatenation.php<html><head><title>Concatenation</title>

Page 43: PHP Basics

</head><body><h1>Concatenation</h1><?php $FirstName = 'Paul'; $Greeting = 'Hello'; echo $Greeting . ' ' . $FirstName . '!';?><h2>Using Double Quotes to Avoid the Concatenation Operator</h2><?php echo "$Greeting $FirstName!";?><h2>Double quotes don't work when concatenating the results of a function call</h2><?php echo $Greeting . ' ' . $FirstName . '! Today is ' . date('l') . '.';?></body></html>Code Explanation

As shown in the code, double quotes can be used to avoid using the concatenation operator. This works for concatenating literal strings with variables, but it does not work for concatenating values returned from functions. To do that, the function call must be outside of any quotes and combined with the rest of the string using the concatenation operator. This also is demonstrated in the code sample above.

String Manipulation FunctionsTrimming Strings

Function Description

trim() Removes whitespace at beginning and end of a string.

ltrim() Removes whitespace at the beginning of a string.

rtrim() Removes whitespace at the end of a string.

Presentation

Function Description

htmlentities() Escapes all HTML entities.

nl2br() Inserts a <br /> tag before each newline character in a string.

strtoupper() Converts a string to uppercase.

strtolower() Converts a string to lowercase.

Page 44: PHP Basics

Presentation

Function Description

ucfirst() Converts the first character of a string to uppercase.

ucwords() Converts the first character of each word in a string to uppercase.

Converting Strings and Arrays

Function Description

explode() Splits a string into an array on a specified character or group of characters.

implode() Converts an array into a string, placing a specified character or group of characters between each array element.

join() Same as implode().

Substrings

Function Description

substr(str,pos) Returns the substring from the character in position pos to the end of the string.

substr(str,-len) Returns the substring from len characters from the end of the string to the end of the string.

substr(str,pos,len) Returns a len length substring beginning with the character in position pos.

substr(str,pos,-len) Returns a substring beginning with the character in position pos and chopping off the last len characters of the string.

strstr() Returns the position of one string in another.

stristr() Returns the position of one string in another. Case insensitive.

strpos() Finds the position of the first occurrence of a specified character in a string.

strrpos() Finds the position of the last occurrence of a specified character in a string.

str_replace() Replaces all occurrences of one string with another string.

Page 45: PHP Basics

Comparing Strings

Function Description

strcmp() Compares two strings. Returns < 0 if str1 is less than str2, > 0 if str1 is greater than str2, and 0 if they are equal.

strcasecmp() Like strcmp() but case insensitive.

strlen() Returns the length of a string.

Examples of String Functions

Below are some examples of string manipulation functions.

trim() and strtolower()

This example uses trim() and strtolower() to improve the form validation script.

Code Sample: Strings/Demos/Greeting.php<html><head> <title>Greeting Page</title></head><body><?php $LastName = trim($_GET['LastName']); $Gender = strtolower(trim($_GET['Gender']));

if ($LastName == '' || $Gender == '') { echo 'Error: You must fill out the form. Please <a href="Greeting.html">try again</a>.'; } else { switch($Gender) { case 'male' : echo "Hello Mr. $LastName!"; break; case 'female' : echo "Hello Ms. $LastName!"; break; default : echo "<b>$Gender</b> is not a gender!"; } }?></body></html>

Page 46: PHP Basics

htmlentities() and nl2br() (see footnote)

The htmlentities() function is used to escape HTML entities, such as less than signs (<) and greater than signs (>). Take a look at the screenshot below to get an idea of why this is important.

Imagine if this form were submitted to the script below.

Code Sample: Strings/Demos/HtmlEntitiesNotUsed.php<html><head><title>HTML Entities Processor</title></head><body><h1>HTML Entities Processor</h1><?php echo $_POST['UserComments'];?></body></html>

This would result in the JavaScript code being executed. This JavaScript code would create a never-ending loop that popped up an alert over and over again. Although this would be pretty annoying, there are much worse things users could do, such as make a remote procedure call to execute a page on your server.

You can test this by opening Strings/Demos/HtmlEntitiesNotUsed.html and submitting the form. You probably don't want to test with a never-ending loop though.

Page 47: PHP Basics

This can easily be fixed by changing the code to look like this:

Code Sample: Strings/Demos/HtmlEntitiesUsed.php<html><head><title>HTML Entities Processor</title></head><body><h1>HTML Entities Processor</h1><?php echo nl2br(htmlentities($_POST['UserComments']));?></body></html>

This script uses htmlentities() to escape all the HTML entities and uses nl2br() to convert newline characters to breaks. The resulting output looks like this:

And the resulting HTML source looks like this:

<html><head><title>HTML Entities Processor</title></head><body><h1>HTML Entities Processor</h1>&lt;script language=&quot;javascript&quot;&gt;<br /> while (true)<br /> {<br /> alert(&quot;Try to get rid of me!&quot;);<br />

Page 48: PHP Basics

}<br />&lt;/script&gt;</body></html>

explode()

The explode() function is used to convert a string to an array. The following form submits to Explode.php, the code of which is shown below.

Code Sample: Strings/Demos/Explode.php<html><head><title>Exploding Emails</title></head><body><?php $Emails = explode(';',$_POST['Emails']); echo '<ol>'; foreach ($Emails as $Email) { echo '<li>' . trim($Email) . '</li>'; } echo '</ol>';?></body></html>

Notice that the trim() function is used to trim the resulting elements of the array. This is because the string is exploded on the semi-colon only. If the user adds additional whitespace around the semi-colon, that whitespace will be part of the array element.

Page 49: PHP Basics

substr()

As shown earlier, the substr() function behaves differently depending on the values passed to it. The following screenshot shows the effects of using substr().

Exercise: Working with String Manipulation FunctionsDuration: 15 to 25 minutes.

In this exercise, you will modify the ProcessEmployee.php script you worked on earlier.

1. Open Strings/Exercises/ProcessEmployee.php in your editor. 2. Modify the code so that all leading and trailing whitespace is removed and HTML entities are

escaped for all incoming form variables.

3. Test the password comparison if condition by entering "0" in the Password1 text box and "-0.00" in the Password2 text box. This does not result in an error. Fix it so that an error will be returned.

4. Modify the code so that each word of the employee's title begins with a capital letter.

5. Modify the code so that hard returns in the Notes field are displayed in the output.

6. To test your solution, load Strings/Exercises/AddEmployee.php in the browser and fill out and submit the form.

Where is the solution?

Magic Quotes

Page 50: PHP Basics

There are two settings in the php.ini file that determine how PHP handles incoming data. The settings are magic_quotes_gpc (on by default) and magic_quotes_runtime (off by default).

magic_quotes_gpc

The value of magic_quotes_gpc determines whether GET, POST and COOKIE data should be escaped "automagically". If magic_quotes_gpc is set to 1, then single quotes, double quotes and backslashes will be escaped with backslashes. In this case, if a user entered "O'Reilly" as her last name, and your script returned that value to the browser (e.g, echo $_POST['LastName'];), the value returned would read "O\'Reilly". You would need to strip the backslashes by passing the value through the stripslashes() function (e.g, echo stripslashes($_POST['LastName']);).

Although magic quotes can be useful, they can also cause confusion as the developer may not know whether magic quotes are turned on or off. To check whether they are on, use the get_magic_quotes_gpc() function as shown below.

if (get_magic_quotes_gpc()){ echo stripslashes($_POST['LastName']);}else{ echo $_POST['LastName'];}

magic_quotes_runtime

The value of magic_quotes_runtime determines whether data returned from files and databases should be escaped "automagically". It works similarly to magic_quotes_gpc.

Recommendation on Magic Quotes

Our recommendation on magic quotes is to turn them off in the php.ini file. You can easily escape a string when you need to with the addslashes() function.

String Manipulation ConclusionIn this lesson of the PHP tutorial, you have learned to format strings safely for outputting to the browser, to work with PHP's built-in string manipulation functions to improve form validation, and to understand how magic quotes work.

Reusing Code and Writing FunctionsIn this lesson of the PHP tutorial, you will learn...

Page 51: PHP Basics

1. To write reusable files and include them in multiple pages. 2. To write user-defined functions.

3. To create a library of user-defined form-validation and form-entry functions.

Writing reusable code results in time and money savings, more consistent and bug free code, and the ability to hide complex code from less seasoned developers.

Including FilesPHP provides two common constructs for including files in web pages: require and include. They are basically the same with one minor difference. require throws a fatal error when it fails; whereas, include only gives a warning. If you need the included file to continue to process the page, you should use require.

It is important to keep in mind that a PHP tag cannot start in a calling file and continue in an included file. All PHP code in the included file must be nested in PHP tags.

require

require is not actually a function, but a language construct, so require statements can be written in two ways:

Syntax

require(path_to_file);

require path_to_file;

path_to_file can be an absolute or a relative path.

require_once

require_once can be used just like require. The difference is that if the included file has already been included by earlier code, it will not be re-included.

A Note on Security

If included files are under the web root, they can be accessed just as any other file can. If they have an extension such as inc then the browser may display them as plain text. With other extensions, the browser may attempt to download the file. If the included file is a PHP file and a user navigates to it, the server will try to process the file and may return errors. As a precaution, you may want to place your included files in a directory above or outside of the web root. This will prevent users from accessing the files directly.

Page 52: PHP Basics

include_path directive

The php.ini contains an include_path directive, which takes a semi-colon delimited list of paths to directories that PHP should look in for included files.

Here is a code sample that demonstrates how to include files using require.

Code Sample: ReusingCode/Demos/Require.php<html><head><title>Including Files</title></head><body>This text is on the main page.<hr/><?php require 'Includes/Required.php';?><hr/><?php require 'Includes/Required.inc';?></body></html>Code Explanation

The above code is relatively straightforward. Require.php contains two included (required) files: Required.php and Required.inc. Notice that there is PHP code inside of Required.inc, which is executed. The extension of the included files does not affect how the code inside the files will be executed.

Exercise: Adding a Header and FooterDuration: 5 to 10 minutes.

In this exercise, you will add a header and a footer to a simple home page, which currently just contains a login form.

1. Open Includes/Header.php and Includes/Footer.php in your editor and review the code. 2. Open ReusingCode/Exercises/index.php in your editor.

3. Add code to include Includes/Header.php and Includes/Footer.php at the top and bottom or the page.

4. To test your solution, load ReusingCode/Exercises/index.php in the browser. It should display as follows:

Page 53: PHP Basics

auto_prepend_file and auto_append_file

The configuration file, php.ini, contains settings for automatically prepending and appending files to every PHP script. These settings are auto_prepend_file and auto_append_file. By default, they contain no values; however, they can be set to point to a files using absolute paths as follows:

; Automatically add files before or after any PHP document.auto_prepend_file = "c:/inetput/include/runbefore.inc"auto_append_file = "c:/inetput/include/runafter.inc"

The auto_prepend_file directive can be used to application-wide variables such as database connection strings or common file paths. The auto_append_file directive can be used for cleaning up code or for outputting debugging information to the browser.

Note that it is not possible to set different auto-prepend and auto-append files for different directories or different scripts.

Page 54: PHP Basics

User FunctionsUser functions are used to make common tasks easier and to make code more modular and easier to read. Unlike other identifiers in PHP, functions are case insensitive.

Defining and Calling Functions

A simple function is defined as follows.

Syntax

function myfunct(){ do this; do that; do this other thing;}

Like built-in functions, user functions can receive parameters. To define a function with parameters, place receiving variables in the parentheses.

Syntax

function addNums($param1, $param2, $param3){ $sum = $param1 + $param2 + $param3; echo 'The sum is ' . $sum;}

User functions can also return values.

Syntax

function addNums($param1, $param2, $param3){ $sum = $param1 + $param2 + $param3; return $sum;}

User functions are called in the same way that built-in functions are. For example, the following code calls the addNums() function to get the sum of three numbers.

Syntax

$total = addNums(1,3,5);

See ReusingCode/Demos/SimpleUDF.php to see the above code in action.

Page 55: PHP Basics

Default Values

You can make function parameters optional by assigning default values to them as shown in the example below.

Code Sample: ReusingCode/Demos/DefaultValues.php<html><head><title>Simple User-defined Function</title></head>

<body><?phpfunction addNums($param1=0, $param2=0, $param3=0){ $sum = $param1 + $param2 + $param3; return $sum;}

$Total = addNums(1,3);

echo $Total;?></body></html>Code Explanation

In this case, if you don't pass a value into the function for one or more of the parameters, the default value of 0 will be used. When defining a function, all required parameters should precede optional parameters.

Variable Scope

In PHP, variables declared outside of functions are not available by default inside of functions. The following code illustrates this:

Code Sample: ReusingCode/Demos/LocalVars.php<html><head><title>Local Variables</title></head>

<body><?php$a = 10;$b = 5;

function incrNumBy(){ $a += $b;}

Page 56: PHP Basics

incrNumBy(); //results in two warnings as $a and $b are //undefined in the function scopeecho $a; //outputs 10 to the browser?></body></html>

To make the variables available to the function, they must be declared within the function as global variables using the global keyword.

Code Sample: ReusingCode/Demos/GlobalVars.php<html><head><title>Global Variables</title></head>

<body><?php$a = 10;$b = 5;

function incrNumBy(){ global $a,$b; $a += $b;}incrNumBy(); echo $a; //outputs 15 to the browser?></body></html>

By Reference vs. By Value

By default, variables are passed to functions by value, meaning that the function's receiving variables get copies of the values received rather than pointers to them. If the receiving variables are modified, the passed variables remain unaffected. The following code illustrates this.

Code Sample: ReusingCode/Demos/ByValue.php<html><head><title>By Value</title></head><body><?php $a = 10; $b = 5; function incrNumBy($num,$incr) { $num += $incr; } incrNumBy($a,$b);

Page 57: PHP Basics

echo $a; //outputs 10 to the browser?></body></html>

The above code outputs "10" to the browser. Although $num was incremented by 5, $a was unaffected by the function call. To pass a variable by reference, put an ampersand (&) before the parameter in the function definition.

Code Sample: ReusingCode/Demos/ByReference.php<html><head><title>By Reference</title></head><body><?php $a = 10; $b = 5; function incrNumBy(&$num,$incr) { $num += $incr; } incrNumBy($a,$b); echo $a; //outputs 15 to the browser?></body></html>

This time the function outputs "15" because $num references the variable $a itself. So, any change in $num will affect $a.

Form ProcessingProcessing forms generally involves the following tasks:

1. Writing the HTML code to output the form. 2. Writing validation code to validate the form entries after the form is submitted.

3. Writing code to output errors if there are any.

4. Writing code to process the form entries if they are all valid.

Although these tasks are all separate, some are dependent on others. For example, if errors are found when the form is submitted, it is nice to re-output the form, but the HTML code may be different from the original form as you will likely want to include error messages and also echo the values that the user entered. It's very easy to get your code all tangled up resulting in what is known as spaghetti code. We will now examine one approach for organizing code using functions and includes to make it easier to maintain.

Page 58: PHP Basics

Code Organization

Application Flow

The application we are building works like this:

1. When the user first visits, she is presented with a form to fill out. 2. If she fills out the form...

o Correctly

She is presented with another form to confirm her entries.

After confirming her entries, the data will be processed (e.g, entered into a database or emailed to someone).

o Incorrectly

She is presented with the same form with her entries in tact and appropriate error messages displayed.

Application Files

To make our code easier to maintain, we will organize it as follows:

1. Includes/init.php - Initializes and sets some variables. 2. AddEmployee.php - Contains code that defines the flow of the application.

3. Includes/EmployeeForm.php - Contains code to display entry form.

4. Includes/ProcessEmployee.php - Contains code to process the original form entry. If there are errors, they will be displayed on the page. If there are no errors, the user's entries will be displayed with a "Confirm" button.

5. Includes/InsertEmployee.php - Contains code to insert the employee into a database. (This file is currently empty.)

6. Includes/fnFormPresentation.php - Contains a library of functions for presenting form fields.

7. Includes/fnFormValidation.php - Contains a library of functions for validating form entries.

8. Includes/fnStrings.php - Contains a couple of useful string functions.

9. Includes/fnDates.php - Contains a useful date function.

We will examine each of these files.

Code Sample: ReusingCode/Demos/Includes/init.php<?php $ShowForm = true;

Page 59: PHP Basics

$MgrEntries = array(); $MgrEntries[1]='Nancy Davolio'; $MgrEntries[2]='Andrew Fuller'; $MgrEntries[3]='Janet Leverling'; $MgrEntries[4]='Margaret Peacock'; $MgrEntries[5]='Steven Buchanan'; $MgrEntries[6]='Michael Suyama'; $MgrEntries[7]='Robert King'; $MgrEntries[8]='Laura Callahan'; $MgrEntries[9]='Anne Dodsworth';

$Errors = array(); $DbEntries = array( 'FirstName'=>'', 'LastName'=>'', 'Email'=>'', 'Title'=>'', 'TitleOfCourtesy'=>'', 'Address'=>'', 'City'=>'', 'Region'=>'', 'PostalCode'=>'', 'Country'=>'', 'HomePhone'=>'', 'Extension'=>'', 'Notes'=>'', 'ReportsTo'=>'', 'Password'=>'', 'Email'=>'', 'BirthMonth'=>1, 'BirthDay'=>1, 'BirthYear'=>date('Y'), 'HireMonth'=>1, 'HireDay'=>1, 'HireYear'=>date('Y')); $BrowserEntries = array();?>Code Explanation

This file sets several variables used throughout the application.

Code Sample: ReusingCode/Demos/AddEmployee.php<?php require 'Includes/fnFormValidation.php'; require 'Includes/fnFormPresentation.php'; require 'Includes/fnStrings.php'; require 'Includes/fnDates.php'; require 'Includes/init.php';?><html><head><title>Add Employee</title><style type="text/css"> .Error {color:red; font-size:smaller;}</style>

Page 60: PHP Basics

</head><body><?php require 'Includes/Header.php';

if (array_key_exists('Submitted',$_POST)) { require 'Includes/ProcessEmployee.php'; } elseif (array_key_exists('Confirmed',$_POST)) { require 'Includes/InsertEmployee.php'; }

if ($ShowForm) { require 'Includes/EmployeeForm.php'; }

require 'Includes/Footer.php';?></body></html>Code Explanation

The code is relatively easy to read. Things to note:

1. At the very top, we include several files we will need for the application. 2. In the body, we include:

o our header and footer files.

o code that checks which, if either, form was submitted and includes the appropriate file.

o code that checks whether or not to show the main form. The form will be shown if:

it has not yet been submitted.

it has been submitted with errors.

Code Sample: ReusingCode/Demos/Includes/fnDates.php<?php/********* DATE FUNCTIONS *********/

/* Function Name: monthAsString Arguments: $m Returns: month as string*/function monthAsString($m){ $Months = array(); $Months[] = 'January';

Page 61: PHP Basics

$Months[] = 'February'; $Months[] = 'March'; $Months[] = 'April'; $Months[] = 'May'; $Months[] = 'June'; $Months[] = 'July'; $Months[] = 'August'; $Months[] = 'September'; $Months[] = 'October'; $Months[] = 'November'; $Months[] = 'December'; return $Months[$m-1];}?>Code Explanation

This file includes a simple function for getting the name of a month (e.g, February) given the month number (e.g, 2).

Code Sample: ReusingCode/Demos/Includes/fnStrings.php<?php/********** STRING FUNCTIONS *********//* Function Name: browserString Arguments: $String Returns: trimmed and escaped string for browser output*/function browserString($String){ return nl2br(trim(htmlentities($String)));}

/* Function Name: dbString Arguments: $String Returns: trimmed and escaped string for database entry*/function dbString($Email){ if (get_magic_quotes_gpc()) { return trim ($Email); } else { return addslashes(trim($Email)); }}

?>Code Explanation

Page 62: PHP Basics

This file includes functions for cleaning up strings for browser and database output.

Code Sample: ReusingCode/Demos/Includes/fnFormPresentation.php<?php/********* FORM PRESENTATION FUNCTIONS *********/

/* Function Name: textEntry Arguments: $Display,$Name,$Entries,$Errors,$Size? Returns: one table row as string*/function textEntry($Display,$Name,$Entries,$Errors,$Size=15){ $ReturnVal = " <tr> <td>$Display:</td> <td> <input type='text' name='$Name' size='$Size' value=\"" . browserString($Entries[$Name]) . "\">";

if (array_key_exists($Name,$Errors)) { $ReturnVal .= '<span class="Error" style="white-space:nowrap">* ' . $Errors[$Name] . '</span>'; }

$ReturnVal .= "</td> </tr>";

return $ReturnVal;}

/* Function Name: pwEntry Arguments: $PW1,$PW2,$Errors,$Size? Returns: table rows as string*/function pwEntry($PW1,$PW2,$Errors,$Size=10){ $ReturnVal = " <tr> <td>Password:</td> <td> <input type='password' name='$PW1' size='$Size'> </td> </tr> <tr> <td>Repeat Password:</td> <td> <input type='password' name='$PW2' size='$Size'> </td> </tr>";

Page 63: PHP Basics

if (array_key_exists('Password',$Errors)) { $ReturnVal .= addErrorRow('Password',$Errors); } return $ReturnVal;}

/* Function Name: textAreaEntry Arguments: $Display,$Name,$Entries,$Errors,$Cols?,$Rows? Returns: table rows as string*/function textAreaEntry($Display,$Name,$Entries,$Errors,$Cols=45,$Rows=5){ $ReturnVal = " <tr> <td colspan='2'>$Display:</td> </tr> <tr> <td colspan='2'> <textarea name='$Name' cols='$Cols' rows='$Rows'>"; $ReturnVal .= $Entries[$Name]; $ReturnVal .= "</textarea> </td> </tr>";

if (array_key_exists($Name,$Errors)) { $ReturnVal .= addErrorRow($Name,$Errors); } return $ReturnVal;}

/* Function Name: radioEntry Arguments: $Display,$Name,$Entries,$Errors,$Values Returns: table rows as string*/function radioEntry($Display,$Name,$Entries,$Errors,$Values){ $ReturnVal = " <tr> <td>$Display:</td> <td>$Name</td> </tr>";

return $ReturnVal;}

/* Function Name: selectEntry Arguments: $Display,$Name,$Entries,$Errors,$Selected? Returns: table rows as string*/

Page 64: PHP Basics

function selectEntry($Display,$Name,$Options,$Errors,$Selected=0){ $ReturnVal = "<tr> <td>$Display:</td> <td> <select name='$Name'> <option value='0'>Choose one...</option>"; $ReturnVal .= "</select> </td> </tr>"; return $ReturnVal;}

/* Function Name: selectDateEntry Arguments: $Display,$NamePre,$Month,$Day,$Year Returns: table rows as string*/function selectDateEntry($Display,$NamePre,$Month,$Day,$Year,$Errors){ $ReturnVal = "<tr> <td>$Display:</td> <td> <select name='$NamePre" . "Month'>"; for ($i=1; $i<=12; $i++) { if ($i == $Month) { $ReturnVal .= "<option value='$i' selected>"; } else { $ReturnVal .= "<option value='$i'>"; } $ReturnVal .= monthAsString($i) . '</option>'; } $ReturnVal .= "</select> <select name='$NamePre" . "Day'>"; for ($i=1; $i<=31; $i++) { if ($i == $Day) { $ReturnVal .= "<option value='$i' selected>"; } else { $ReturnVal .= "<option value='$i'>"; } $ReturnVal .= "$i</option>"; } $ReturnVal .= "</select> <select name='$NamePre" . "Year'>"; for ($i=date('Y'); $i>=1900; $i=$i-1) { if ($i == $Year) {

Page 65: PHP Basics

$ReturnVal .= "<option value='$i' selected>"; } else { $ReturnVal .= "<option value='$i'>$i</option>"; } $ReturnVal .= "$i</option>"; } $ReturnVal .= '</select> </td> </tr>';

if (array_key_exists($NamePre . 'Date',$Errors)) { $ReturnVal .= addErrorRow($NamePre . 'Date',$Errors); } return $ReturnVal;}

/* Function Name: addErrorRow Arguments: $Name Returns: table row as string*/function addErrorRow($Name,$Errors){ $ErrorRow = '<tr><td colspan="2" class="Error">* ' . $Errors[$Name] . '</td></tr>'; return $ErrorRow;}?>Code Explanation

This file contains functions for presenting form entries. Several of these functions are complete, but there are a couple that need to be finished. This will be part of the next exercise.

Code Sample: ReusingCode/Demos/Includes/fnFormValidation.php<?php/********* FORM VALIDATION FUNCTIONS *********/

/* Function Name: checkLength Arguments: $Text,$Min?,$Max?,$Trim? Returns: false if $Text has fewer than $Min characters false if $Text has more than $Max characters true otherwise*/function checkLength($Text,$Min=1,$Max=10000,$Trim=true){ if ($Trim) { $Text = trim($Text);

Page 66: PHP Basics

} if (strlen($Text) < $Min || strlen($Text) > $Max) { return false; } return true;}

/* Function Name: checkEmail Arguments: $Email Returns: false if $Email has fewer than 6 characters false if $Email does not contain @ symbol false if $Email does not contain a period (.) false if the last @ symbol comes after the last period (.) true otherwise*/function checkEmail($Email){ return true;}

/* Function Name: checkPassword Arguments: $PW1,$PW2 Returns: false if $PW1 has fewer than 6 characters false if $PW1 has more than 12 characters false if $PW1 and $PW2 do not match true otherwise*/function checkPassword($PW1,$PW2){ return true;}?>Code Explanation

This file contains functions for validating form entries. One of these functions is complete, but there are a couple that need to be finished. This will also be part of the next exercise.

Code Sample: ReusingCode/Demos/Includes/EmployeeForm.php<h1 align="center">Add Employee</h1><form method="post" action="AddEmployee.php"><input type="hidden" name="Submitted" value="true"><table align="center" border="1" width="500"> <?php echo textEntry('First name','FirstName',$DbEntries,$Errors,15); echo textEntry('Last name','LastName',$DbEntries,$Errors,15); echo textEntry('Email','Email',$DbEntries,$Errors,25); echo textEntry('Title','Title',$DbEntries,$Errors,30); echo radioEntry('Title of Courtesy','TitleOfCourtesy', $DbEntries,$Errors, array('Dr.','Mr.','Mrs.','Ms.'));

Page 67: PHP Basics

echo selectDateEntry('Birth date','Birth', $DbEntries['BirthMonth'], $DbEntries['BirthDay'], $DbEntries['BirthYear'], $Errors); echo selectDateEntry('Hire date','Hire', $DbEntries['HireMonth'], $DbEntries['HireDay'], $DbEntries['HireYear'], $Errors); echo textEntry('Address','Address',$DbEntries,$Errors,50); echo textEntry('City','City',$DbEntries,$Errors,30); echo textEntry('Region','Region',$DbEntries,$Errors,2); echo textEntry('Postal Code','PostalCode',$DbEntries,$Errors,10); echo textEntry('Country','Country',$DbEntries,$Errors,5); echo textEntry('Home phone','HomePhone',$DbEntries,$Errors,15); echo textEntry('Extension','Extension',$DbEntries,$Errors,5); echo textAreaEntry('Notes','Notes',$DbEntries,$Errors,50,3); echo selectEntry('Manager','ReportsTo',$MgrEntries, $Errors,$DbEntries['ReportsTo']); echo pwEntry('Password1','Password2',$Errors,10); ?> <tr> <td colspan="2"><input type="submit" value="Add Employee"></td> </tr></table></form>Code Explanation

This file creates the entry form. Notice that it creates entry rows through calls to functions in the fnFormPresentation.php file. This allows us to easily incorporate error handling and error messages into the form entries without making the HTML form itself difficult to maintain.

Code Sample: ReusingCode/Demos/Includes/ProcessEmployee.php<?php $DbEntries['FirstName'] = dbString($_POST['FirstName']); $DbEntries['LastName'] = dbString($_POST['LastName']); $DbEntries['Title'] = ucwords(dbString($_POST['Title'])); $DbEntries['Address'] = dbString($_POST['Address']); $DbEntries['City'] = dbString($_POST['City']); $DbEntries['Region'] = dbString($_POST['Region']); $DbEntries['PostalCode'] = dbString($_POST['PostalCode']); $DbEntries['Country'] = dbString($_POST['Country']); $DbEntries['HomePhone'] = dbString($_POST['HomePhone']); $DbEntries['Extension'] = dbString($_POST['Extension']); $DbEntries['Notes'] = dbString($_POST['Notes']); $DbEntries['ReportsTo'] = $_POST['ReportsTo']; $DbEntries['Password'] = dbString($_POST['Password1']); $DbEntries['Email'] = dbString($_POST['Email']); $DbEntries['BirthMonth'] = dbString($_POST['BirthMonth']); $DbEntries['BirthDay'] = dbString($_POST['BirthDay']); $DbEntries['BirthYear'] = dbString($_POST['BirthYear']); $DbEntries['HireMonth'] = dbString($_POST['HireMonth']); $DbEntries['HireDay'] = dbString($_POST['HireDay']); $DbEntries['HireYear'] = dbString($_POST['HireYear']);

Page 68: PHP Basics

if (!checkLength($_POST['FirstName'])) { $Errors['FirstName'] = 'First name omitted.'; } else { $BrowserEntries['FirstName'] = browserString($_POST['FirstName']); }

if (!checkLength($_POST['LastName'])) { $Errors['LastName'] = 'Last name omitted.'; } else { $BrowserEntries['LastName'] = browserString($_POST['LastName']); }

if (!checkLength($_POST['Title'])) { $Errors['Title'] = 'Title omitted.'; } else { $BrowserEntries['Title'] = ucwords(browserString($_POST['Title'])); }

if ( array_key_exists('TitleOfCourtesy',$_POST) ) { $BrowserEntries['TitleOfCourtesy'] = browserString($_POST['TitleOfCourtesy']); $DbEntries['TitleOfCourtesy'] = dbString($_POST['TitleOfCourtesy']); } else { $Errors['TitleOfCourtesy'] = 'Title of Courtesy not selected.'; }

if (!checkdate($_POST['BirthMonth'],$_POST['BirthDay'],$_POST['BirthYear'])) { $Errors['BirthDate'] = 'Birth date is not a valid date.'; }

if (!checkdate($_POST['HireMonth'],$_POST['HireDay'],$_POST['HireYear'])) { $Errors['HireDate'] = 'Hire date is not a valid date.'; }

if (!checkLength($_POST['Address'],5,200)) { $Errors['Address'] = 'Address omitted.'; } else { $BrowserEntries['Address'] = browserString($_POST['Address']); }

Page 69: PHP Basics

if (!checkLength($_POST['City'],1,100)) { $Errors['City'] = 'City omitted.'; } else { $BrowserEntries['City'] = browserString($_POST['City']); }

if (!checkLength($_POST['Region'],2,2) && !checkLength($_POST['Region'],0,0)) { $Errors['Region'] = 'Region name must be two characters.'; } else { $BrowserEntries['Region'] = browserString($_POST['Region']); }

if (!checkLength($_POST['PostalCode'])) { $Errors['PostalCode'] = 'Postal Code omitted.'; } else { $BrowserEntries['PostalCode'] = browserString($_POST['PostalCode']); }

if (!checkLength($_POST['Country'])) { $Errors['Country'] = 'Country omitted.'; } else { $BrowserEntries['Country'] = browserString($_POST['Country']); }

if (!checkLength($_POST['HomePhone'],10,15)) { $Errors['HomePhone'] = 'Home phone must be between 10 and 15 characters.'; } else { $BrowserEntries['HomePhone'] = browserString($_POST['HomePhone']); }

if (!checkLength($_POST['Extension'],3,5)) { $Errors['Extension'] = 'Extension must be between 3 and 5 characters.'; } else { $BrowserEntries['Extension'] = browserString($_POST['Extension']); }

if (!checkLength($_POST['Notes'],0,100)) {

Page 70: PHP Basics

$Errors['Notes'] = 'Notes must be fewer than 100 characters:<br/> <span style="color:blue; font-weight:normal">' . browserString(substr($_POST['Notes'],0,100)) . '</span><span style="color:red; font-weight:normal; text-decoration:line-through;">' . browserString(substr($_POST['Notes'],100)) . '</span>'; } else { $BrowserEntries['Notes'] = browserString($_POST['Notes']); }

if ($_POST['ReportsTo'] == 0) { $Errors['ReportsTo'] = 'Manager not selected.'; } else { $BrowserEntries['ReportsTo'] = $_POST['ReportsTo']; }

if ( !checkPassword($_POST['Password1'],$_POST['Password2']) ) { $Errors['Password'] = 'Passwords do not match or are not the right length.'; } else { $BrowserEntries['Password'] = browserString($_POST['Password1']); }

if ( !checkEmail($_POST['Email']) ) { $Errors['Email'] = 'Email is invalid.'; } else { $BrowserEntries['Email'] = browserString($_POST['Email']); }?><?php if (!count($Errors)) { $ShowForm = false;?> <form method="post" action="AddEmployee.php"> <input type="hidden" name="Confirmed" value="true"> <?php echo '<h2>Confirm Entries</h2>'; echo '<ol>'; foreach ($BrowserEntries as $key=>$Entry) { if ($key=='ReportsTo') { echo "<li><b>Manager:</b> $MgrEntries[$Entry]</li>"; } else

Page 71: PHP Basics

{ echo "<li><b>$key:</b> $Entry</li>"; } } echo '</ol>';

foreach ($DbEntries as $key=>$Entry) { ?> <input type="hidden" name="<?php echo $key ?>" value="<?php echo $Entry ?>"> <?php } ?> <input type="submit" value="Confirm"> </form><?php } else { $DbEntries = $_POST; }?>Code Explanation

This file contains code for processing the form entries. It makes use of functions in the fnFormValidation.php file for validating entries. If no errors are found, it sets the boolean $ShowForm to false, so that the original form will not be displayed and it outputs all the entries (made browser-safe) to the browser for confirmation. If errors are found, it adds them to the $Errors array, which is passed into the form presentation functions, so that they can return code for displaying the errors. If there are errors, the boolean $ShowForm is left as true, so that the original form is redisplayed.

Code Sample: ReusingCode/Demos/Includes/InsertEmployee.phpTO DO LATERCode Explanation

This file will eventually contain code for inserting the employee information into the database.

Exercise: Form Validation and Presentation FunctionsDuration: 45 to 60 minutes.

In this exercise, you will complete several functions needed for the application we have just seen.

1. Open ReusingCode/Exercises/Includes/fnFormPresentation.php in your editor. 2. Complete the radioEntry() and selectEntry() functions so that the return value contains correct

form entries and, if appropriate, errors.

3. Open ReusingCode/Exercises/Includes/fnFormValidation.php in your editor.

Page 72: PHP Basics

4. Complete checkEmail() and checkPassword(), so that they return true if the form entry is valid and false otherwise.

5. To test your solution, open ReusingCode/Exercises/AddEmployee.php in your browser and submit the form several times entering different data combinations each time.

Managing DataIn this lesson of the PHP tutorial, you will learn...

1. To retrieve and safely display records from a database. 2. To insert new records into a database.

3. To update existing records in a database.

Querying a DatabaseThe steps for querying a database in a PHP script are as follows:

1. Connect to the database. 2. Send query to the database.

3. Retrieve and store results sent back from the database.

4. Output the results of the query to the browser.

5. Free up resources and disconnect from the database.

mysqli() Overview

New in PHP5 is the mysqli library, which works with MySQL versions 4.1.3 and above and takes advantage of a new faster connection protocol in MySQL. The mysqli library provides two interfaces: an object-oriented interface and a procedural interface. The following two scripts use the two different interfaces to accomplish the same result.

Code Sample: ManagingData/Demos/SimpleQuery-OO.php<html><head><title>Simple Query - OO</title></head><body>

Page 73: PHP Basics

<?php@$DB = new mysqli('localhost','root','pwdpwd','Northwind');if (mysqli_connect_errno()){ echo 'Cannot connect to database: ' . mysqli_connect_error();}else{ $Query = 'SELECT * FROM Employees'; $Result = $DB->query($Query); $NumResults = $Result->num_rows;

echo "<b>$NumResults Employees</b>";?> <table border="1"> <tr> <th>First Name</th> <th>Last Name</th> <th>Title</th> <th>Email</th> <th>Extension</th> </tr><?php while ($Row = $Result->fetch_assoc()) { echo '<tr>'; echo '<td>' . $Row['FirstName'] . '</td>'; echo '<td>' . $Row['LastName'] . '</td>'; echo '<td>' . $Row['Title'] . '</td>'; echo '<td>' . $Row['Email'] . '</td>'; echo '<td align="right">x' . $Row['Extension'] . '</td>'; echo '</tr>'; }?> </table><?php $Result->free(); $DB->close();}?></body></html>

Code Sample: ManagingData/Demos/SimpleQuery-Procedural.php<html><head><title>Simple Query - Procedural</title></head><body><?php@$DB = mysqli_connect('localhost','root','pwdpwd','Northwind');if (mysqli_connect_errno()){ echo 'Cannot connect to database: ' . mysqli_connect_error();}else

Page 74: PHP Basics

{ $Query = 'SELECT * FROM Employees'; $Result = mysqli_query($DB,$Query); $NumResults = mysqli_num_rows($Result);

echo "<b>$NumResults Employees</b>";?> <table border="1"> <tr> <th>First Name</th> <th>Last Name</th> <th>Title</th> <th>Email</th> <th>Extension</th> </tr><?php while ($Row = mysqli_fetch_assoc($Result)) { echo '<tr>'; echo '<td>' . $Row['FirstName'] . '</td>'; echo '<td>' . $Row['LastName'] . '</td>'; echo '<td>' . $Row['Title'] . '</td>'; echo '<td>' . $Row['Email'] . '</td>'; echo '<td align="right">x' . $Row['Extension'] . '</td>'; echo '</tr>'; }?> </table><?php mysqli_free_result($Result); mysqli_close($DB);}?></body></html>Code Explanation

1. To connect to the database, we use: (see footnote)

1.

o Object-oriented

@$DB = new mysqli('localhost','root','pwdpwd','Northwind');o Procedural:

@$DB = mysqli_connect('localhost','root','pwdpwd','Northwind');2. To see if the connection was successful we check mysqli_connect_errno(), which returns an

error number if there is a connection error or 0 if there is no error. If an error occurs, we output a message with mysqli_connect_error(). We use the procedural interface in both cases, because a connection object doesn't get created if the connection fails.

3. To send the query to the database and store the results in a variable, we use:

o Object-oriented: $Result = $DB->query($Query);

Page 75: PHP Basics

o Procedural: $Result = mysqli_query($DB,$Query);

4. To output the results of the query, we use:

o Object-oriented:

o while ($Row = $Result->fetch_assoc())o {o echo "<tr>";o echo "<td>" . $Row['FirstName'] . "</td>";o echo "<td>" . $Row['LastName'] . "</td>";o echo "<td>" . $Row['Title'] . "</td>";o echo "<td>" . $Row['Email'] . "</td>";o echo "<td align='right'>x" . $Row['Extension'] . "</td>";o echo "</tr>";

}o Procedural: o while ($Row = mysqli_fetch_assoc($Result))o {o echo "<tr>";o echo "<td>" . $Row['FirstName'] . "</td>";o echo "<td>" . $Row['LastName'] . "</td>";o echo "<td>" . $Row['Title'] . "</td>";o echo "<td>" . $Row['Email'] . "</td>";o echo "<td align='right'>x" . $Row['Extension'] . "</td>";o echo "</tr>";

}5. To free up resources and disconnect from the database, we use:

o Object-oriented:

o $Result->free();$DB->close();

o Procedural: o mysqli_free_result($Result);

mysqli_close($DB);

As you can see, the two scripts are pretty similar. We will use the object-oriented interface in future examples.

mysqli Methods and PropertiesConnection Methods and Properties

Object-oriented Procedural Description

new mysqli() mysqli_connect() Connects to a MySQL server.

mysqli_connect_errno() Returns connection error number or 0 if there's no error.

mysqli_connect_error() Returns connection error message.

$DB->host_info mysqli_get_host_info() Returns information on the connection.

Page 76: PHP Basics

Query Functions

Object-oriented Procedural Description

$DB->query() mysqli_query() Sends a query to the database and returns results.

$DB->multi_query() mysqli_multi_query() Sends multiple queries to the database and returns results.

Fetch Functions

Object-oriented Procedural Description

$Result->fetch_row() mysqli_fetch_row() Returns a result row from a query result object or resource as an indexed array.

$Result->fetch_assoc()

mysqli_fetch_assoc() Returns a result row from a query result object or resource as an associative array.

$Result->fetch_object()

mysqli_fetch_object() Returns a result row from a query result object or resource as an object.

Inserting and Updating Records

Records are inserted and updated with SQL queries using the same mysqli library we used to generate a report. Review the following scripts.

Code Sample: ManagingData/Demos/EmployeeReport.php ---- Code Omitted ---- <table border="1"> <tr> <th>First Name</th> <th>Last Name</th> <th>Title</th> <th>Email</th> <th>Extension</th> <th>Edit</th> </tr><?php while ($Row = $Result->fetch_assoc()) { echo '<tr>'; echo '<td>' . $Row['FirstName'] . '</td>'; echo '<td>' . $Row['LastName'] . '</td>'; echo '<td>' . $Row['Title'] . '</td>'; echo '<td>' . $Row['Email'] . '</td>'; echo '<td align="right">x' . $Row['Extension'] . '</td>'; echo '<td><form method="post" action="EditEmployee.php"> <input type="hidden" name="EmployeeID" value="' . $Row['EmployeeID'] . '"/>

Page 77: PHP Basics

<input type="submit" name="Editing" value="Edit"/> </form></td>'; echo '</tr>'; }?> </table> ---- Code Omitted ----

Code Explanation

This file is similar to the SimpleQuery examples we saw earlier in this lesson. The only difference is that each row now has an edit form in the last column, which sends the employee's EmployeeID to EditEmployee.php.

Code Sample: ManagingData/Demos/EditEmployee.php<?php require 'Includes/fnFormValidation.php'; require 'Includes/fnFormPresentation.php'; require 'Includes/fnStrings.php'; require 'Includes/fnDates.php'; require 'Includes/init.php'; @$DB = new mysqli('localhost','root','pwdpwd','Northwind'); if (mysqli_connect_errno()) { echo 'Cannot connect to database: ' . mysqli_connect_error(); }?><html><head><title>Edit Employee</title><style type="text/css"> .Error {color:red; font-size:smaller;}</style></head><body><?php require 'Includes/Header.php';

if (array_key_exists('Updating',$_POST)) { require 'Includes/ProcessEmployee.php'; }

require 'Includes/EmployeeData.php'; require 'Includes/EmployeeForm.php';

require 'Includes/Footer.php';

$DB->close();?></body></html>Code Explanation

Page 78: PHP Basics

This file is similar to the AddEmployee.php file we worked on earlier in the course. This one goes a step further though by connecting to the database to retrieve data to populate the form. It works as follows:

1. At the very top, we include several files we will need for the application and we connect to the database.

2. In the body, we include:

o our header and footer files.

o code that checks whether the user has already made updates and, if so, includes the processing file.

o the file with code to retrieve the specified employee's data.

o the file with code to display the filled-in form.

Code Sample: ManagingData/Demos/Includes/EmployeeData.php<?php $EmployeeID = $_POST['EmployeeID'];

$Query = "SELECT FirstName, LastName, Title, TitleOfCourtesy, Email, MONTH(BirthDate) AS BirthMonth, DAYOFMONTH(BirthDate) AS BirthDay, YEAR(BirthDate) AS BirthYear, MONTH(HireDate) AS HireMonth, DAYOFMONTH(HireDate) AS HireDay, YEAR(HireDate) AS HireYear, Address, City, Region, PostalCode, Country, HomePhone, Extension, Notes, ReportsTo, Password FROM Employees WHERE EmployeeID = $EmployeeID"; $Result = $DB->query($Query); $DbEntries = $Result->fetch_assoc(); $Result->free();?>Code Explanation

This file contains the query that selects the specified employee's data and populates the $DbEntries array with the results.

Code Sample: ManagingData/Demos/Includes/fnStrings.php<?php/********** STRING FUNCTIONS *********/ ---- Code Omitted ----

/* Function Name: dbString Arguments: $String Returns:

Page 79: PHP Basics

trimmed and escaped string for database entry*/function dbString($String){ $String=trim($String); if (get_magic_quotes_gpc()) { return $String; } else { return addslashes($String); }}?>Code Explanation

This file is the same as the fnStrings.php file we saw before except that the dbString() function has been updated. It now checks to see if magic quotes are turned on. If they are, then form entries will be made database-safe "automagically", so it just returns the trimmed string. If they are not, then it uses addslashes() to make the string safe for database queries.

Code Sample: ManagingData/Demos/Includes/fnFormValidation.php<?php/********* FORM VALIDATION FUNCTIONS *********/ ---- Code Omitted ---- /* Function Name: checkPassword Arguments: $PW1,$PW2,$CheckLength? Returns: false if $PW1 has fewer than 6 characters false if $PW1 has more than 12 characters false if $PW1 and $PW2 do not match true otherwise*/function checkPassword($PW1,$PW2,$CheckLen=true){ $PW1 = trim($PW1); $PW2 = trim($PW2); if ($CheckLen) { return checkLength($PW1,6,12) && strcmp($PW1,$PW2) == 0; } else { return strcmp($PW1,$PW2) == 0; }}?>Code Explanation

Page 80: PHP Basics

This file is the same as the fnFormValidation.php file we saw before except that the checkPassword() function now takes an additional parameter: $CheckLen, which when set to false, will prevent the function from returning false if a blank password is entered.

Code Sample: ManagingData/Demos/Includes/ProcessEmployee.php<?php $DbEntries = $_POST; foreach ($DbEntries as &$Entry) { $Entry = dbString($Entry); } $DbEntries['Title'] = ucwords($DbEntries['Title']); ---- Code Omitted ----

if (array_key_exists('EmployeeID',$_POST)) { $PwCheckLen = false; } else { $PwCheckLen = true; }

if ( !checkPassword($_POST['Password1'],$_POST['Password2'],$PwCheckLen) ) { $Errors['Password'] = 'Passwords do not match or are not the right length.'; } else { $BrowserEntries['Password'] = browserString($_POST['Password1']); } ---- Code Omitted ---- ?><?php if (!count($Errors) && array_key_exists('EmployeeID',$_POST)) { $EmployeeID = $_POST['EmployeeID']; $Query = "UPDATE Employees SET FirstName='" . $DbEntries['FirstName'] . "', LastName='" . $DbEntries['LastName'] . "', Title='" . $DbEntries['Title'] . "', TitleOfCourtesy='" . $DbEntries['TitleOfCourtesy'] . "', Email='" . $DbEntries['Email'] . "', BirthDate='" . $DbEntries['BirthYear'] . '-' . $DbEntries['BirthMonth'] . '-' . $DbEntries['BirthDay'] . "', HireDate='" . $DbEntries['HireYear'] . '-' . $DbEntries['HireMonth'] . '-' . $DbEntries['HireDay'] . "', Address='" . $DbEntries['Address'] . "', City='" . $DbEntries['City'] . "', Region='" . $DbEntries['Region'] . "', PostalCode='" . $DbEntries['PostalCode'] . "', Country='" . $DbEntries['Country'] . "', HomePhone='" . $DbEntries['HomePhone'] . "',

Page 81: PHP Basics

Extension='" . $DbEntries['Extension'] . "', Notes='" . $DbEntries['Notes'] . "', ReportsTo=" . $DbEntries['ReportsTo']; if (CheckLength($DbEntries['Password'])) { $Query .= ", Password='" . $DbEntries['Password'] . "'"; } $Query .= " WHERE EmployeeID = $EmployeeID"; $DB->query($Query); echo '<div align="center">Record Updated</div>'; } elseif (!count($Errors)) { $ShowForm = false;?> ---- Code Omitted ---- } else { $DbEntries = $_POST; }?>Code Explanation

This file is the same as the ProcessEmployee.php file we saw before with a few important changes:

1. Instead of assigning values from $_POST to $DbEntries one by one, we simply copy $_POST into $DbEntries and then loop through the array to pass each element through dbString(). Notice the use of the & to make $Entry a reference to rather than a copy of the array element.

2. The call to checkPassword() now contains a third parameter to specify whether the function should return false if the password fields are not filled out. We only want to check the password length for new entries, not for updates.

3. If the EmployeeID key exists in the $_POST array, then the Edit Employee form has been submitted and a database query will be executed to update the employee record.

Exercise: Inserting RecordsDuration: 30 to 40 minutes.

In this exercise, you will work on the InsertEmployee.php script to insert new employees.

1. Open ManagingData/Exercises/InsertEmployee.php for editing. 2. Add code at the top to populate $DbEntries with SQL-safe entries from the form.

3. Make the connection to the database.

4. The SQL insert query has been started for you. Finish it.

5. Write code to execute the query.

Page 82: PHP Basics

o If the query succeeds, return "Employee Added" and a link to EmployeeReport.php. You will also need to set $ShowForm to false to prevent the form from reappearing.

o If the query fails, return "Insert failed".

Code Sample: ManagingData/Exercises/Includes/InsertEmployee.php<?php //Add code to populate $DbEntries with //SQL-safe entries from the form.

//Connect to the database //Finish the query below $Query = "INSERT INTO Employees (FirstName, LastName, Title, TitleOfCourtesy, Email, BirthDate, HireDate, Address, City, Region, PostalCode, Country, HomePhone, Extension, Notes, ReportsTo, Password)... //Execute the query. //If the query succeeds, return 'Employee Added' // and provide a link to EmployeeReport.php // and set $ShowForm to false //If it fails, return 'Insert failed'?>

Instead of hiding the form after an employee is inserted. Provide a new empty form, so that the user can enter another employee.

Where is the solution?

mysqli Prepared Statements

With mysqli it is possible to create prepared statements, which improve performance and improve security. Prepared statements are essentially templated queries to which you can bind input and output variables. To illustrate, look at the following example. (see footnote)

Code Sample: ManagingData/Demos/PreparedStatement.php<html><head><title>Prepared Statement</title></head><body><?php$CompanyID = $_GET['City']; //Try London

@$DB = new mysqli('localhost','root','pwdpwd','Northwind');if (mysqli_connect_errno()){ echo 'Cannot connect to database: ' . mysqli_connect_error();}

Page 83: PHP Basics

else{ $Query = 'SELECT CompanyName,ContactName,Phone FROM Customers WHERE City=?'; $Stmt = $DB->prepare($Query); $Stmt->bind_param('s',$CompanyID); $Stmt->execute(); $Stmt->bind_result($Company,$Contact,$Phone);?> <table border="1"> <tr> <th>Company</th> <th>Contact</th> <th>Phone</th> </tr><?php while ($Stmt->fetch()) { echo '<tr>'; echo "<td>$Company</td>"; echo "<td>$Contact</td>"; echo "<td>$Phone</td>"; echo '</tr>'; }?> </table><?php $Stmt->close(); $DB->close();}?></body></html>Code Explanation

Using the object-oriented interface, the process is as follows:

1. A query is created with question marks used as placeholders for parameters (input variables). 2. A statement is prepared using the prepare() method, which takes a query as an argument.

3. Parameters can be bound to the statement with the bind_param() method. The first argument of this method is a string that has one character for each subsequent argument. The character specifies the data type of that input parameter. For example, "isd" would specify that the input parameters are an integer, string, and double, in that order. The only other option is b for blob.

4. The statement is executed with the execute() method.

5. If the query returns results (e.g, SELECT queries), they can be bound to the statement with the bind_result() method.

6. The fetch() method can be used to fetch rows from the result set.

Prepared statements are most useful in cases where you have to loop through a dataset to do bulk inserts or updates.

Page 84: PHP Basics

Prepare Functions

Object-oriented Procedural Description

$db->prepare() mysqli_prepare() Prepares a SQL statement for execution.

$Stmt->bind_result() mysqli_stmt_bind_result() Binds variables to a prepared statement results.

$Stmt->bind_param() mysqli_stmt_bind_param() Binds variables to a prepared statement.

$Stmt->execute() mysqli_stmt_execute() Executes a prepared statement.

$Stmt->fetch() mysqli_stmt_fetch() Fetches results into the bound variables.

$Stmt->close() mysqli_stmt_close() Closes prepared statement.

PEAR:DBIn this lesson of the PHP tutorial, you will learn...

1. To use the PEAR DB package as a database abstraction layer.

PEAR (see footnote) supplies a number of open source extensions to PHP including its DB package, which provides a database abstraction layer, so that the PHP programmer doesn't have to worry about all the APIs for different databases.

Advantages and Disadvantages of PEAR DBWhether or not you decide to use PEAR DB or a similar database abstraction layer depends on your needs. If you need to be able to work on many applications and get your work done quickly, then PEAR DB is certainly helpful. If performance is key, then you may find the extra weight of PEAR DB to be prohibitive.

Why use a database abstraction layer?

One big benefit of using a database abstraction layer like PEAR DB is portability. PEAR DB allows you to use a single API for working with many different types of databases. So if you decide to move to another database, you will not have to rewrite all your code.

Another benefit is code simplification. If your application involves multiple databases of different flavors or you work on many applications each of which uses a different type of database, you would normally have to learn the APIs for each of the databases you would be working with. Again, PEAR DB allows you to work with all these databases using the same API.

Page 85: PHP Basics

When not to use a database abstraction layer?

The biggest downside of using a database abstraction layer is that the benefits come at a performance cost. Imagine you were planning to travel around Europe and had the choice of bringing an interpreter who could speak all European languages and learning the languages yourself. It would certainly be easier to bring the interpreter, but this would make each conversation you had somewhat slower. The abstraction layer is the interpreter.

Using PEAR DBThe connection string for connecting to the database with PEAR DB is:

Syntax

driver://username:password@host/database

Some of the drivers supported by PEAR DB are

mysqli myssql

mssql

oci8

odbc

pgsql

sybase

dbase

sqlite

Code Sample: PEAR-DB/Demos/EmployeeReport.php<html><head><title>Employee Report</title></head><body><?phprequire_once 'DB.php';@$DB = DB::connect('mysqli://root:pwdpwd@localhost/Northwind');if (DB::isError($DB)){ echo 'Cannot connect to database: ' . $DB->getMessage();}else{

Page 86: PHP Basics

$Query = 'SELECT * FROM Employees'; $Result = $DB->query($Query); $NumResults = $Result->numRows(); echo "<b>$NumResults Employees</b>";?> <table border="1"> <tr> <th>First Name</th> <th>Last Name</th> <th>Title</th> <th>Email</th> <th>Extension</th> </tr><?php while ($Row = $Result->fetchRow(DB_FETCHMODE_ASSOC)) { echo '<tr>'; echo '<td>' . $Row['FirstName'] . '</td>'; echo '<td>' . $Row['LastName'] . '</td>'; echo '<td>' . $Row['Title'] . '</td>'; echo '<td>' . $Row['Email'] . '</td>'; echo '<td align="right">x' . $Row['Extension'] . '</td>'; echo '</tr>'; }?> </table><?php $Result->free(); $DB->disconnect();}?></body></html>Code Explanation

As you can see, the PEAR DB API is very similar to the mysqli object-oriented API. Let's walk through the code.

1. First, we include the PEAR DB library. Notice that we simply use DB.php for the path:

require_once 'DB.php';

This will only work if:

o DB.php is in the same directory as EmployeeReport.php. This isn't likely as DB.php itself includes files, which would also have to be in the same directory.

o The include_path directive in php.ini includes a path to the pear folder containing DB.php.

2. Next, we connect to the database:

@$DB = DB::connect('mysqli://root:pwdpwd@localhost/Northwind');

Page 87: PHP Basics

This line of code will create a connection object if the connection is successful or an error object if it is not. The :: syntax will be covered when we discuss object-oriented PHP programming, but the crux of it is that the connect() method is a class-level method rather than an object-level method, so it can be called without first instantiating an object. (see footnote)

3. We then use the class-level isError() method to check if $DB is an error object, which would mean that the connection failed. If it did fail, we output an error.

4. if (DB::isError($DB))5. {6. echo 'Cannot connect to database: ' . $DB->getMessage();

}7. If the connection succeeded, we run our query: 8. $Query = 'SELECT * FROM Employees';9. $Result = $DB->query($Query);

$NumResults = $Result->numRows();10. And, after writing out our header row, we loop through the query results outputting a row for

each record returned: 11. while ($Row = $Result->fetchRow(DB_FETCHMODE_ASSOC))12. {13. echo '<tr>';14. echo '<td>' . $Row['FirstName'] . '</td>';15. echo '<td>' . $Row['LastName'] . '</td>';16. echo '<td>' . $Row['Title'] . '</td>';17. echo '<td>' . $Row['Email'] . '</td>';18. echo '<td align="right">x' . $Row['Extension'] . '</td>';

}

The fetchRow() method can take one of several constants to specify how a row is returned. In this example, we use DB_FETCHMODE_ASSOC to get the row as an associative array. Other options are DB_FETCHMODE_ORDERED (the default) and DB_FETCHMODE_OBJECT, which get the row as an indexed array and an object, respectively.

Exercise: Creating a Customer ReportDuration: 20 to 30 minutes.

In this exercise, you will create a sales report using PEAR DB.

1. Open PEAR-DB/Exercises/SalesReport.php for editing. 2. Write code to:

o Include the PEAR DB package.

o Connect to the Northwind database.

o If the connection fails, return an error message to the browser.

o If the connection succeeds run a query that gets the order date and the first and last name of the associated employee and the customer company for all orders. Order by OrderDate.

Page 88: PHP Basics

o Output the results of the query in a table.

o Free the result and disconnect from the database.

Code Sample: PEAR-DB/Exercises/SalesReport.php<html><head><title>Sales Report</title></head><body><?php//Include PEAR DB Package

//Connect to the Northwind database.// If the connection fails, return an error message to the browser.// If the connectoin succeeds run a query that gets the order date // and the first and last name of the associated employee // and the customer company for all orders. Order by OrderDate.?> <table border="1"> <tr> <th>#</th> <th>Salesperson</th> <th>Customer</th> <th>Order Date</th> </tr><?php //Create rows for each record returned from the query.?> </table><?php //Free the result and disconnect from the database.}?></body></html>

830 rows are returned. This is two many to display on a single page. MySQL has a LIMIT clause that specifies which and how many records to return from the query. For example, the query below would return 10 orders starting with the 100th order (note that the first row is row 0).

SELECT OrderDate, OrderIDFROM OrdersLIMIT 99,10;

Add code to your solution that allows the user to tab through the results 10 at a time with Previous and Next buttons.

Authentication with PHP and SQLIn this lesson of the PHP tutorial, you will learn...

Page 89: PHP Basics

1. To authenticate users with a login form.

A Database-less Login FormBelow is a simple login form that uses a hard-coded username and password.

Code Sample: Authentication/Demos/SimpleLogin.php<html><head><title>Login Page</title></head><body><?php require 'Includes/Header.php';

$msg=''; $Email = ''; if (array_key_exists('LoggingIn',$_POST)) { $Email = $_POST['Email']; $PW = $_POST['Password']; if ($Email == '[email protected]' && $PW == 'cowboy') { echo '<div align="center">Success</div>'; } else { echo '<div align="center">Login Failed</div>'; unset($_POST['LoggingIn']); } }

if (!array_key_exists('LoggingIn',$_POST)) {?>

<div align="center">

<h2>Log in</h2> <form method="post" action="SimpleLogin.php"> <input type="hidden" name="LoggingIn" value="true"> <table> <tr> <td>Email:</td> <td><input type="text" name="Email" value="<?php echo $Email?>" size="25"></td> </tr> <tr> <td>Password:</td> <td> <input type="password" name="Password" size="10"> </td> </tr> <tr>

Page 90: PHP Basics

<td align="right" colspan="2"> <input type="submit" value="Log in"> </td> </tr> </table> </form></div><?php } require 'Includes/Footer.php';?></body></html>Code Explanation

This page contains an HTML login form, which submits to itself (i.e, the action points to the same page). A hidden field, LoggingIn, is passed to the server when the user submits the form. The script checks to see if LoggingIn exists in the $_POST array. If it does, it processes the form input:

$Email = $_POST['Email'];$PW = $_POST['Password'];if ($Email == '[email protected]' && $PW == 'cowboy'){ echo '<div align="center">Success</div>';}else{ echo '<div align="center">Login Failed</div>'; unset($_POST['LoggingIn']);}

This code simply checks to see if the user's email and password match the hard-coded values ([email protected] and cowboy). If they do, it outputs a "success" message. If they don't, it outputs a "failed" message and removes LoggingIn from the $_POST array, so that the form will be displayed again.

Exercise: Authenticating UsersDuration: 25 to 35 minutes.

In this exercise, you will use mysqli or PEAR DB to authenticate users.

1. Open Authentication/Exercises/index.php in your editor. This file has been created for you and contains the underlying logic of the authentication application. You will see that it includes several of the scripts we saw in earlier exercises. Most of these are exactly the same, but a small change has been made to the pwEntry() function in Authentication/Exercises/Includes/fnFormPresentation.php. It now takes a fifth parameter: $Repeat. When $Repeat is set to true (default), the user will be asked to repeat her password (used for registration forms). When $Repeat is set to false, she'll just get a single password field (used for login forms).

Page 91: PHP Basics

2. Your job is to finish Authentication/Exercises/Includes/LoginForm.php and Authentication/Exercises/Includes/Login.php, which are currently both nearly empty. You may find it helpful to refer to ManagingData/Demos/Includes/EmployeeForm.php when creating LoginForm.php and to ManagingData/Demos/Includes/ProcessEmployee.php when creating Login.php.

Code Sample: Authentication/Exercises/index.php<?php require 'Includes/fnFormPresentation.php'; require 'Includes/fnStrings.php'; $Errors = array(); $DbEntries = array( 'Email'=>'', 'Password'=>'');?><html><head><title>Northwind Home Page</title></head><body><?php $msg=''; require 'Includes/Header.php'; if (array_key_exists('LoggingIn',$_POST)) { require 'Includes/Login.php'; } if (!array_key_exists('LoggingIn',$_POST)) { require 'Includes/LoginForm.php'; } if (strlen($msg) > 0) { echo "<div align='center'>$msg</div>"; } require 'Includes/Footer.php';?></body></html>

Regular ExpressionsIn this lesson of the PHP tutorial, you will learn...

1. To understand how regular expressions work. 2. To use regular expressions for advanced form validation.

Regular expressions are used to do sophisticated pattern matching. PHP supports two types of regular expressions: POSIX and Perl. The Perl style is more powerful and much more common, so we'll cover these in this class.

Page 92: PHP Basics

Perl-compatible Regular Expression Functionspreg_match()

The syntax for preg_match() is as follows.

preg_match(pattern, text_to_search);

preg_match() returns 1 if pattern is found in text_to_search and 0 if it is not.

preg_replace()

The syntax for preg_replace() is as follows.

preg_replace(pattern, replacement, text_to_search);

preg_replace() replaces all instances of pattern in text_to_search with replacement.

Regular Expression Tester

We have created a simple PHP-based regular expression tester. The code for the tester is shown below.

Code Sample: RegExp/Demos/Tester.php<?php@$Pattern = $_POST['Pattern'];@$TextToSearch = $_POST['TextToSearch'];?><html><head> <title>Regular Expression Tester</title><style> .reg {font-family:Verdana; font-size: 14pt; font-weight:bold; color:darkblue; text-decoration:none; padding: 4px} .reg:hover {border: 2px solid red; padding: 2px}</style>

<script>function usePattern(PATTERN){ document.formRE.Pattern.value=PATTERN; document.getElementById("display").innerHTML="<b>PATTERN: </b>" + PATTERN;}</script></head>

<body>

Page 93: PHP Basics

<h2><font face="Verdana, Arial, Helvetica, sans-serif">Regular Expression Tester</font></h2><form name="formRE" method="post"><table><tr> <td align="right"><font size="+2" face="Arial, Helvetica, sans-serif">Text to search:</font></td> <td><font size="+3" face="Arial, Helvetica, sans-serif"> <input type="text" name="TextToSearch" value="<?= $TextToSearch ?>" size="50" maxlength="50"> </font></td></tr><tr> <td align="right"><font size="+2" face="Arial, Helvetica, sans-serif" id="exp">Pattern:</font></td> <td><font size="+3" face="Arial, Helvetica, sans-serif"> <input type="text" name="Pattern" size="50" value="<?= $Pattern ?>" maxlength="100"> </font></td></tr><tr> <td colspan="2" align="center" style="font-size:18pt; font-family:Arial, Helvetica, sans-serif; background: #cccccc;"> <?php if (empty($Pattern)) echo '<font color="blue">Let\'s play!</font>'; elseif (preg_match($Pattern,$TextToSearch)) echo '<font color="green">Match</font>'; else echo '<font color="red">No Match</font>'; ?> </td></tr><tr align="center"><td colspan="2"><font size="+2" face="Arial, Helvetica, sans-serif"> <input type="submit" value="Submit"> <input type="reset"></font></td></tr>

<tr> <td colspan="2"> <table width="100%" border="0" cellpadding="4"> <tr> <th><a href="javascript:usePattern('/^[a-zA-Z0-9_\\-\\.]+@[a-zA-Z0-9\\-]+\\.[a-zA-Z0-9\\-\\.]+$/');" class="reg">Email</a></th> <th><a href="javascript:usePattern('/^[0-9]{3}[\\- ]?[0-9]{2}[\\- ]?[0-9]{4}$/');" class="reg">SSN</a></th> <th><a href="javascript:usePattern('/^\\(?[2-9][0-9]{2}\\)?[\\- ]?[0-9]{3}[\\- ]?[0-9]{4}$/');" class="reg">Phone</a></th> </tr> </table> </td></tr></table></form>

Page 94: PHP Basics

<div id="display" style="font-size:18pt; font-family:Courier New"><b>PATTERN:</b> <?= $Pattern ?></div>

</body></html>

Regular Expression SyntaxA regular expression is a pattern that specifies a list of characters. In this section, we will look at how those characters are specified. As we go through this section, we'll test some regular expression in our browser using our regular expression tester at RegExp/Demos/Tester.php.

Start and End ( ^ $ )

A caret (^) at the beginning of a regular expression indicates that the string being searched must start with this pattern.

The pattern ^foo can be found in "food", but not in "barfood".

A dollar sign ($) at the end of a regular expression indicates that the string being searched must end with this pattern.

The pattern foo$ can be found in "curfoo", but not in "food".

Number of Occurrences ( ? + * {} )

The following symbols affect the number of occurrences of the preceding character (see footnote): ?, +, *, and {}.

A questionmark (?) indicates that the preceding character should appear zero or one times in the pattern.

The pattern foo? can be found in "food" and "fod", but not "faod".

A plus sign (+) indicates that the preceding character should appear one or more times in the pattern.

The pattern fo+ can be found in "fod", "food" and "foood", but not "fd".

A asterisk (*) indicates that the preceding character should appear zero or more times in the pattern.

The pattern fo*d can be found in "fd", "fod" and "food".

Curly brackets with one parameter ( {n} ) indicate that the preceding character should appear exactly n times in the pattern.

Page 95: PHP Basics

The pattern fo{3}d can be found in "foood" , but not "food" or "fooood".

Curly brackets with two parameters ( {n1,n2} ) indicate that the preceding character should appear between n1 and n2 times in the pattern.

The pattern fo{2,4}d can be found in "food","foood" and "fooood", but not "fod" or "foooood".

Curly brackets with one parameter and an empty second paramenter ( {n,} ) indicate that the preceding character should appear at least n times in the pattern.

The pattern fo{2,}d can be found in "food" and "foooood", but not "fod".

Common Characters ( . \d \D \w \W \s \S )

A period ( . ) represents any character except a newline.

The pattern fo.d can be found in "food", "foad", "fo9d", and "fo*d".

Backslash-d ( \d ) represents any digit. It is the equivalent of [0-9].

The pattern fo\dd can be found in "fo1d", "fo4d" and "fo0d", but not in "food" or "fodd".

Backslash-D ( \D ) represents any character except a digit. It is the equivalent of [^0-9].

The pattern fo\Dd can be found in "food" and "foad", but not in "fo4d".

Backslash-w ( \w ) represents any word character (letters, digits, and the underscore (_) ).

The pattern fo\wd can be found in "food", "fo_d" and "fo4d", but not in "fo*d".

Backslash-W ( \W ) represents any character except a word character.

The pattern fo\Wd can be found in "fo*d", "fo@d" and "fo.d", but not in "food".

Backslash-s ( \s) represents any whitespace character (e.g, space, tab, newline, etc.).

The pattern fo\sd can be found in "fo d", but not in "food".

Backslash-S ( \S ) represents any character except a whitespace character.

The pattern fo\Sd can be found in "fo*d", "food" and "fo4d", but not in "fo d".

Grouping ( [] )

Square brackets ( [] ) are used to group options. This creates what is referred to as a "character class".

Page 96: PHP Basics

The pattern f[aeiou]d can be found in "fad" and "fed", but not in "food", "faed" or "fd". The pattern f[aeiou]{2}d can be found in "faed" and "feod", but not in "fod", "fed" or "fd".

Negation ( ^ )

When used after the opening square bracket of a character class, the caret ( ^ ) is used for negation.

The pattern f[^aeiou]d can be found in "fqd" and "f4d", but not in "fad" or "fed".

Subpatterns ( () )

Parentheses ( () ) are used to capture subpatterns.

The pattern f(oo)?d can be found in "food" and "fd", but not in "fod".

Alternatives ( | )

The pipe ( | ) is used to create optional patterns.

The pattern foo$|^bar can be found in "foo" and "bar", but not "foobar".

Escape Character ( \ )

The backslash ( \ ) is used to escape special characters.

The pattern fo\.d can be found in "fo.d", but not in "food" or "fo4d".

Form Validation Functions with Regular ExpressionsRegular expressions can be used to write sophisticated form validation functions. For example, earlier in the course, we wrote a checkEmail() function that looked like this:

function checkEmail($Email){ $Email = trim($Email); if (!checkLength($Email,6)) { return false; } elseif (!strpos($Email,'@')) { return false; }

Page 97: PHP Basics

elseif (!strpos($Email,'.')) { return false; } elseif (strrpos($Email,'.') < strpos($Email,'@')) { return false; } return true;}

We can use a regular expression to make this function both simpler and more powerful:

function checkEmail($Email){ $EmailPattern = '/^(\w+\.)*\w+@(\w+\.)+[A-Za-z]+$/'; return preg_match($EmailPattern,$Email));}

A nice thing about this is that we can use virtually the same function to do client-side validation with JavaScript:

function checkEmail(EMAIL){ var reEmail = /^(\w+[\-\.])*\w+@(\w+\.)+[A-Za-z]+$/; if (reEmail.test(EMAIL)) { return true; } else { return false; }}

So, by using regular expressions in this way, you make it easy to create a similar function library on the client side.

Session Control and CookiesIn this lesson of the PHP tutorial, you will learn...

1. To maintain sessions to track user visits. 2. To write and read cookies.

In the lesson on authenticaion, we created a login form and learned to authenticate users by comparing their emails and passwords to records in a database. In this lesson, we will use session variables to remember that the users are logged in as they go from page to page and we will use cookies to make it easier for users to log in on future visits.

Page 98: PHP Basics

SessionsA session begins when a visiting client somehow identifies itself to the web server. The web server assigns the client a unique session id, which the client uses to re-identify itself as it moves from page to page on the website. Most of the time, these unique ids are stored in session cookies that expire after the client hasn't interacted with the server for some amount of time. The amount of time varies depending on the web application. For example, an online investment site might have very short sessions, so that if a user leaves her computer without logging out, another user who sits down at the same computer several minutes later cannot continue with the first user's session.

Configuring Sessions

In PHP, session management is configured in the php.ini file. To have a user's session start as soon as the user visits the website, the session.auto_start flag must be set to 1.

The session length is also set in the php.ini file with the session.gc_maxlifetime variable. The default value is 1440 seconds (24 minutes).

Session Functions

The following table shows the most common session functions.

Function Explanation

session_start() Starts new session if one does not exist. Continues current session if one exists.

session_unset() Unsets all session variables.

session_destroy() Kills session.

Together, the files below illustrate how sessions can be tracked.

Code Sample: Sessions/Demos/Session1.php<?php//Begin a session and create a session variable in//the $_SESSION array. session_start();

$_SESSION['Greeting'] = 'Hello world!';

echo $_SESSION['Greeting'];?><hr/><a href="Session2.php">Next page</a>

Page 99: PHP Basics

Code Sample: Sessions/Demos/Session2.php<?php//Continue session, show that session variable still//exists and then unset the session variable session_start();

echo $_SESSION['Greeting'];

unset($_SESSION['Greeting']);?><a href="Session3.php">Next page</a>

Code Sample: Sessions/Demos/Session3.php<?php//Continue session, show that session variable no longer//exists and then kill session. session_start();

echo $_SESSION['Greeting'];

session_unset(); session_destroy();?>Code Explanation

The code above illustrates the following points.

Pages that are part of the session should begin with a call to session_start(). Session variables are created in the $_SESSION array.

Session variables are deleted in the same way as other variables – using the unset() function.

All session variables can be unset with the session_unset() function. This should be called before calling session_destroy().

Sessions are killed with a call to session_destroy().

CookiesCookies are stored in text files that sit on the client machine. Web pages with the right permissions can read from and write to cookies. They are generally used to track user information between visits.

In PHP, cookies are set with the setcookie() function, which can take several parameters including:

The cookie's name (required). The cookie's value.

Page 100: PHP Basics

The cookie's expiration date (if this isn't set, the cookie will expire when the browser window is closed).

The directory path on the server that can read the cookie.

The domain name that can read the cookie.

A flag indicating whether the cookie should only be read over https.

The following code will set a cookie that expires in one week.

setcookie('flavor','chocolate chip', time()+60*60*24*7);

There is no deletecookie() function. To delete a cookie, set the expiration date to sometime in the past, like this.

setcookie('flavor','chocolate chip', time()-10000);

Cookies are set in the HTTP header, so they must be set before any HTML code is passed back to the browser.

Exercise: Authentication with Session ControlDuration: 30 to 40 minutes.

In this exercise, you will create a login form that allows a user to log in to a site, rather than just a page on the site. You will also modify several other pages so that their content changes based on whether or not the user is logged in.

1. Open Sessions/Exercises/index.php in your editor. This file has been completed for you. Note the following:

o At the top of the document, we start a session with session_start().

o We've added an outer if condition to the body to check if EmployeeID already exists in the $_SESSION array. If it does, this means the user has already logged in.

o if (array_key_exists('EmployeeID',$_SESSION))o {o echo '<div align="center">o Logged in as ' .o $_SESSION['FirstName'] . ' ' . o $_SESSION['LastName'] .o '</div>';o }o elseo {o if (array_key_exists('LoggingIn',$_POST))o {o require 'Includes/Login.php';o }o if (!array_key_exists('LoggingIn',$_POST))o {

Page 101: PHP Basics

o require 'Includes/LoginForm.php';o }o if (strlen($msg) > 0)o {o echo "<div align='center'>$msg</div>";o }o }

2. Open Sessions/Exercises/Includes/Login.php (you can use LoginPear.php if you prefer) in your

editor. Modify the code, so that when the user logs in, she is remembered for the duration of her visit. You should remember her first name, last name and employee id.

3. Sessions/Exercises/Includes/Footer.php has been changed to include a "Log out" link, which points to Sessions/Exercises/Logout.php. Open Sessions/Exercises/Logout.php in your editor. Add code to log the user out (i.e, delete all session variables and kill the session).

4. Open Sessions/Exercises/OtherPage.php in your editor. Notice that it includes Includes/LoginCheck.php.

5. Open Sessions/Exercises/Includes/LoginCheck.php in your editor. You will see that it currently contains code to redirect the page to index.php. Modify this script so that it only redirects to index.php if the user is not logged in.

Write code so that the user can indicate that she would like to be remembered between visits. If she chooses to be remembered, she should not have to log in again for a week. You will need to modify index.php, Includes/LoginForm.php, Includes/Login.php and Includes/Logout.php. You may also find it useful to create a new include file (e.g, CookieCheck.php) to hold the code that checks for the cookie

Sending Email with PHPIn this lesson of the PHP tutorial, you will learn...

1. To send emails using PHP's built-in mail() function. 2. To send email using PHPMailer, a PHP extension with more features than mail().

mail()PHP has a built-in mail() function that makes it easy to send email.

Mail Parameters

Method Description

To The address to send the email to.

Subject The email's subject.

Page 102: PHP Basics

Mail Parameters

Method Description

Message The body of the email.

Additional Headers Optional. Additional headers (e.g, From, Reply-To)

Additional Parameters Optional. Any additional parameters you may want to send to your mail server.

Code Sample: Email/Demos/Mail.php<html><head><title>Mail()</title></head><body><?php if (!array_key_exists('Submitted',$_POST)) {?> <form method="post" action="Mail.php"> <input type="hidden" name="Submitted" value="true"/> Mail Server: <input type="text" name="Host" size="25"/><br/> To: <input type="text" name="To" size="25"/><br/> From: <input type="text" name="From" size="25"/><br/> Subject: <input type="text" name="Subject" size="25"/><br/> <textarea name="Message" cols="50" rows="10"></textarea><br/> <input type="submit" value="Send Email"/> </form><?php } else { ini_set('SMTP',$_POST['Host']); $To = $_POST['To']; $From = 'From: ' . $_POST['From']; $Subject = $_POST['Subject']; $Message = $_POST['Message']; if(mail($To,$Subject,$Message,$From)) { echo "Message Sent"; } else { echo "Message Not Sent"; } }?></body></html>Code Explanation

Page 103: PHP Basics

For this example to work, you will need to have a mail server set up on your server.

The first time a visitor hits the page, he'll be presented with a form. When the user fills out and submits that form, the mail() function will attempt to send an email to the address the user entered.

Note that the mail server is set with the ini_set() function, which is used to temporarily change configuration settings. You can set the default mail server in the php.ini file with the SMTP setting.

Shortcomings of mail()

The mail() function has many limitations.

No support for SMTP authentication. Difficult to send HTML-formatted emails.

Difficult to add attachments.

Luckily, there are extensions that do provide these features.

PHPMailerA very good email extension is PHPMailer, which is available for free at http://phpmailer.sourceforge.net. We will use PHPMailer in our examples and exercises. The following tables show some of the more common methods and properties of PHPMailer.

PHPMailer Methods

Method Description

AddAddress() Adds a "To" address.

AddAttachment() Adds an attachment from a path on the filesystem.

AddBCC() Adds a "bcc" address.

AddCC() Adds a "cc" address.

AddReplyTo() Adds a "Reply-to" address.

IsHTML() Sets message type to HTML.

IsSMTP() Sets Mailer to send message using SMTP.

Send() Creates message and assigns Mailer. If the message is not sent successfully then it

Page 104: PHP Basics

PHPMailer Methods

Method Description

returns false.

PHPMailer Properties

Property Description

AltBody Sets the text-only body of the message.

Body Sets the Body of the message. This can be either an HTML or text body.

ErrorInfo Holds the most recent mailer error message.

From Sets the From email address for the message.

FromName Sets the From name of the message.

Host Sets the SMTP hosts. All hosts must be separated by semicolons.

Password Sets SMTP password.

SMTPAuth Sets SMTP authentication. Utilizes the Username and Password properties.

Subject Sets the Subject of the message.

Username Sets SMTP username.

WordWrap Sets word wrapping on the body of the message to a given number of characters.

Code Sample: Email/Demos/PHPMailer.php<html><head><title>PHPMailer</title></head><body><?php if (!array_key_exists('Submitted',$_POST)) {?> <form method="post" action="PHPMailer.php"> <input type="hidden" name="Submitted" value="true"/><br/> Mail Server: <input type="text" name="Host" size="25"/><br/> If authentication is required:<br/> Username: <input type="text" name="Username" size="25"/><br/> Password: <input type="password" name="Password" size="10"/> <hr/>

Page 105: PHP Basics

To: <input type="text" name="To" size="25"/><br/> From Email: <input type="text" name="From" size="25"/><br/> From Name: <input type="text" name="FromName" size="25"/><br/> Subject: <input type="text" name="Subject" size="25"/><br/> <textarea name="Message" cols="50" rows="10"></textarea><br/> Using HTML: <input type="checkbox" name="HTML"/> <input type="submit" value="Send Email"/> </form><?php } else { require("class.phpmailer.php"); $To = $_POST['To']; $From = $_POST['From']; $FromName = $_POST['FromName']; $Subject = $_POST['Subject']; $Message = $_POST['Message']; $Host = $_POST['Host']; if (array_key_exists('HTML',$_POST)) { $HTML = true; $Mail->Username=$_POST['Username']; $Mail->Password=$_POST['Password']; } else { $HTML = false; } $Mail = new PHPMailer(); $Mail->IsSMTP(); // send via SMTP $Mail->Host = $Host; //SMTP server if (array_key_exists('Username',$_POST)) { $Mail->SMTPAuth=true; } else { $Mail->SMTPAuth=false; } $Mail->From = $From; $Mail->FromName = $FromName; $Mail->AddAddress($To); $Mail->AddReplyTo($From); $Mail->WordWrap = 50; // set word wrap $Mail->IsHTML($HTML); $Mail->Subject = $Subject; $Mail->Body = $Message; if($Mail->Send())

Page 106: PHP Basics

{ echo "Message Sent"; } else { echo "Message Not Sent<br/>"; echo "Mailer Error: " . $Mail->ErrorInfo; } }?></body></html>Code Explanation

As you can see, PHPMailer comes with a full set of intuitive methods and properties that make sending emails very easy.

Exercise: Sending a Password by EmailDuration: 20 to 30 minutes.

In this exercise, you will create a Password Reminder page that allows users to have their passwords sent to them by email.

1. Open Mail/Exercises/PasswordReminder.php in your editor. 2. This page contains a simple form that submits to the same page.

3. In the else block of the if condition add code that sends the user her password, which you'll need to get from the Northwind database.

4. BCC yourself on the email. You'll need this to check to see that your solution is working.

5. If the email fails to send, output the error to the browser. Otherwise, let the user know the password has been sent.

6. Test your solution in your browser.

File System ManagementIn this lesson of the PHP tutorial, you will learn...

1. To read from files on the server. 2. To write to files on the server.

3. To upload files to the server.

4. To get information about files on the server.

5. To access and work with directories on the server.

Page 107: PHP Basics

Most Web applications use databases to store large amounts of data. However, in some cases, it will be necessary to store data in or access data from files.

Opening a Filefopen()Syntax

fopen (path_to_file, file_mode)

path_to_file can either be a relative or an absolute path.

File Modes

File Mode Description

r open for reading

w open for writing (erases existing content); creates new file if one doesn't exist

a open for appending to end of content; creates new file if one doesn't exist

x create and open for writing (new in PHP 4.3.2); fails and returns false if file already exists

r+ open for reading and writing (erases existing content when file is written to)

w+ open for writing and reading (erases existing content on opening or creates new file if one doesn't exist

a+ open for appending and writing; creates new file if one doesn't exist

x+ create and open for writing and reading (new in PHP 4.3.2); fails and returns false if file already exists

File Permissions

Files that do no have the appropriate permissions settings will fail to open. In this case, the fopen() function will return false and a warning will be given. Use conditional processing as shown below to handle this situation.

$MyFile = @fopen('MyFile.txt','a');if (!$MyFile){ echo '<b>Sorry, but the file cannot be opened.</b>';}else

Page 108: PHP Basics

{ // code for processing file}

The @ symbol in front of first line of code is used to suppress errors. Any errors can then be handled more gracefully.

Reading from a FileOpening a file for reading involves three steps:

1. Open the file. 2. Read the file.

3. Close the file.

fgets()

fgets() is used to read a file one line at a time. It requires one argument: the resource or "handle" for the file and accepts a second argument: the length of the line. It will continue reading the line until the length - 1 have been read or it reaches the end of the line or the end of the file. If the second argument is not included, it will continue reading until it reaches the end of the line.

Examine the file shown below.

Code Sample: Files/Demos/Employees.txtNancy Davolio Sales Representative [email protected] Fuller Vice President, Sales [email protected] Leverling Sales Representative [email protected] Peacock Sales Representative [email protected] Buchanan Sales Manager [email protected] Suyama Sales Representative [email protected] King Sales Representative [email protected] Callahan Inside Sales Coordinator [email protected] Dodsworth Sales Representative [email protected] Explanation

Employees.txt is a tab-delimited text file. Each line is formatted as follows:

FirstName\tLastName\tTitle\tEmail\n

The file is divided into "columns" using tabs (\t) and each "row" is separated by a newline character (\n). The code below opens Employees.txt, reads and displays each line, and closes the file.

Page 109: PHP Basics

Code Sample: Files/Demos/Employees.php<html><head> <title>Employees</title></head><body><h1>Employees</h1><?php $MyFile = @fopen("Employees.txt", 'r'); if (!$MyFile) { echo '<p>Cannot open file.'; } else { while (!feof($MyFile)) { $Employee = fgets($MyFile, 999); echo $Employee.'<br />'; } fclose($MyFile); }?></body></html>

Other options for reading from files

Function Description

fgetss() Like fgets() but it strips out HTML and PHP tags.

fgetcsv() Like fgets() but it splits the file on a specified delimiter rather than a newline character.

readfile() Opens a file, sends its contents to the browser, and closes the file.

file() Opens a file, splits it into an array on newline characters, and closes the file.

Writing to a FileOpening a file for writing involves three steps:

1. Open the file. 2. Write to the file.

3. Close the file.

fwrite()Syntax

Page 110: PHP Basics

fwrite(file_pointer,output_string)

The output_string is the text to write to the file. See the following example of writing to a file.

$OutputString='text to write';$MyFile = @fopen('Employees.txt', 'a');fwrite($MyFile, $OutputString);fclose($MyFile);

Exercise: Writing to a FileDuration: 10 to 15 minutes.

In this exercise you will write code to append entries to the Employees.txt.

1. Open Files/Exercises/AddEmployee.php in your editor. 2. Create short versions of the form variables.

3. Write code to save the entry in Employees.txt, which is in the same directory. The steps involved are:

1. Open Employees.txt for appending. Be sure to suppress errors.

2. Write a condition that checks to see if the file failed to open.

3. If it did open, write the output string to the file and close the file.

Where is the solution?

File Lockingflock() (see footnote)

flock() is used to lock a file so that two or more people do not get access to it at the same time. This helps protect the file from being corrupted. flock() takes two arguments: a file handler and a lock type.

Lock Type Explanation

LOCK_SH Reading lock. Others can read file.

LOCK_EX Exclusive lock. The file cannot be opened by others.

LOCK_UN Unlocks file.

LOCK_NB If a file is already locked by another user, flock() waits to get a lock. LOCK_NB tells it not to wait.

Page 111: PHP Basics

The code below shows how we should change Files/Solutions/AddEntry.php to protect Employees.txt from being corrupted.

Code Sample: Files/Demos/Locking.php ---- Code Omitted ----

flock($MyFile, LOCK_EX); fwrite($MyFile,$OutputString); flock($MyFile, LOCK_UN); fclose($MyFile); ---- Code Omitted ----

Uploading Files via an HTML Form (see footnote) In order to upload files via an HTML form, the form tag's method must be set to "post" and the enctype must be set to "multipart/form-data" as shown below.

Syntax

<form method="post" enctype="multipart/form-data">

The following example demonstrates how to safely allow the user to upload a file to the server.

Code Sample: Files/Demos/FileUpload.php<html><head><title>Resume Upload</title></head><body style="text-align:center"><?php if (!array_key_exists('Submitted',$_POST)) {?><h2>Resume Upload Form</h2><form method="post" enctype="multipart/form-data"><input type="hidden" name="Submitted" value="true"><table border="1"><tr> <td>First Name</td> <td><input type="text" name="FirstName" size="20"></td></tr><tr> <td>Last Name</td> <td><input type="text" name="LastName" size="20"></td></tr><tr> <td>Resume</td> <td><input type="file" name="Resume"></td></tr>

Page 112: PHP Basics

<tr> <td colspan="2" align="center"><input type="submit" value="Upload"></td></tr></table></form><?php} else { //process the form $ResumeFile = $_FILES['Resume']['tmp_name']; $FileSize = $_FILES['Resume']['size']; $FileType = $_FILES['Resume']['type']; $FileError = $_FILES['Resume']['error'];

$ResumeName=$_POST['FirstName'] . '_' . $_POST['LastName'] . '_Resume.txt'; if ($FileError) { echo "We could not upload the file:<br/>$FileError"; EndPage(); } elseif ($FileType != 'text/plain') { echo "You have attempted to upload a file of type: $FileType. <br/>Only text files allowed."; EndPage(); }

$FileSavePath = 'Resumes/' . $ResumeName; if (is_uploaded_file($ResumeFile)) { if (!move_uploaded_file($ResumeFile,$FileSavePath)) { echo 'Could not save file.'; EndPage(); } } else { //This case happens if somehow the file //we are working with was already on the server. //It's to stop hackers. echo 'Hey, what is going on here? Are you being bad?'; EndPage(); } $Resume=makeFileSafe($FileSavePath);?> <h2>Thanks!</h2> <b>We got your resume.</b><hr> <form> <textarea cols="60" rows="20"><?echo $Resume?></textarea> </form> </p><?php}

function EndPage()

Page 113: PHP Basics

{ echo '</body></html>'; exit;}

function makeFileSafe($FilePath){ $FP = @fopen($FilePath,'r+'); if (!$FP) { return "Could not read file"; } $Contents = fread($FP,filesize($FilePath)); $Contents = strip_tags($Contents); rewind($FP); fwrite($FP,$Contents); fclose($FP); return $Contents;}?></body></html>Code Explanation

The first thing to notice about this page is that it submits to itself. The first time it is loaded, it will show the form. When the form is submitted, it will attempt to upload and save the user's resume.

1. The form also has an input field of type file that is used to browse for the file to upload. 2. When the form is submitted, the script assigns values to short named variables.

3. The next block of code is the if-elseif-elseif statement, which checks for errors. If it finds any, it displays an appropriate message and calls the EndPage() user function, which just closes the HTML page.

4. The next piece of code attempts to upload the file:

5. if (is_uploaded_file($ResumeFile))6. {7. if (!move_uploaded_file($ResumeFile,$FileSavePath))8. {9. echo 'Could not save file.';10. EndPage();11. }12. }13. else14. {15. //This case happens if somehow the file16. //we are working with was already on the server.17. //It's to stop hackers.18. echo 'Hey, what is going on here?19. Are you being bad?';20. EndPage();

}

Page 114: PHP Basics

21. The last bit of PHP code on the page calls the makeFileSafe() user function which opens the resume file, strips out all the tags from its contents and closes it.

Getting File InformationThe following code sample illustrates how to get information about a file using PHP.

Code Sample: Files/Demos/FileInfo.php<html><head> <title>File Details</title></head><body><?php $CurrentDir = 'Resumes/'; $File = basename('J_C_Resume.txt'); echo '<h1>Details of file: ' . $File.'</h1>'; $File = $CurrentDir.$File; echo '<h2>File data</h2>'; echo 'File last accessed: ' . date('j F Y H:i', fileatime($File)) . '<br/>'; echo 'File last modified: ' . date('j F Y H:i', filemtime($File)).'<br/>'; echo 'File type: ' . filetype($File).'<br/>'; echo 'File size: '.filesize($File).' bytes<br/>'; echo '<h2>File tests</h2>'; echo 'is_dir: ' . (is_dir($File)? 'true' : 'false') . '<br/>'; echo 'is_file: ' . (is_file($File)? 'true' : 'false').'<br/>'; echo 'is_readable: ' . (is_readable($File)? 'true' : 'false').'<br/>'; echo 'is_writable: ' . (is_writable($File)? 'true' : 'false').'<br/>';?></body></html>Code Explanation

The functions used in this script are described in the following table.

Function Description

basename() Strips off the path and returns the file name.

fileatime() Returns the last accessed time of the file.

filemtime() Returns the last modified time of the file.

Page 115: PHP Basics

Function Description

filetype() Returns the type of file (e.g, file or dir).

filesize() Returns the size of the file in bytes.

is_dir() Returns true if the passed value is a directory, false if it isn't.

is_file() Returns true if the passed value is a file, false if it isn't.

is_readable() Returns true if the file is readable, false if it isn't.

is_writable() Returns true if the file is writable, false if it isn't.

More File FunctionsA few more file functions are shown below:

Function Description

file_exists(path_to_file) Checks to see if a file exists.

filesize(path_to_file) Returns the size of file in bytes.

unlink(path_to_file) Deletes the file.

copy() Copies a file. Takes two arguments: the path to the source file and the destination to copy the source file to.

rename() Moves a file. Takes two arguments: the path to the source file and the destination to move the source file to. If the path and destination are the same with the exception of the filename, rename() simply renames the file.

Directory FunctionsThe following table shows some of the more common directory functions.

Function Description

mkdir() Creates a directory.

rmdir() Deletes a directory.

Page 116: PHP Basics

Function Description

opendir() Opens a directory for reading.

readdir() Reads the contents of an open directory.

Getting a Directory Listing

To get a directory listing, use the opendir() function to open the directory and the readdir() function to read its contents. Then loop through its contents with a while loop outputting the name of each file and folder.

Exercise: Creating a Resume Management PageDuration: 20 to 30 minutes.

In this exercise, you will create a simple resume management page that will list all the resumes currently in the resumes folder and allow you to remove resumes from the folder.

1. Open Files/Exercises/FileListing.php in your editor. Much of the file is done already. 2. Complete the fileDetails() function so that it will properly display the details of the passed file.

3. At the end of the if block of the fileDetails() function there is a "Delete File" link. Modify this link so that it passes the file path in the "Delete" variable via the query string.

4. Write the browseDir() function.

5. Write the deleteFile() function.

Write a renameFile() function and add a form to the fileDetails() function that allows the user to provide a new name for the file.

Where is the solution?

File System Management ConclusionAlthough writing to and reading from files can be useful in certain situations, when it is important to be able to access and change data quickly and to maintain the integrity of that data, it is often better to use a database.

Many websites allow visitors to upload files via a form. In this lesson, we have stored those files in a directory under the web root. For security reasons, this is generally not a good idea. In practice, you should store any uploaded files above or outside of the web root.

Page 117: PHP Basics