Chapter 3
In This Chapter
Getting used to conditions
Using if, else if, and else
Using switch structures
Working with while and for loops
Using comparison operators
Computer programs are most interesting when they appear to make decisions. PHP has many of the same decision-making structures as JavaScript, so if you've already looked over Chapters 2 and 3 of Book IV, you will find this chapter very familiar. In any case, take a look at conditions to see the key to making the computer branch and loop.
Computer programs make decisions. That's part of what makes them interesting. But all the decisions a computer seems to make were already determined by the programmer. The computer's decision-making power is all based on an idea called a condition. This little gem is an expression that can be evaluated as true or false. (That sounds profound. I wonder if it will be on the mid-term?)
Conditions can be comparisons of one variable to another, they can be Boolean (true or false) variables, or they can be functions that return a true or false value.
The if statement is the powerhouse of computer programming. Take a look at Figure 3-1 to see it in action. This program might be familiar if you read Book IV already. It rolls a standard six-sided die, and then displays that die on the screen.
When it rolls a six, it displays an elaborate multimedia event, as shown in Figure 3-2. (Okay, it just says Holy Guacamole! That's a six! The dancing hippos come later …)
This program is much like the if.html program in Book IV, Chapter 3. I do all the same things here as in that program. However, PHP and JavaScript are a little different, and that's part of the game of programming. Appreciate the concepts that flow between languages while noting those details that are different.
PHP has a random number generator, which works a little differently than the one in JavaScript. The PHP version is actually easier for dice.
$variable = rand(a, b);
This code creates a random integer between a and b (inclusive), so if you want a random 1–6 die, you can use a statement like this:
$die = rand(1,6);
It doesn't get a lot easier than that.
The code for the if.php program rolls a die, displays an image, and celebrates the joyous occasion of a six.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>if.php</title>
</head>
<title>if.php</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
</head>
<body>
<h1>Try to roll a six</h1>
<p>
<a href = "if.php">roll again</a>
</p>
<?php
//thanks to user rg1024 from openClipart.org for
//the great dice images
$roll = rand(1,6);
print <<<HERE
<p>
<img src = "images/dado_$roll.png"
alt = "$roll"
height = "100px"
width = "100px" />
</p>
HERE;
if ($roll == 6){
print("<h1>Holy Guacamole! That's a six!</h1>
");
} // end if
?>
</body>
</html>
The process is eerily familiar:
As always, PHP is encased in HTML. There's no need to switch to PHP until you get to the part that HTML can't do: that is, rolling dice and responding to the roll.
Add a link that returns to the same page. When the user clicks the link, the server refreshes the page and rolls a new number.
I preloaded a bunch of die images into a directory called images. Each image is carefully named dado_1.png through dado_6.png. (Dado is Spanish for “die” — thanks to user rg1024 from openclipart.org for the great images.) To display an image in PHP, just print out a standard img tag. The URL is created by interpolating the variable $roll into the image name. Don't forget that HTML requires an alt attribute for the img tag. I just use the $roll value as the alt. That way, the die roll will be known even if the image doesn't work.
This is where the condition comes in. Use the if statement to see whether the value of $roll is 6. If so, print out a message.
The else clause is used when you want to do one thing if a condition is true and something else if the condition is false. The highLow.php program shown in Figure 3-3 handles this kind of situation.
The code is very similar to the if.php program.
The bold code shows the only part of the program that's new.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>highLow.php</title>
</head>
<body>
<h1>High or low?</h1>
<p>
<a href = "highLow.php">roll again</a>
</p>
<?php
$roll = rand(1,6);
print <<<HERE
<p>
<img src = "images/dado_$roll.png"
alt = "$roll"
height = "100px"
width = "100px" />
</p>
HERE;
if ($roll > 3){
print "<h2>You rolled a high one</h2>
";
} else {
print "<h2>That's pretty low</h2>
";
} // end if
?>
</body>
</html>
Most of the code for this program is the same as the previous code example, but the condition is slightly different:
Table 3-1 Comparison Operators
Comparison |
Discussion |
A == B |
True if A is equal to B |
A != B |
True if A is not equal to B |
A < B |
True if A is less than B (if they are numeric) or earlier in the alphabet (for strings) |
A > B |
True if A is larger than B (numeric) or later in the alphabet (string) |
A >= B |
A is larger than or equal to B |
A<= B |
A is less than or equal to B |
The else clause is special because it handles the situation when the condition is false. All it does is set up another block of code.
The code between else and the ending brace for if ending brace will run only if the condition is evaluated false.
PHP uses many of the same comparison operators as JavaScript (and many other languages based on C). Table 3-1 summarizes these operators.
Note that PHP determines the variable type dynamically, so comparisons between numeric and string values may cause problems. It's best to explicitly force variables to the type you want if you're not sure. For example, if you want to ensure that the variable $a is an integer before you compare it to the value 4, you could use this condition:
(integer)$a == 4
This forces the variable $a to be read as an integer. You can also use this technique (called typecasting) to force a variable to other types: float, string, or boolean.
Another variation of the if structure allows you to check multiple conditions. As an example, look at the highMidLow.php page featured in Figure 3-4.
If the roll is 1 or 2, the program reports Low. If the roll is 3 or 4, it says Middle; and if it's 5 or 6, the result is High. This if has three branches. See how it works; you can add as many branches as you wish.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>highMidLow.php</title>
</head>
<body>
<h1>High, middle, or low?</h1>
<p>
<a href = "highMidLow.php">roll again</a>
</p>
<?php
$roll = rand(1,6);
print <<<HERE
<p>
<img src = "images/dado_$roll.png"
alt = "$roll"
height = "100px"
width = "100px" />
</p>
HERE;
if ($roll > 4){
print "<h2>High!</h2>
";
} else if ($roll <= 2){
print "<h2>Low</h2>
";
} else {
print "<h2>Middle</h2>
";
} // end if
?>
</body>
</html>
The if statement is the only part of this program that's new. It's not terribly shocking.
Check whether the roll is greater than 4. If so, say High. If the first condition is true, the computer evaluates the code in the first section and then skips the rest of the while loop.
The else if section allows me to add a second condition. This second condition (roll <= 2) is evaluated only if the first condition is false. If this condition is true, the code inside this block will be executed (printing the value Low). You can add as many else if sections as you want. As soon as one is found to be true, the code block associated with that condition executes, and the program leaves the whole else system.
If none of the previous conditions are true, the code associated with the else clause operates. In this case, the roll is lower than 4 and higher than 2, so report that it's in the Middle.
An especially important application of the if structure is unique to server-side programming. Up to now, many of your PHP programs required two separate files: an HTML page to get information from the user and a PHP program to respond to that code. Wouldn't it be great if the PHP program could determine whether it had the data or not? If it has data, it will process it. If not, it just produces a form to handle the data. That would be pretty awesome, and that's exactly what you can do with the help of the if statement. Figure 3-5 shows the first pass of ownForm.php.
The interesting thing happens when the user submits the form. The program calls itself! This time, though, ownForm recognizes that the user has sent some data and processes that information, giving the result shown in Figure 3-6.
This program doesn't really require anything new, just a repurposing of some tools you already know. Take a look at the following code:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ownForm.php</title>
</head>
<body>
<?php
if (filter_has_var(INPUT_POST, "userName")){
//the form exists - process it
$userName = filter_input(INPUT_POST, "userName");
print "<h1>Hi, $userName</h1>
";
} else {
//no form present, so give 'em one
print <<<HERE
<form action = ""
method = "post">
<fieldset>
<label>Name</label>
<input type = "text"
name = "userName">
<button type = "submit">
submit
</button>
</fieldset>
</form>
HERE;
} // end if
?>
</body>
</html>
Making a program “do its own stunts” like this is pretty easy. The key is using an if statement. However, begin by thinking about the behavior. In this example, the program revolves around the $userName variable. If this variable has a value, it can be processed. If the variable has not been set yet, the user needs to see a form so she can enter the data.
Use the isset() function to determine whether the variable in question has been set. Check the $_REQUEST or one of the other superglobals ($_POST or $_GET) to determine whether the form has already been submitted. You need to check the existence of only one variable, even if the form has dozens.
If the variable exists, extract all the variables from the form and carry on with your processing.
If the variable does not exist, you need to make the form that will ask the user for that variable (and any others you need). Note that the action attribute of the form element should be null (““). This tells the server to re-call the same program.
Often, you run across a situation where you have one expression that can have many possible values. You can always use the if–else if structure to manage this situation, but PHP supplies another interesting option, shown in Figure 3-7.
The code for this program uses the switch structure. Take a look at how it's done:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>switch.php</title>
</head>
<body>
<p>Ask the magic 8 ball a yes or no question!</p>
<?php
$yourNumber = rand(1,8);
switch($yourNumber){
case 1:
print "<p><img src="images/8ball1.png" alt = "fat chance"
/></p>";
break;
case 2:
print "<p><img src="images/8ball2.png" alt = "Yes" /></p> ";
break;
case 3:
print "<p><img src="images/8ball3.png" alt = "PhD" /></p>";
break;
case 4:
print "<p><img src="images/8ball4.png" alt = "You didn't say please" /></p>";
break;
case 5:
print "<p><img src="images/8ball5.png" alt = "tell, then kill" /></p>";
break;
case 6:
print "<p><img src="images/8ball6.png" alt = "Why trust me?" /></p>";
break;
case 7:
print "<p><img src="images/8ball7.png" alt = "Ask your mother" /></p>";
break;
case 8:
print "<p><img src="images/8ball8.png" alt = "The answer is in the question" /></p>";
break;
default:
print "<p>An error has occurred. Please try again, or contact [email protected] for assistance. Error code: 8BIC:$yourNumber
</p>";
}
?>
<p>
<a href="switch.php">Ask another question!</a>
</p>
</body>
</html>
The main (in fact nearly only) feature of this code is the switch statement. Here's how it works:
This indicates that you will be building a switch structure.
Following the switch statement is a pair of parentheses. Put the expression (usually a variable) you wish to evaluate inside the parentheses. In this case, I'm checking the value of the variable $yourNumber.
Use squiggle braces to indicate the entire case. As in most blocking structures, use indentation to help you remember how the structure is organized.
Put the first value you want to check for. In this situation, I'm looking for the value 1. Note that the type of data matters, so be sure you're comparing against the same type of data you think the variable will contain. Use a colon (:) to indicate the end of the case. This is one of the rare situations where you do not use a semicolon or brace at the end of a line.
If the expression matches the case (for example, if $yourNumber is equal to 1), the code you write here will execute.
When you use an if-else if structure to work with multiple conditions, the interpreter jumps out of the system as soon as it encounters the first true condition. Switches work differently. Unless you specify (with the break statement), code will continue to evaluate even when one of the expressions is matched. You almost always need the break statement.
The default section of the switch structure is used to handle any situation that wasn't covered by one of the previously defined cases. It's a good idea to always include a default clause.
Sometimes you want to repeat something. PHP (like most languages) supports a number of looping constructs. Begin with the humble but lovable for loop, as shown in Figure 3-8.
As you can see, Figure 3-8 prints a lot of dice. In fact, it prints 100 dice. This would be tedious to do by hand, but that's exactly the kind of stuff computers are so good at.
The following code explains all:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>for.php</title>
<style type="text/css">
img{
height: 40px;
width: 50px;
}
</style>
</head>
<body>
<h1>Dice Rolling Game</h1>
<p>Welcome to the dice rolling game. Rolling 100 dice. How many will be sixes?</p>
<p>
<?php
$sixCount = 0;
for ($i = 0; $i < 100; $i++){
$userNumber = rand(1,6);
print <<< HERE
<img src="images/dado_$userNumber.png"
alt = "$userNumber"
width = "20px"
height = "20px" />
HERE;
if($userNumber == 6){
$sixCount++;
} // end if
} // end for
print "</p><p>You rolled $sixCount six(es)!</p>";
?>
<p><a href="for.php">Try Again!</a></p>
</body>
</html>
Most of the code is plain-old HTML. Note the lone print statement responsible for printing out dice. That print statement (and a few supporting characters) are repeated 100 times. for loops are extremely powerful ways to get a lot of work done.
This keyword indicates the beginning of the for structure.
for ($i = 0; $i < 100; $i++){
for loops usually center around a specific integer variable, sometimes called the sentry variable. The first part of the for loop sets up the initial value of that variable. Often, the variable is initialized to 0 or 1.
for ($i = 0; $i < 100; $i++){
The loop continues as long as the condition is true and exits as soon as the condition is evaluated as false. Normally, the condition will check whether the variable is larger than some value.
for ($i = 0; $i < 100; $i++){
Every time through the loop, you need to do something to change the value of the sentry. Normally, you add 1 to the sentry variable (remember, ++ is a shortcut for “add one”).
for ($i = 0; $i < 100; $i++){
The code that will be repeated is placed inside braces({}). As usual, indent all code inside braces so you understand that you're inside a structure.
This particular program has a few other features that make it suitable for printing out 100 dice.
$userNumber = rand(1,6);
print <<< HERE
<img src="images/dado_$userNumber.png"
alt = "$userNumber"
width = "20px"
height = "20px" />
HERE;
if($userNumber == 6){
$sixCount++;
} // end if
print “</p><p>You rolled $sixCount six(es)!</p>“;
The while loop is the other primary way of repeating code. Figure 3-9 shows a variation of the dice-rolling game.
while loops are much like for loops. They require the same thought:
Take a look at the following code for the while.php program to see how it works:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>while.php</title>
<style type="text/css">
img {
height: 40px;
width: 50px;
}
</style>
</head>
<body>
<h1>Dice Rolling Game 2</h1>
<p>Welcome to the dice rolling game. See how many rolls it takes to get a six!</p>
<div id = "output">
<?php
$userNumber = 999;
$counter = 0;
while ($userNumber != 6){
$userNumber = rand(1,6);
print <<< HERE
<img src = "images/dado_$userNumber.png"
alt = "$userNumber"
height = "100px"
width = "100px" />
HERE;
$counter++;
}
print "<p>It took $counter tries to get a six.</p>";
?>
</div>
<p><a href="while.php">Try Again!</a></p>
</body>
</html>
This example illustrates how subtle while loops can be. All the key elements are there, but they don't all look like part of the while loop.
For this loop, $userNumber is the sentry variable. The initialization needs to guarantee that the loop runs exactly once. Because the condition will be ($userNumber != 6), I need to give $userNumber a value that clearly isn't 6. 999 will do the job, and it's wild enough to be clearly out of range. Although the initialization step appears in the code before the while loop, it's often best to start with your condition and then back up a line to initialize because the initialization step depends on the condition.
Think about what should cause the loop to continue or quit. Remember that the condition explains when the loop continues. It's often easier to think about what causes the loop to exit. That's fine; just reverse it. For example, I want the loop to quit when $userNumber is equal to 6, so I'll have it continue as long as $userNumber != 6.
This one is tricky. In this particular example, modify the sentry variable by getting a new random number: $userNumber = rand(1,6). Often in a while loop, the modification step is intrinsic to the problem you're solving. Sometimes you get the new value from the user, sometimes you get it from a file or database, or sometimes you just add (just like a for loop). The key here is to ensure you have a statement that modifies the sentry variable and that the condition can trigger. For example, using $userNumber = rand(1,5) would result in an endless loop because $userNumber could never be 6.