PHP, MySQL, JavaScript & HTML5 All-in-One For Dummies (2013)

Book IV: PHP

Chapter 2: Building PHP Scripts

In This Chapter

arrow.png Setting up conditions in your code

arrow.png Using conditional statements

arrow.png Building and using loops for repeated statements

arrow.png Using functions

arrow.png Keeping your code clean and organized

PHP scripts are a series of instructions in a file named with an extension that tells the web server to look for PHP sections in the file. (The extension is usually .php or .phtml, but it can be anything that the web server is configured to expect.) PHP begins at the top of the file and executes each instruction, in order, as it comes to it.

Instructions, called statements, can be simple or complex. Chapter 1 in this minibook discusses what we term "simple" statements, such as the echo statement. For example, the Hello World script in Chapter 1 in this minibook is a simple script containing only simple statements. However, the scripts that make up a web database application aren't that simple. They are dynamic and interact with both the user and the database. Consequently, the scripts require more complex statements.

Complex statements execute one or more blocks of statements. A block of statements consists of a group of simple statements enclosed by curly braces ({ and }). PHP looks for the ending curly brace of the last block in complex statements.

The following complex statements are described in this chapter:

check Conditional statements: Statements that execute only when certain conditions are met. The PHP conditional statements are if and switch statements.

check Loops: Statements that repeatedly execute a block of statements. Four types of loops are foreach, for, while, and do..while loops.

check Functions: Statements that can be reused many times. Many tasks are performed in more than one part of the application. PHP allows you to reuse statement blocks by creating a function.

Conditional statements and loops execute a block of statements based on a condition. That is, if a condition is true, the block of statements executes. Thus, to use conditional statements and loops, you need to set up conditions.

In this chapter, you find out how to use complex statements and how to organize them into a PHP script.

Setting Up Conditions

Conditions are expressions that PHP tests or evaluates to see whether they are true or false. Conditions are used in complex statements to determine whether a block of simple statements should be executed. To set up conditions, you compare values. Here are some questions you can ask to compare values for conditions:

check Are two values equal? Is Sally’s last name the same as Bobby’s last name? Or, is Nick 15 years old? (Does Nick’s age equal 15?)

check Is one value larger or smaller than another? Is Nick younger than Bobby? Or, did Sally’s house cost more than a million dollars?

check Does a string match a pattern? Does Bobby’s name begin with an S? Does the ZIP code have five numeric characters?

You can also set up conditions in which you ask two or more questions. For example, you may ask: Is Nick older than Bobby and is Nick younger than Sally? Or you may ask: Is today Sunday and is today sunny? Or you may ask: Is today Sunday or is today Monday?

Comparing values

You can compare numbers or strings to see whether they are equal, whether one is larger than the other, or whether they are not equal. You compare values with comparison operators. PHP evaluates the comparison and returns true or false. For example, the following is a simple comparison:

$result = $a == $b;

The comparison operator == checks whether two values are equal. If $a and $b are equal, $result is assigned the Boolean value true. If $a and $b are not equal, $result is assigned false. Thus, $a == $b is a simple condition that is either true or false.

PHP offers several comparison operators that you can use to compare values. Table 2-1 shows these comparison operators.

Table 2-1 Comparison Operators

Operator

What It Means

==

Are the two values equal in value?

===

Are the two values equal in both value and data type?

Is the first value larger than the second value?

>=

Is the first value larger than or equal to the second value?

Is the first value smaller than the second value?

<=

Is the first value smaller than or equal to the second value?

!=, <>

Are the two values not equal to each other in value?

!==

Are the two values not equal to each other in either value or data type?

You can compare both numbers and strings. Strings are compared alphabetically, with all uppercase characters coming before any lowercase characters. For example, SS comes before Sa. Punctuation characters also have an order, and one character can be found to be larger than another character. However, comparing a comma to a period doesn't have much practical value.

technicalstuff.eps Strings are compared based on their ASCII code. In the ASCII character set, each character is assigned an ASCII code that corresponds to a number between 0 and 127. When strings are compared, they are compared based on this code. For example, the number that represents the comma is 44. The period corresponds to 46. Therefore, if a period and a comma are compared, the period is evaluated as larger.

The following are some valid comparisons that PHP can test to determine whether they’re true:

check $a == $b

check $age != 21

check $ageNick < $ageBobby

check $house_price >= 1000000

warning_bomb.eps The comparison operator that asks whether two values are equal consists of two equal signs (==). One of the most common mistakes is to use a single equal sign for a comparison. A single equal sign puts the value into the variable. Thus, a statement like if ($weather = "raining") would set $weather to raining rather than check whether it already equaled raining, and would always be true.

If you write a negative (by using !), the negative condition is true. Look at the following comparison:

$age != 21

The condition being tested is that $age does not equal 21. Therefore, if $age equals 20, the comparison is true.

Checking variable content

Sometimes you just need to know whether a variable exists or what type of data is in the variable. Here are some common ways to test variables:

isset($varname)    # True if variable is set, even if

                     nothing is stored in it.

empty($varname)    # True if value is 0 or is a string with

                     no characters in it or is not set.

You can also test what type of data is in the variable. For example, to see whether the value is an integer, you can use the following:

is_int($number)

The comparison is true if the value in $number is an integer. Some other tests provided by PHP are as follows:

check is_array($var2): Checks to see whether $var2 is an array.

check is_float($number): Checks to see whether $number is a floating point number.

check is_null($var1): Checks to see whether $var1 is equal to 0.

check is_numeric($string): Checks to see whether $string is a numeric string.

check is_string($string): Checks to see whether $string is a string.

You can test for a negative condition, as well, by using an exclamation point (!) in front of the expression. This is really a logical NOT condition, as in "If this condition is NOT true, do something." For example, the following statement returns true if the variable doesn't exist at all:

!isset($varname)

You could think of that in plain language as "If $varname is not set . . . ."

Pattern matching with regular expressions

Sometimes you need to compare character strings to see whether they fit certain characteristics, rather than to see whether they match exact values. For example, you might want to identify strings that begin with S or strings that have numbers in them. For this type of comparison, you compare the string to a pattern. These patterns are called regular expressions.

You've probably used some form of pattern matching in the past. When you use an asterisk (*) as a wild card when searching for files (dir ex*.doc, for example), you're pattern matching. For example, ex*.txt is a pattern. Any string that begins with ex and ends with .txt, with any characters in between the ex and the .txt, matches the pattern. The strings exam.txt, ex33.txt, and ex3x4.txt all match the pattern. Using regular expressions is just a more powerful variation of using wild cards.

One common use for pattern matching is to check the input from a web page form. If the information input doesn’t match a specific pattern, it might not be something you want to store in your database. For example, if the user types a ZIP code into your form, you know the format needs to be five numbers or a ZIP + 4. So, you can check the input to see whether it fits the pattern. If it doesn’t, you know it isn’t a valid ZIP code, and you can ask the user to type in the correct information.

Regular expressions are used for pattern matching in many situations. Many Linux commands and programs, such as grep, vi, or sed, use regular expressions. Many applications, such as text editors and word processors, allow searches using regular expressions.

PHP provides support for Perl-compatible regular expressions. The following sections describe some basic Perl-compatible regular expressions, but much more complex and powerful pattern matching is possible. See www.php.net/manual/en/reference.pcre.pattern.syntax.php for further explanation of Perl-compatible regular expressions.

Using special characters in patterns

Patterns consist of literal characters and special characters.

check Literal characters are normal characters, with no special meaning. An e is an e, for example, with no meaning other than that it’s one of 26 letters in the alphabet.

check Special characters, on the other hand, have special meaning in the pattern, such as the asterisk (*) when used as a wild card. Table 2-2 shows the special characters that you can use in patterns.

Table 2-2

Considering some example patterns

Literal and special characters are combined to make patterns, sometimes long, complicated patterns. A string is compared with the pattern, and if it matches, the comparison is true. Some example patterns follow, with a breakdown of the pattern and some sample matching and non-matching strings.

Example 1

^[A-Za-z].*

This pattern defines strings that begin with a letter and have these two parts:

check ^[A-Za-z]: The first part of the pattern dictates that the beginning of the string must be a letter (either upper- or lowercase).

check .*: The second part of the pattern tells PHP the string of characters can be one or more characters long, including numbers, spaces, or anything.

The expression ^[A-Za-z].* matches the following strings: play it again, Sam, 4 times, and I.

The expression ^[A-Za-z].* does not match the following strings: 123 and ?.

Example 2

Dear (Kim|Rikki)

This pattern defines two alternate strings and has these two parts:

check Dear: The first part of the pattern is just literal characters followed by a space.

check (Kim|Rikki): The second part defines either Kim or Rikki as matching strings.

The expression Dear (Kim|Rikki) matches the following strings: Dear Kim and My Dear Rikki.

The expression Dear (Kim|Rikki) does not match the following strings: Dear Bobby and Kim.

Example 3

^[0-9]{5}(\-[0-9]{4})?$

This pattern defines any ZIP code and has several parts:

check ^[0-9]{5}: The first part of the pattern describes any string of five numbers.

check \-: The backslash indicates that the hyphen is a literal.

check [0-9]{4}: This part of the pattern tells PHP that the next characters should be a string of numbers consisting of four characters.

check ( )?: These characters group the last two parts of the pattern and make them optional.

check $: The dollar sign dictates that this string should end (no characters are allowed after the pattern).

The expression ^[0-9]{5}(\-[0-9]{4})?$ matches the following strings: 90001 and 90002-4323.

The expression ^[0-9]{5}(\-[0-9]{4})?$ does not match the following strings: 9001 and 12-4321.

Example 4

^.+@.+\.com$

This pattern defines any string with @ embedded that ends in .com. In other words, it defines a common (but not the only) format for an e-mail address. This expression has several parts:

check ^.+: The first part of the pattern describes any string of one or more characters that precede the @.

check @: This is a literal @ ("at" sign). @ is not a special character and does not need to be preceded by \.

check .+: This is any string of one or more characters.

check \.: The slash indicates that PHP should look for a literal dot.

check com$: This defines the literal string com at the end of the string, and the $ marks the end of the string.

The expression ^.+@.+\.com$ matches the following strings: you@yourcompany.com and johndoe@somedomain.com.

The expression ^.+@.+\.com$ does not match the following strings: you@yourcompany.net, you@.com, and @you.com.

Using PHP functions for pattern matching

You can compare whether a pattern matches a string with the preg_match function. The general format is as follows:

preg_match("pattern",value);

The pattern must be enclosed in a pair of delimiters — characters that enclose the pattern. Often, the forward slash (/) is used as a delimiter. How-ever, you can use any nonalphanumeric character, except the backslash (\). For example, to check the name that a user typed in a form, match the pattern with the name (stored in the variable $name), as follows:

preg_match("/^[A-Za-z' -]+$/",$name)

The pattern in this statement does the following:

check Encloses the pattern in forward slashes (/).

check Uses ^ and $ to signify the beginning and end of the string, respectively. That means that all the characters in the string must match the pattern.

check Encloses all the literal characters that are allowed in the string in [ ]. No other characters are allowed. The allowed characters are upper- and lowercase letters, an apostrophe ('), a blank space, and a hyphen (-).

You can specify a range of characters by using a hyphen within the [ ]. When you do that, as in A-Z, the hyphen doesn't represent a literal character. Because you also want a hyphen included as a literal character that is allowed in your string, you need to add a hyphen that isn't between any two other characters. In this case, the hyphen is included at the end of the list of literal characters.

check Follows the list of literal characters in the [ ] with a +. The plus sign means that the string can contain any number of the characters inside the [ ], but must contain at least one character.

If the pattern itself contains forward slashes, the delimiter can’t be a forward slash. You must use another character for the delimiter, such as:

preg_match("#^[A-Za-z' -/]+$#",$name)

Joining multiple comparisons

Often you need to ask more than one question to determine your condition. For example, suppose your company offers catalogs for different products in different languages. You need to know which type of product catalog the customer wants to see and which language he or she needs to see it in. This requires you to join comparisons, which have the following the general format:

comparison1 and|or|xor comparison2 and|or|xor comparison3 and|or|xor ...

Comparisons are connected by one of the following three words:

check and: Both comparisons are true.

check or: One or both comparisons are true.

check xor: Only one of the comparisons is true.

Table 2-3 shows some examples of multiple comparisons.

Table 2-3 Multiple Comparisons

Condition

Is True If . . .

$ageBobby == 21 or $ageBobby == 22

Bobby is 21 or 22 years of age.

$ageSally > 29 and $state =="OR"

Sally is older than 29 and lives in Oregon.

$ageSally > 29 or $state == "OR"

Sally is older than 29 or lives in Oregon or both.

$city == "Reno" xor $state == "OR"

The city is Reno or the state is Oregon, but not both.

$name != "Sam" and $age < 13

The name is anything except Sam and age is under 13 years of age.

You can string together as many comparisons as necessary. The comparisons using and are tested first, the comparisons using xor are tested next, and the comparisons using or are tested last. For example, the following condition includes three comparisons:

$resCity == "Reno" or $resState == "NV" and $name == "Sally"

If the customer’s name is Sally and she lives in Nevada (NV), this statement is true. The statement is also true if she lives in Reno, regardless of what her name is. This condition is not true if she lives in NV but her name is not Sally. You get these results because the script checks the condition in the following order:

1. The and is compared.

The script checks $resState to see whether it equals NV and checks $name to see whether it equals Sally. If both match, the condition is true, and the script doesn't need to check or. If only one or neither of the variables equals the designated value, the testing continues.

2. The or is compared.

The script checks $resCity to see whether it equals Reno. If it does, the condition is true. If it doesn't, the condition is false.

You can change the order in which comparisons are made by using parentheses. The connecting word inside the parentheses is evaluated first. For example, you can rewrite the preceding statement with parentheses, as follows:

($resCity == "Reno or $resState == "NV") and $name == "Sally"

The parentheses change the order in which the conditions are checked. Now the or is checked first because it's inside the parentheses. This condition statement is true if the customer's name is Sally and she lives in either Reno or NV. You get these results because the script checks the condition as follows:

1. The or is compared.

The script checks to see whether $resCity equals Reno or $resState equals NV. If it doesn't, the entire condition is false, and testing stops. If it does, this part of the condition is true. However, the comparison on the other side of the and must also be true, so the testing continues.

2. The and is compared.

The script checks $name to see whether it equals Sally. If it does, the condition is true. If it doesn't, the condition is false.

tip.eps Use parentheses liberally, even when you believe you know the order of the comparisons. Unnecessary parentheses can’t hurt, but comparisons that have unexpected results can.

technicalstuff.eps If you're familiar with other languages, such as C, you might have used || (for or) and && (for and) in place of the words. The || and && work in PHP as well. The statement $a < $b && $c > $b is just as valid as the statement $a < $b and $c > $b. The || is checked before or, and the && is checked before and.

Using Conditional Statements

conditional statement executes a block of statements only when certain conditions are true. Here are two useful types of conditional statements:

check An if statement: Sets up a condition and tests it. If the condition is true, a block of statements is executed.

check A switch statement: Sets up a list of alternative conditions. It tests for the true condition and executes the appropriate block of statements.

We tell you how to use both of those conditional statements in the text that follows.

Using if statements

An if statement tests conditions, executing a block of statements when a condition is true. The following sections discuss how to build an if statement using the appropriate format, create an if statement for a false condition, and nest one if statement within another.

Building if statements

The general format of an if conditional statement is as follows:

if ( condition )

{

   block of statements

}

elseif  ( condition )

{

   block of statements

}

else

{

   block of statements

}

The if statement consists of three parts:

check if: This part is required. Only one if is allowed. It tests a condition:

• If the condition is true: The block of statements is executed. After the statements are executed, the script moves to the next instruction following the conditional statement; if the conditional statement contains any elseif or else sections, the script skips over them.

 If the condition is not true: The block of statements is not executed. The script skips to the next instruction, which can be an elseif, an else, or the next instruction after the if conditional statement.

check elseif: This part is optional. You can use more than one elseif if you want. An elseif also tests a condition:

• If the condition is true: The block of statements is executed. After executing the block of statements, the script goes to the next instruction following the conditional statement; if the if statement contains any additional elseif sections or an else section, the script skips over them.

 If the condition is not true: The block of statements is not executed. The script skips to the next instruction, which can be an elseif, an else, or the next instruction after the if conditional statement.

check else: This part is also optional. Only one else is allowed. This part doesn't test a condition, but rather, it executes the block of statements. The script enters the else section only when the if section and all the elseif sections are not true.

Here's an example of how to build an if statement. Pretend you're a teacher. The following if statement, when given a test score, sends your student a grade and a snappy little text message. It uses all three parts of the if statement (if, elseif, and else), as follows:

if ($score > 92 )

{

   $grade = "A";

   $message = "Excellent!";

}

elseif ($score <= 92 and $score > 83 )

{

   $grade = "B";

   $message = "Good!";

}

elseif ($score <= 83 and $score > 74 )

{

   $grade = "C";

   $message = "Okay";

}

elseif ($score <= 74 and $score > 62 )

{

   $grade = "D";

   $message = "Uh oh!";

}

else

{

  $grade = "F";

  $message = "Doom is upon you!";

}

echo $message."\n";

echo "Your grade is $grade\n";

The if conditional statement proceeds as follows:

1. The value in $score is compared to 92.

If $score is greater than 92, $grade is set to A, $message is set to Excellent!, and the script skips to the echo statement. If $score is 92 or less, $grade and $message are not set, and the script skips to the elseif section.

2. The value in $score is compared to 92 and to 83.

If $score is 92 or less and greater than 83, $grade and $message are set, and the script skips to the echo statement. If $score is 83 or less, $grade and $message are not set, and the script skips to the second elseif section.

3. The value in $score is compared to 83 and to 74.

If $score is 83 or less and greater than 74, $grade and $message are set, and the script skips to the echo statement. If $score is 74 or less, $grade and $message are not set, and the script skips to the next elseif section.

4. The value in $score is compared to 74 and to 62.

If $score is 74 or less and greater than 62, $grade and $message are set, and the script skips to the echo statement. If $score is 62 or less, $grade and $message are not set, and the script skips to the else section.

5. $grade is set to F, and $message is set to Doom is upon you!.

The script continues to the echo statement.

tip.eps When the block to be executed by any section of the if conditional statement contains only one statement, the curly braces are not needed. For example, say the preceding example had only one statement in the blocks, as follows:

if ($grade > 92 )

{

   $grade = "A";

}

You could write it as follows:

if ($grade > 92 )

   $grade = "A";

tip.eps This shortcut can save some typing. However, when you're using several if statements, you should include the curly braces because leaving them out can lead to confusion.

Negating if statements

You can write an if statement so that the statement block is executed when the condition is false by putting an exclamation point (!) at the beginning of the condition. For example, you can use the following if statement:

if (preg_match("/^S[a-z]*/",$string))

{

    $list[]=$string."\n";

}

This if statement creates an array of strings that begin with S. More specifically, if $string matches a pattern that specifies one uppercase S at the beginning, followed by a number of lowercase letters, the condition is true and the statement block is executed. However, if you were to place an exclamation point at the beginning of the condition, things would change considerably. For example, say you use the following statements instead:

if (!preg_match("/^S[a-z]*/",$string)

{

    $list[]=$string."\n";

}

In this case, the array $list contains all the strings except those that begin with S. Because ! appears at the beginning of the condition, the condition is "$string does not match a pattern that begins with S." So, when $string does not begin with S, the condition is true.

Nesting if statements

You can have an if conditional statement inside another if conditional statement. Putting one statement inside another is called nesting. For example, suppose you need to contact all your customers who live in Idaho. You plan to send e-mail to those who have e-mail addresses and send letters to those who don't have e-mail addresses. You can identify the groups of customers by using the following nested if statements:

if ( $custState == "ID" )

{

   if ( $EmailAdd = "" )

   {

     $contactMethod = "letter";

   }

   else

   {

     $contactMethod = "email";

   }

}

else

{

   $contactMethod = "none needed";

}

These statements first check to see whether the customer lives in Idaho. If the customer does live in Idaho, the script tests for an e-mail address. If the e-mail address is blank, the contact method is set to letter. If the e-mail address is not blank, the contact method is email. If the customer doesn't live in Idaho, the else section sets the contact method to indicate that the customer won't be contacted at all.

Using switch statements

For most situations, the if conditional statement works best. However, sometimes you have a list of conditions and want to execute different statements for each condition. For example, suppose your script computes sales tax. How do you handle the different state sales tax rates? Theswitch statement was designed for such situations.

The switch statement tests the value of one variable and executes the block of statements for the matching value of the variable. The general format is as follows:

switch ( $variablename )

{

  case value :

     block of statements;

     break;

  case value :

     block of statements;

     break;

  ...

  default:

     block of statements;

     break;

}

The switch statement tests the value of $variablename. The script then skips to the case section for that value and executes statements until it reaches a break statement or the end of the switch statement. If there is no case section for the value of $variablename, the script executes thedefault section. You can use as many case sections as you need. The default section is optional. If you use a default section, it's customary to put the default section at the end, but as far as PHP is concerned, it can go anywhere.

The following statements set the sales tax rate for different states:

switch ( $custState )

{

  case "OR" :

     $salestaxrate = 0;

     break;

  case "CA" :

     $salestaxrate = 1.0;

     break;

  default:

     $salestaxrate = .5;

     break;

}

$salestax = $orderTotalCost * $salestaxrate;

In this case, the tax rate for Oregon is 0, the tax rate for California is 100 percent, and the tax rate for all the other states is 50 percent. The switch statement looks at the value of $custState and skips to the section that matches the value. For example, if $custState is TX, the script executes the default section and sets $salestaxrate to .5. After the switch statement, the script computes $salestax at .5 times the cost of the order.

The break statements are essential to end the case section. If a case section does not include a break statement, the script does not stop executing statements at the end of the case section. The script continues executing statements past the end of the case section, on to the next case section, and continues until it reaches a break statement or the end of the switch statement. This is a problem for every case section except the last one because it will execute sections following the appropriate section.

tip.eps In some rare instances, you may want two case sections to execute when the switch variables match the value of the first case section, so you can leave out the break statement in the first case section. This is not a common situation, but it can occasionally solve a problem.

remember.eps The last case section in a switch statement doesn't actually require a break statement. You can leave it out. However, it's a good idea to include it for clarity and consistency.

Repeating Actions with Loops

Loops are used frequently in scripts to set up a block of statements that repeat. The loop can repeat a specified number of times. For example, a loop that echoes all the state capitals in the United States needs to repeat 50 times. Or the loop can repeat until a certain condition is met. For example, a loop that echoes the names of all the files in a directory needs to repeat until it runs out of files, regardless of how many files there are.

Here are three types of loops:

check A for loop: Sets up a counter; repeats a block of statements until the counter reaches a specified number.

check A while loop: Sets up a condition; checks the condition, and if it's true, repeats a block of statements until the condition becomes false.

check A do..while loop: Sets up a condition; executes a block of statements; checks the condition, and if it's true, repeats the block of statements until the condition becomes false.

We describe each of these loops in detail in the following few sections.

Using for loops

The most basic for loops are based on a counter. You set the beginning value for the counter, set the ending value, and set how the counter is incremented each time the statement block is executed. We tell you how to build that basic loop, and then how to nest one loop inside another and also build more sophisticated loops.

Building for loops

The general format of a basic for loop is as follows:

for (startingvalue;endingcondition;increment)

{

    block of statements;

}

Within the for statement, you need to fill in the following values:

check startingvalue: The startingvalue is a statement that sets up a variable to be your counter and sets it to your starting value. For example, the statement $i=1; sets $i as the counter variable and sets it equal to 1. Frequently, the counter variable is started at 0 or 1. The starting value can be a number, a combination of numbers (such as 2 + 2), or a variable.

check endingcondition: The endingcondition is a statement that sets your ending value. As long as this statement is true, the block of statements keeps repeating. When this statement is not true, the loop ends. For example, the statement $i<10; sets the ending value for the loop to 10. When$i is equal to 10, the statement is no longer true (because $i is no longer less than 10), and the loop stops repeating. The statement can include variables, such as $i<$size;.

check increment: This statement increments your counter. For example, the statement $i++; adds 1 to your counter at the end of each block of statements. You can use other increment statements, such as $i=+1; or $i--;.

A basic for loop sets up a variable, like $i, that is used as a counter. This variable has a value that changes during each loop. The variable $i can be used in the block of statements that is repeating. For example, the following simple loop displays Hello World! three times:

for ($i=1;$i<=3;$i++)

{

  echo "$i. Hello World!<br />";

}

The following is the output from these statements:

1. Hello World!

2. Hello World!

3. Hello World!

Nesting for loops

You can nest for loops inside for loops. Suppose you want to print the multiplication tables from 1 to 9. You can use the following statements:

for($i=1;$i<=9;$i++)

{

   echo "\nMultiply by $i \n";

   for($j=1;$j<=9;$j++)

   {

       $result = $i * $j;

       echo "$i x $j = $result\n";

   }

}

The output is as follows:

Multiply by 1

1 x 1 = 1

1 x 2 = 2

...

1 x 8 = 8

1 x 9 = 9

Multiply by 2

2 x 1 = 2

2 x 2 = 4

...

2 x 8 = 16

2 x 9 = 18

Multiply by 3

3 x 1 = 3

And so on.

Designing advanced for loops

The structure of a for loop is quite flexible and allows you to build loops for almost any purpose. Although the basic for loop discussed so far in this section has one statement in its starting, conditional, and increment sections, the general format allows more than one statement in each section. The general format is:

for (beginning statementsconditional statements;

     ending statements)

{

     block of statements;

}

The statements within a for loop have the following roles:

check The beginning statements execute once at the start of the loop. They can be statements that set any needed starting values or other statements that you want to execute before your loop starts running.

check The conditional statements are tested for each iteration of your loop.

check The ending statements execute once at the end of the loop. They can be statements that increment your values or any other statements that you want to execute at the end of your loop.

Each statement section is separated by a semicolon (;). Each section can contain as many statements as needed, separated by commas. Any section can be empty.

The following loop has statements in all three sections:

$t = 0;

for ($i=0,$j=1;$t<=4;$i++,$j++)

{

  $t = $i + $j;

  echo "$t<br />";

}

In this example, $i=0 and $j=1 are the beginning statements, $t<=4 is the conditional statement, and $i++ and $j++ are the ending statements.

The output of these statements is as follows:

1

3

5

The loop is executed in the following order:

1. The beginning section containing two statements is executed.

$i is set to 0, and $j is set to 1.

2. The conditional section containing one statement is evaluated.

Is $t less than or equal to 4? Yes, so the statement is true. The loop continues to execute.

3. The statements in the statement block are executed.

$t becomes equal to $i plus $j, which is 0 + 1, which equals 1. Then $t is echoed to give the output 1.

4. The ending section containing two statements ($i++ and $j++) is executed.

Both $i and $j are incremented by 1, so $i now equals 1, and $j now equals 2.

5. The conditional section is evaluated.

Is $t less than or equal to 4? Because $t is equal to 1 at this point, the statement is true. The loop continues to execute.

6. The statements in the statement block are executed.

$t becomes equal to $i plus $j, which is 1 + 2, which equals 3. Then $t is echoed to give the output 3.

7. The ending section containing two statements ($i++ and $j++) is executed.

Both $i and $j are incremented by 1, so $i now equals 2, and $j now equals 3.

8. The conditional section is evaluated.

Is $t less than or equal to 4? Because $t now equals 3, the statement is true. The loop continues to execute.

9. The statements in the statement block are executed.

$t becomes equal to $i plus $j, which is 2 + 3, which equals 5. Then $t is echoed to give the output 5.

10. The ending section containing two statements ($i++ and $j++) is executed.

Both $i and $j are incremented by 1, so $i now equals 2, and $j now equals 3.

11. The conditional section is evaluated.

Is $t less than or equal to 4? Because $t now equals 5, the statement is not true. The loop doesn't continue to execute. The loop ends, and the script continues to the next statement after the end of the loop.

Using while loops

A while loop continues repeating as long as certain conditions are true. The loop works as follows:

1. You set up a condition.

2. The condition is tested at the top of each loop.

3. If the condition is true, the loop repeats. If the condition is not true, the loop stops.

The following is the general format of a while loop:

while ( condition )

{

   block of statements

}

The following statements set up a while loop that looks through an array for an apple:

$fruit = array ( "orange", "apple", "grape" );

$testvar = "no";

$k = 0;

while ( $testvar != "yes" )

{

  if ($fruit[$k] == "apple" )

  {

    $testvar = "yes";

    echo "apple\n";

  }

  else

  {

    echo "$fruit[$k] is not an apple\n";

  }

  $k++;

}

These statements generate the following output:

orange is not an apple

apple

The script executes the statements as follows:

1. The variables are set before starting the loop.

$fruit is an array with three values, $testvar is a test variable set to "no", and $k is a counter variable set to 0.

2. The loop starts by testing whether $testvar != "yes" is true.

Because $testvar was set to "no", the statement is true, so the loop continues.

3. The condition in the if statement is tested.

Is $fruit[$k] == "apple" true? At this point, $k is 0, so the script checks $fruit[0]. Because $fruit[0] is "orange", the statement is not true. The statements in the if block aren't executed, so the script skips to the else statement.

4. The statement in the else block is executed.

The else block outputs the line "orange is not an apple". This is the first line of the output.

5. $k is incremented by one.

Now $k becomes equal to 1.

6. The bottom of the loop is reached.

Flow returns to the top of the while loop.

7. The condition $testvar != "yes" is tested again.

Is $testvar != "yes" true? Because $testvar hasn't been changed and is still set to "no", it is true, so the loop continues.

8. The condition in the if statement is tested again.

Is $fruit[$k] == "apple" true? At this point, $k is 1, so the script checks $fruit[1]. Because $fruit[1] is "apple", the statement is true. So the loop enters the if block.

9. The statements in the if block are executed.

These statements set $testvar to "yes" and output "apple". This is the second line of the output.

10. $k is incremented again.

Now $k equals 2.

11. The bottom of the loop is reached again.

Once again, the flow returns to the top of the while loop.

12. The condition $testvar != "yes" is tested one last time.

Is $testvar != "yes" true? Because $testvar has been changed and is now set to "yes", it is not true. The loop stops.

remember.eps It's possible to write a while loop that is infinite — that is, a loop that loops forever. You can easily, without intending to, write a loop in which the condition is always true. If the condition never becomes false, the loop never ends. For a discussion of infinite loops, see the section Avoiding infinite loops, later in this chapter.

Using do..while loops

A do..while loop is very similar to a while loop. Like a while loop, a do..while loop continues repeating as long as certain conditions are true. Unlike while loops, however, those conditions are tested at the bottom of each loop. If the condition is true, the loop repeats. When the condition is not true, the loop stops.

The general format for a do..while loop is as follows:

do

{

   block of statements

} while ( condition );

The following statements set up a loop that looks for an apple. This script does the same thing as the script in the preceding section that uses a while loop:

$fruit = array ( "orange", "apple", "grape" );

$testvar = "no";

$k = 0;

do

{

  if ($fruit[$k] == "apple" )

  {

    $testvar = "yes";

    echo "apple\n";

  }

  else

  {

    echo "$fruit[$k] is not an apple\n";

  }

  $k++;

} while ( $testvar != "yes" );

The output of these statements in a browser is as follows:

orange is not an apple

apple

This is the same output shown for the while loop example. The difference between a while loop and a do..while loop is where the condition is checked. In a while loop, the condition is checked at the top of the loop. Therefore, the loop will never execute if the condition is never true. In the do..while loop, the condition is checked at the bottom of the loop. Therefore, the loop always executes at least once, even if the condition is never true.

For example, in the preceding loop that checks for an apple, suppose the original condition is set to yes, instead of no, by using this statement:

$testvar = "yes";

The condition tests false from the beginning. It is never true. In a while loop, there is no output. The statement block never runs. However, in a do..while loop, the statement block runs once before the condition is tested. Thus, the while loop produces no output, but the do..while loop produces the following output:

orange is not an apple

The do..while loop produces one line of output before the condition is tested. It doesn't produce the second line of output because the condition tests false.

Avoiding infinite loops

You can easily set up loops so that they never stop. These are called infinite loops. They repeat forever. However, seldom does anyone create an infinite loop intentionally. It's usually a mistake in the programming. For example, a slight change to the script that sets up a while loop can make it into an infinite loop.

Here is the script shown in the section Using while loops, earlier in this chapter, with a slight change:

$fruit = array ( "orange", "apple", "grape" );

$testvar = "no";

while ( $testvar != "yes" )

{

  $k = 0;

  if ($fruit[$k] == "apple" )

  {

    $testvar = "yes";

    echo "apple\n";

  }

  else

  {

    echo "$fruit[$k] is not an apple\n";

  }

  $k++;

}

The small change is moving the statement $k = 0; from outside the loop to inside the loop. This small change makes it into an endless loop. This changed script has the following output:

orange is not an apple

orange is not an apple

orange is not an apple

orange is not an apple

...

This will repeat forever. Every time the loop runs, it resets $k to 0. Then it gets $fruit[0] and echoes it. At the end of the loop, $k is incremented to 1. However, when the loop starts again, $k is set back to 0. Consequently, only the first value in the array, orange, is ever read. The loop never gets to the apple, and $testvar is never set to "yes". The loop is endless.

Don’t be embarrassed if you write an infinite loop. We guarantee that the best programming guru in the world has written many infinite loops. It isn’t a big deal. If you’re testing a script and get output repeating endlessly, there’s no need to panic. Do one of the following:

check If you’re using PHP on a web page: Wait. It will stop by itself in a short time. The default time is 30 seconds, but the timeout period might have been changed by the PHP administrator. You can also click the Stop button on your browser to stop the display in your browser.

check If you’re using PHP CLI: Press Ctrl+C (or Cmd+C on a Mac). This stops the script from running. Sometimes the output will continue to display a little longer, but it will stop very shortly.

Then figure out why the loop is repeating endlessly and fix it.

tip.eps A common mistake that can result in an infinite loop is using a single equal sign (=) when you mean to use double equal signs (==). The single equal sign stores a value in a variable; the double equal signs test whether two values are equal. The following condition using a single equal sign is always true:

while ($testvar = "yes")

The condition simply sets $testvar equal to "yes". This isn't a question that can be false. What you probably meant to write is this:

while ($testvar == "yes")

This is a question asking whether $testvar is equal to "yes", which can be answered either true or false.

Another common mistake is to leave out the statement that increments the counter. For example, in the script earlier in this section, if you leave out the statement $k++;, $k is always 0, and the result is an infinite loop.

Breaking out of a loop

Sometimes you want your script to break out of a loop. PHP provides two statements for this purpose:

check break: Breaks completely out of a loop and continue with the script statements after the loop.

check continue: Skips to the end of the loop where the condition is tested. If the condition tests positive, the script continues from the top of the loop.

The break and continue statements are usually used in conditional statements. In particular, break is used most often in switch statements, discussed earlier in this chapter.

The following statements show the difference between continue and break. This first chunk of code shows an example of the break statement:

$counter = 0;

while ( $counter < 5 )

{

  $counter++;

  If ( $counter == 3 )

  {

      echo "break\n";

      break;

  }

  echo "Last line in loop: counter=$counter\n";

}

echo "First line after loop\n\n";

The output of this statement is the following:

Last line in loop: counter=1

Last line in loop: counter=2

break

First line after loop

Notice that the first loop ends at the break statement. It stops looping and jumps immediately to the statement after the loop. That isn't true of the continue statement.

The following code gives you an example of the continue statement:

$counter = 0;

while ( $counter < 5 )

{

  $counter++;

  If ( $counter == 3 )

  {

      echo "continue\n";

      continue;

  }

  echo "Last line in loop: counter=$counter\n";

}

echo "First line after loop\n";

The output of this statement is the following:

Last line in loop: counter=1

Last line in loop: counter=2

continue

Last line in loop: counter=4

Last line in loop: counter=5

First line after loop

Unlike the break statement loop, this loop does not end at the continue statement. It just stops the third repeat of the loop and jumps back up to the top of the loop. It then finishes the loop, with the fourth and fifth repeats, before it goes to the statement after the loop.

One use for break statements is insurance against infinite loops. The following statements inside a loop can stop it at a reasonable point:

$test4infinity++;

if ($test4infinity > 100 )

{

   break;

}

tip.eps If you’re sure that your loop should never repeat more than 100 times, use these statements to stop the loop if it becomes endless. Use whatever number seems reasonable for the loop you’re building.

Using Functions

Applications often perform the same task at different points in the script or in different scripts. Functions are designed to allow you to reuse the same code in different locations. A function is a group of PHP statements that perform a specific task. You can use the function wherever you need to perform the task.

For example, suppose you display your company logo frequently throughout your website with the following statements:

echo "<p><img src='Images/logo.jpg' width='50' height='50' hspace='10' align='left' /></p>";

echo "<p style='font-size: x-large'>My Fine Company</p>";

echo "<p style='font-style: italic'>quality products</p>";

Rather than typing this code in every place in your scripts where you want to display your logo, you can create a function that contains the statements and name it display_logo. Then, you can just use the function whenever you want to display your logo. Using the function looks like this:

display_logo();

You can see that using this one line saves a lot of typing and is easier to read and understand than typing the echo statements everywhere the logo is needed. In the sections that follow, we tell you how to create and call a function, use variables within functions, pass and return values to and from functions, and simplify your work with PHP's built-in functions.

Creating a function

You can create a function by putting the code into a function block. The general format is as follows:

function functionname()

{

   block of statements;

   return;

}

For example, you can create the function display_logo() that we discuss in the preceding section with the following statements:

function display_logo()

{

   echo "<p><img src='Images/logo.jpg' width='50' height='50'

       hspace='10' align='left' /></p>";

   echo "<p style='font-size: x-large'>My Fine Company</p>";

   echo "<p style='font-style: italic'>quality products</p>";

   return;

}

You can then call the function anywhere you want to display the logo, as follows:

display_logo();

The return statement at the end of the preceding function stops the function and returns control to the main script. A return statement isn't needed at the end of the function, because the function stops at the end anyway and returns control to the calling script. However, the returnstatement makes the function easier to understand. The return statement is discussed in more detail in the section Returning a value from a function, later in this chapter.

You can create a function with a function-definition statement anywhere in the script, but the usual practice is to put all the functions together at the beginning or the end of the script. Functions that you plan to use in more than one script can be defined in a separate file that you include in any scripts that need to use the functions. Including files in scripts is discussed in the section, Organizing Scripts, later in this chapter.

Using variables in functions

You can create and use a variable inside your function. Such a variable is called local to the function. However, the variable isn't available outside of the function; it isn't available to the main script. If you want to use the variable outside the function, you have to make the variable global,rather than local, by using a global statement. For instance, the variable $name is created in the following function:

function format_name()

{

   $first_name = "John";

   $last_name = "Smith";

   $name = $last_name, ".$first_name;

}

format_name();

echo "$name";

These statements don't produce any output. In the echo statement, $name doesn't contain any value. The variable $name was created inside the function, so it doesn't exist outside the function.

You can create a variable inside a function that does exist outside the function by using the global statement. The following statements contain the same function with a global statement added:

function format_name()

{

   global $name;

   $first_name = "John";

   $last_name = "Smith";

   $name = $last_name . ", " . $first_name;

}

format_name();

echo "$name";

The script now echoes this:

Smith, John

warning_bomb.eps You must make the variable global before you can use it. If the global statement follows the $name assignment statement, the script doesn't produce any output. That is, in the preceding function, if the global statement followed the $name = statement, the function wouldn't work correctly.

Similarly, if a variable is created outside the function, you can't use it inside the function unless it's global. In the following statements, the only global statement is inside the function:

$first_name = "John";

$last_name = "Smith";

function format_name()

{

   global $first_name, $last_name;

   $name = $last_name.", ".$first_name;

   echo "$name";

}

format_name();

Because the code didn't include a global statement outside the function, $last_name and $first_name inside the function are different variables than $last_name and $first_name created in the script outside the function. The variables $last_name and $first_name inside the function are created when you name them and have no values. Therefore, $name echoes only a comma, as follows:

,

You need the global statement for the function to work correctly.

Passing values to a function

You pass values to a function by putting the values between the parentheses when you call the function, as follows:

functionname(value,value,...);

Of course, the variables can’t just show up. The function must be expecting them. The function statement includes variables’ names for the values it’s expecting, as follows:

function functionname($varname1,$varname2,...)

{

   statements

   return;

}

For example, the following function computes the sales tax:

function compute_salestax($amount,$custState)

{

  switch ( $custState )

  {

    case "OR" :

      $salestaxrate = 0;

      break;

    case "CA" :

      $salestaxrate = 1.0;

      break;

    default:

      $salestaxrate = .5;

      break;

  }

  $salestax = $amount * $salestaxrate;

  echo "$salestax<br />";

}

The first line shows that the function expects two values — $amount and $custState. When you call the function, you pass it two values, as follows:

$amount = 2000.00;

$custState = "CA";

compute_salestax($amount,$custState);

In this case, the amount passed in is 2000.00 and the state is CA. The output is 2000, because the salestaxrate for CA is 1.0.

Passing the right type of values

You can pass values directly, including computed values, or you can pass variables containing values. The following calls are valid:

compute_salestax(2000,"CA");

compute_salestax(2*1000,"");

compute_salestax(2000,"C"."A");

You can pass values of any data type. See Chapter 1 in this minibook for a discussion of data types. Generally, you want to test the values that are passed to check whether the values are the expected data type. For example, the following function expects an array:

function add_numbers($numbers)

{

   if(is_array($numbers))

   {

      for($i=0;$i <sizeof($numbers);$i++)

      {

         @$sum = $sum + $numbers[$i];

      }

      echo $sum;

   }

   else

   {

      echo "value passed is not an array";

      return;

   }

}

You can use the following statements to call the add_numbers function:

$arrayofnumbers = array(100,200);

add_numbers($arrayofnumbers);

The function displays 300, which is the sum of 100 plus 200. If the value passed isn’t an array, as follows:

add_numbers(100);

the function displays the message:

value passed is not an array

Passing values in the correct order

The function receives the values in the order they are passed. That is, suppose you have the following function:

function functionx($x,$y,$z)

{

   do stuff

}

You call the function, as follows:

functionx($var1,$var2,$var3);

functionx sets $x=$var1, $y=$var2, and $z=$var3.

If the values you pass aren’t in the expected order, the function uses the wrong value when performing the task. For instance, perhaps your definition for a function to compute sales tax looks like the following:

function compute_salestax($orderCost,$custState)

{

   compute tax

}

Here, $orderCost is the cost of the order, and $custState is the state the customer resides in. But suppose you use the following call:

compute_salestax($custState,$orderCost);

The function uses the value of the $custState variable as the cost of the order, which it sets to 0, because it is a string. It sets the $custState variable to the number in $orderCost, which wouldn't match any of its categories. The output would be 0.

Passing the right number of values

A function is designed to expect a certain number of values to be passed to it. If you don't send enough values, the function sets the missing one(s) to NULL. If you have your warning message level turned on, a warning message is displayed. (See the section about understanding error messages in Chapter 1 in this minibook for a description of error levels.) For example, suppose you have the following function that formats a name:

function format_name($first_name,$last_name)

{

   $name = "$last_name, ".$first_name;

   echo $name;

}

The function expects two values to be passed to it. Suppose you call it with the following statement:

format_name("John");

You see a message similar to the following:

Warning: Missing argument 2 for format_name() in testing.php on line 9

However, warnings don’t stop the script; it continues to run. So, the script outputs the following:

, John

If you send too many values, the function ignores the extra values. In most cases, you don’t want to pass the wrong number of values, although this can be useful in a few rare instances.

You can set default values to be used when a value isn’t passed. The defaults are set when you write the function, as follows:

function add_2_numbers($num1=1,$num2=1)

{

   $total = $num1 + $num2;

   echo "total = $total";

}

If one or both of the values aren’t passed to the function, the function uses the assigned defaults, but if a value is passed, it is used instead of the default. For instance, you might use one of the following calls:

add_2_numbers(2,2);

add_2_numbers(2);

add_2_numbers();

The results are, in consecutive order:

$total = 4

$total = 3

$total = 2

Passing values by reference

When you pass values into variables in the function definition as shown so far, you’re passing by value. Passing by value is the most common way to pass values to a function, as follows:

function add_1($num1)

{

     $num1 = $num1 + 1;

}

When passing by value, copies are made of $num1 and are passed to the function. While $num1 is changed inside the function, by adding 1 to it, the variable $num1 outside of the function is not changed. So, if you call the function with the following statements:

$num1 = 3;

add_1($num1);

echo $num1;

The output is

3

$num1 still contains the same value as it did before you called the function. You can change this by making the variable global inside the function or by returning $num1 from the function after it's changed and calling the function, as follows:

$num1 = add_1($num1);

The new value of $num1 is returned from the function and stored in $num1 outside the function.

In some cases, you want to change the values of variables directly, changing their values outside the function. Passing by reference is used for this task. To pass a variable by reference, add & before the variable name, as follows:

function add_1(&$num1)

{

     $num1 = $num1 + 1;

}

When you call this function, a pointer to the location of the variable is passed, rather than a copy of the variable. That is, the function call passes a pointer to the container called $num where the value 3 is stored. When you change the variable with statements inside the function, the value at the original location is changed. So, if you call the function with the following statements:

$num1 = 3;

add_1($num1);

echo $num1;

the output is

4

Because you’re passing a pointer to a variable, the following doesn’t make sense:

add_1(&7);

Passing by reference is used mainly when passing really large values, such as an object or a large array. It’s more efficient to pass a pointer than to pass a copy of really large values.

Returning a value from a function

If you want a function to send a value back to the main script, use the return statement. The main script can put the value in a variable or use it in any manner it would use any value.

To return a value from the function, put the return statement in the function. The general format is

return value;

For instance, the function that adds two numbers might look like this:

function add_2_numbers($num1,$num2)

{

   $total = $num1 + $num2;

   return $total;

}

The total of the two numbers is returned. You call the function, as follows:

$sum = add_2_numbers(5,6);

$sum then equals the value in $total that was returned from the function — 11. In fact, you could use a shortcut and send the total back to the main script with one statement:

return $num1 + $num2;

The main script can use the value in any of the usual ways. The following statements use the function call in valid ways:

$total_height = add_2_numbers($height1,$height2);

$totalSize = $current_size + add_2_numbers($size1,$size2);

if (add_2_numbers($costSocks,$costShoes) > 200.00 )

        $echo "No sale";

A return statement can return only one value. However, the value returned can be an array, so you can actually return many values from a function.

You can use a return statement in a conditional statement to end a function, as follows:

function find_value($array,$value)

{

  for($i=1;$i<sizeof($array);$i++)

  {

     if($array[$i] = $value)

     {

       echo "$i. $array[$i]<br />";

       return;

     }

  }

}

The function checks an array to see whether it contains a value. For instance, you can call the function with the following statements:

$names = array("Joe","Sam","Juan");

find_value($names,"Sam");

The function searches through the values in the array searching for Sam. If it finds Sam, it stops searching. The output shows the array item where Sam is found, as follows:

1. Sam

Often functions are designed to return Boolean values (true or false), as in the following function:

function is_over_100($number)

{

  if($number > 100)

  {

     return true;

  }

  else

  {

     return false;

  }

}

Numbers equal to or less than 100 return false; numbers over 100 return true. Another common function design returns a value if the function succeeds but returns false if the function does not succeed. For instance, you can design the find_value function as follows:

function find_value($array,$value)

{

  for($i=1;$i<sizeof($array);$i++)

  {

     if($array[$i] == $value)

     {

       return i$;

     }

  }

  return false;

}

If the function finds the value in the array, it returns the number of the array element where it found $value. However, if it doesn't find the value anywhere in the array, it returns false.

Using built-in functions

PHP’s many built-in functions are one reason why PHP is so powerful and useful. The functions included with PHP are normal functions. They’re no different than functions you create yourself. It’s just that PHP has already done all the work for you.

You can call PHP’s built-in functions the same way you call functions you create yourself. You use the function name and pass any values the function needs. We discuss specific PHP functions throughout the book. For instance, earlier in this chapter, we discuss several functions that you can use to check whether a variable exists or whether it’s empty. Here are a couple of those functions:

isset($varname)

empty($varname)

The PHP online documentation describes all the built-in functions at www.php.net/manual/en/funcref.php. In addition, the PHP documentation provides a search function that's very useful when you remember the name of the function but can't remember the exact syntax. Type the function name in the Search For text box at the top of the web page and choose Function List from the drop-down list.

Organizing Scripts

script is a series of PHP statements, and each statement performs an action. PHP starts at the beginning of the script and executes each statement in turn. Some statements are complex statements that execute simple statements conditionally or repeatedly.

An application often consists of more than one PHP script. In general, one script performs one major task. For instance, an application might include a script to display a form and a script that stores the data in a database. However, this is a guideline, rather than a rule. Some scripts both display a form and process the form data.

Each script should be organized into sections for each specific task. Start each section with a comment describing what the section does. (We cover writing comments in Book II, Chapter 1.) Separate sections from each other with blank lines. For instance, a login script might have sections as follows:

#display the login form

  statements that display the login form

#check for valid user name and password

  statements that check for valid user name and password

#display first page of website or error message

  statements that display the site if user had valid login

  or error message if login invalid

remember.eps The goal is to make the script as clear and understandable as possible. Scripts need to be maintained and updated over a period of time, often not by the person who created them. The more clear and understandable they are, the easier to maintain and update they are.

The following sections give you some tips and tricks for organizing your PHP scripts in a way that simplifies your programming tasks.

Separating display code from logic code

One principle of good practice for writing an application is to separate the PHP programming logic from the HTML that displays the web page. To do this, the HTML that displays the page is put in a separate file. This file can then be used in the script wherever the web page needs to be displayed. You can store the HTML code that displays a form in a separate file and then use that code whenever the form needs to be displayed. Not only does it make your PHP script easier to read, but it also makes changing the form simpler. You can make the changes just in the file that contains the HTML code rather than having to find everywhere the application displays the form and make the changes at every location.

For example, suppose your customer adds an item to a shopping cart. On the shopping cart web page, you include two buttons — one that says Continue Shopping and one that says Log Out. When the user clicks either button, the following PHP script is executed:

<?php

if($button == "Continue Shopping")

{

   include("catalog.inc");

}

else

{

   include("logout.inc");

}

?>

If the user clicks Continue Shopping, a file containing HTML code that displays the catalog is used. If the users clicks the Log Out button, a file that contains the HTML code for the log-out message is used. We discuss the details of using include files later in this chapter in theOrganizing with include files section.

You can see how much easier the script is to read with only the include statement in the script, rather than with all the HTML code needed to display the page cluttering up the script.

Reusing code

Another practice that makes scripts easy to maintain is reusing code. It’s common to find yourself typing the same ten lines of PHP statements in several places in the script. You can store that block of code and reuse it wherever it’s needed.

Storing reusable code separately makes the script easier to read and understand. In addition, when the code needs changing, you just change it in one place, rather than changing it in a dozen different places in the script.

You can reuse code by storing the code in a function and calling the function wherever you need to perform the task. Creating and using functions is discussed earlier in this chapter, in the Using Functions section.

Another way you can reuse code is to store the code in a separate file and incorporate the file into the script where it is needed. You can bring an external file into a script with an include statement, discussed later in this chapter in the Organizing with include files section.

Organizing with functions

Make frequent use of functions to organize your scripts. Functions are useful when your script needs to perform the same task at repeated locations in a script, in different scripts in the application, and even in different applications. After you write a function that does the task and you know it works, you can use it anywhere that you need it.

Look for opportunities to use functions. Your script is much easier to read and understand with a line like this:

getCustomerName();

than with 20 lines of statements that actually get the customer name. In fact, after you've been writing PHP scripts for a while, you'll have a stash of functions that you've written for various scripts. Very often the script that you're writing can use a function that you wrote for another application two jobs ago. For instance, you may often have a need for a list of the states. Rather than include a list of all 50 states in the United States every time you need it, you could create a function called getStateNames() that returns an array that holds the 50 state names in alphabetical order and a function called getStateCodes() that returns an array with all 50 two-letter state abbreviation codes in the same order.

tip.eps Always use descriptive function names. The function calls in your script should tell you exactly what the functions do. Long names are okay. You don’t want to see a line in your script that reads

function1();

Even a line like the following is less informative than it could be:

getData();

You want to see a line like this:

getAllCustomerNames();

Organizing with include files

include statements bring the content of a file into your script. Thus, you can put statements into an external file — a file separate from your script file — and insert the file wherever you want in the script with the include statement. include statements are useful for storing statements that are repeated. Here are some ways to use include files to organize your scripts:

check Put all or most of your HTML into include files. For instance, if your script sends a form to the browser, put the HTML for the form into an external file. When you need to send the form, use an include statement. Putting the HTML into an include file is a good idea if the form is shown several times. It's even a good idea if the form is shown only once because it makes your script much easier to read.

check Put your functions in include files. You don't need the statements for functions in the script; you can put them in an include file. If you have a lot of functions, organize related functions into several include files, such as data_functions.inc and form_functions.inc. Use includestatements at the top of your scripts, reading in only the functions that are used in the script.

check Store statements that all the files on your website have in common. Most websites have many web pages with many elements in common. For instance, all web pages start with <html>, <head>, and <body> tags. If you store the common statements in an include file, you can include them in every web page, ensuring that all your pages look alike. For instance, you might have the following statements in an include file:

<html>

<head><title><?php echo $title ?></title></head>

<body topmargin="0">

<p style="text-align: center">

    <img src="logo.gif" width="100" height="200">

<hr color="red" />

If you include this file at the top of every script on your website, you save a lot of typing, and you know that all your pages match. In addition, if you want to change anything about the look of all your pages, you have to change it only in one place — in the include file.

Including files

You use an include statement to bring the content of an external text file into your script. The format for an include statement is

include("filename");

The file can have any name. We, your humble book authors, like to use the extension .inc so that we know the file is an include file as soon as we see the name. It helps with the organization and clarity of a website.

PHP provides four types of include statements:

check include: Includes and evaluates the specified file. It displays a warning if it can't find the specified file.

check require: Performs the same was as the include statement, except that it produces, in addition to a warning, a fatal error when it can't find the specified file, stopping the script at that point.

check include_once: Performs the same as the include statement, except it includes the file only once. If the file has already been included, it won't be included again. In some scripts, a file might be included more than once, causing function redefinitions, variable reassignments, and other possible problems.

check require_once: Performs the same as the require statement, except it includes the file only once. If the file has already been included, it won't be included again. This statement prevents problems that might occur when a file is included more than once.

The external file is included in your script at the location of the include statement. The content of the file is read as HTML code, not PHP. Therefore, if you want to use PHP statements in your include file, you must include PHP tags in the include file.

warning_bomb.eps Forgetting the PHP tags in the include file is a common mistake. It's also a security problem because without the PHP tags, the code in the include file is displayed to the user as HTML. You don't want your database password displayed on your web page. We discuss includefile security later in this chapter in the section Storing include files securely.

Using variables in include statements

You can use a variable name for the filename, as follows:

include("$filename");

For example, you might want to display different messages on different days. You might store these messages in files that are named for the day on which the message should appear. For instance, you can have a file named Sun.inc with the following content:

<p>Go ahead. Sleep in. No work today.</p>

and similar files for all days of the week. The following statements can be used to display the correct message for the current day:

$today  = date("D");

include("$today".".inc");

After the first statement, $today contains the day of the week, in abbreviation form. The date statement is discussed in Chapter 1 in this minibook. The second statement includes the correct file, using the day stored in $today. If $today contains Sun, the statement includes a file calledSun.inc.

Storing include files securely

Where you store include files can be a security issue for websites. Files stored on websites can be downloaded by any user, unless protected. Theoretically, a user can connect to your website by using the following URL:

http://example.com/secretpasswords.inc

If the web server is configured to process PHP sections only in files with the .php extension and secretpasswords.inc contains the following statements:

<?php

  $mysecretaccount="account48756";

  $mypassword="secret";

?>

the web server would obligingly display the contents of secretpasswords.inc to the user. You can protect against this in one of the following ways:

check Name include files with .php extensions. This needs to be done carefully because it allows some PHP code to be run independently, without any context. For instance, suppose you have code in your include file that deleted a record in the database (highly unlikely). Running the code outside of a script might have negative consequences. Also, you might find it convenient to name files with a .inc extension, so you can see at a glance that it's a fragment, not a script intended to run by itself.

check Configure the web server to scan for PHP sections in files with the .inc extension, as well as the .php extension. This allows you to recognize include files by their names, but it still has the problem of possible unintended consequences of running the file independently, as discussed earlier.

check Store the file in a location that isn’t accessible to outside users. This is the preferred solution, but it may not be possible in some environments, such as when using a web hosting company.

The best place to store include files is a directory where outside users cannot access them. For instance, for your website, set up an include directory that is outside your web space: that is, a directory in a location that outside users can't access using their browsers. For instance, the default web space for Apache, unless it has been changed in the configuration file (usually httpd.conf), is htdocs in the directory where Apache is installed. If you store your include files in a directory that isn't in your web space, such as d:\include, you protect the files from outside users.

To include a file from a hidden directory (such as a directory outside your web space), you can use the full pathname to the file, as follows:

include("d:/hidden/secretpasswords.inc");

However, PHP allows you to set an include directory. You can include files from the include directory using only the filename.

Setting up include directories

PHP looks for include files in the current directory, where your web page file is stored, and in one or more directories specified by a setting in your php.ini file. You can include files from the include directory without specifying the path to the file.

You can see the current include directory location by using the phpinfo() statement. In the output, in the PHP core section, you can find a setting for include_path that shows where your current include directory is located. For example, in PHP 5, the default location might bec:\php5\pear.

You can change the setting for your include directory in the php.ini file. Find the setting for include_path and change it to the path to your preferred directory, as follows:

include_path=".;c:\php\include";       # for Windows

include_path=".:/user/local/include";  # for Unix/Linux

Both of the statements specify two directories where PHP looks for include files. The first directory is dot (meaning the current directory), followed by the second directory, path. You can specify as many include directories as you want and PHP will search them, in the order in which they are listed, to find the include file. The directory paths are separated by a semicolon for Windows or a colon for Unix and Linux.

If you can't set the path yourself in php.ini, you can set the path in each individual script by using the following statement:

ini_set("include_path","d:\hidden");

The statement sets the include_path to the specified directory only while the script is running. It doesn't set the directory for your entire website.

To access a file from an include directory, just use the filename, as follows. You don't need to use the full pathname.

include("secretpasswords.inc");

If your include file isn't in an include directory, you may need to use the entire pathname in the include statement. If the file is in the same directory as the script, the filename alone is sufficient. However, if the file is located in another directory, such as a subdirectory of the directory the script is in or in a hidden directory outside the web space, you need to use the full pathname to the file, as follows:

include("d:\hidden\secretpasswords.inc");