Chapter 5
In This Chapter
Creating functions to manage your code's complexity
Enhancing your code by using functions
Working with variable scope
Getting familiar with session variables
Incorporating session variables into your code
PHP programs are used to solve interesting problems, which can get quite complex. In this chapter, you explore ways to manage this complexity. You discover how to build functions to encapsulate your code. You also learn how to use session variables to make your programs keep track of their values, even when the program is called many times.
It won't take long before your code starts to get complex. Functions are used to manage this complexity. As an example, take a look at Figure 5-1.
Before I show you how to improve your code with functions, look at a program that doesn't use functions so you have something to compare with.
The following rollDice.php program creates five random numbers and displays a graphic for each die:
<!DOCTYPE html>
<html lang = "en-US">
<head>
<meta charset = "UTF-8">
<title>rollDice1.php</title>
</head>
<body>
<h1>RollDice 1</h1>
<h2>Uses Sequential Programming</h2>
<div>
<?php
$roll = rand(1,6);
$image = "dado_$roll.png";
print <<< HERE
<img src = "$image"
alt = "roll: $roll"
width = "100px"
height = "100px" />
HERE;
$roll = rand(1,6);
$image = "dado_$roll.png";
print <<< HERE
<img src = "$image"
alt = "roll: $roll"
width = "100px"
height = "100px" />
HERE;
$roll = rand(1,6);
$image = "dado_$roll.png";
print <<< HERE
<img src = "$image"
alt = "roll: $roll"
width = "100px"
height = "100px" />
HERE;
$roll = rand(1,6);
$image = "dado_$roll.png";
print <<< HERE
<img src = "$image"
alt = "roll: $roll"
width = "100px"
height = "100px" />
HERE;
$roll = rand(1,6);
$image = "dado_$roll.png";
print <<< HERE
<img src = "$image"
alt = "roll: $roll"
width = "100px"
height = "100px" />
HERE;
?>
</div>
</body>
</html>
Here are some interesting features of this code:
$roll = rand(1,6);
$image = "dado_$roll.png";
print <<< HERE
<img src = "$image"
alt = "roll: $roll"
height = "100px"
width = "100px" />
HERE;
Functions are predefined code fragments. After you define a function, you can use it as many times as you wish. As you can see in the following code, the outward appearance of this program is identical to rollDice1.php, but the internal organization is quite different:
<!DOCTYPE html>
<html lang = "en-US">
<head>
<meta charset = "UTF-8">
<title>rollDice2.php</title>
</head>
<body>
<h1>RollDice 2</h1>
<h2>Uses Functions</h2>
<?php
function rollDie(){
$roll = rand(1,6);
$image = "dado_$roll.png";
print <<< HERE
<img src = "$image"
alt = "roll: $roll"
height = "100px"
width = "100px" />
HERE;
} // end rollDie
for ($i = 0; $i < 5; $i++){
rollDie();
} // end for loop
?>
</body>
</html>
Here's how things have changed in this version:
The function keyword indicates that a function definition will follow. The code inside the definition won't be run immediately, but instead, PHP will “remember” the code inside the function definition and play it back on demand:
function rollDie(){
The function name should indicate what the function does. I call my function rollDie() because that's what it does (rolls a die):
function rollDie(){
You can send arguments (special variables for your function to work with) by indicating them in the parentheses. This function doesn't need arguments, so I leave the parentheses empty:
function rollDie(){
For more information on functions, arguments, and the return statement, turn to Book IV, Chapter 4. Functions in PHP act almost exactly like their cousins in JavaScript.
The left brace is used to indicate the beginning of the function code.
Use indentation to indicate which code is part of your function. In this case, the function generates the random number and prints an image tag based on that random number:
function rollDie(){
$roll = rand(1,6);
$image = "dado_$roll.png";
print <<< HERE
<img src = "$image"
alt = "roll: $roll"
height = "100px"
width = "100px" />
HERE;
} // end rollDie
After the function is defined, you can use it in your code as if it were built into PHP. In this example, I call the function inside a loop:
for ($i = 0; $i < 5; $i++){
rollDie();
} // end for loop
Because the code is defined in a function, it's a simple matter to run it as many times as I want. Functions also make your code easier to read because the details of rolling the dice are hidden in the function.
Two kinds of scope are in PHP: global and local.
If you define a variable outside a function, it has the potential to be used inside any function. If you define a variable inside a function, you can access it only from inside the function in which it was created. See Book IV, Chapter 4 for more on variable scope.
So, if you have a variable that you want to access and modify from within the function, you either need to pass it through the parentheses or access it with the global modifier.
The following code will print hello world! only once:
<?php
$output = "<p>hello world!</p>";
function helloWorld(){
global $output;
print $output;
}
function helloWorld2(){
print $output;
}
helloWorld();
helloWorld2();
?>
I left the global keyword off in the helloWorld2() function, so it didn't print at all because inside the function, the local variable $output is undefined. By putting the global keyword on in the helloWorld() function, I let it know I was referring to a global variable defined outside the function.
At the end of the function, you can tell the function to return one (and only one) thing. The return statement should be the last statement of your function. The return statement isn't required, but it can be handy.
The getName() function in the following code example will return "World" to be used by the program. The program will print it once and store the text in a variable to be printed multiple times later, as shown in the following code and Figure 5-2:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>helloFunction</title>
</head>
<body>
<?php
function getName(){
return "World";
}
print "<h1>Hello, " . getName() . "!</h1>";
$name = getName();
print <<<HERE
<p>$name, welcome to our site. We are so very happy to have you here.</p>
<p>If you would like to contact us, $name, just use the form on the contact page.</p>
HERE;
?>
</body>
</html>
Server-side programming is very handy, but it has one major flaw. Every connection to the server is an entirely different transaction. Sometimes, you'll want to reuse a variable between several calls of the program. As an example, take a look at rollDice3.php in Figure 5-3.
The interesting feature of rollDice3.php happens when you reload the page. Take a look at Figure 5-4. This is still rollDice3.php, after I refreshed the browser a few times. Take a look at the total. It increases with each roll.
The rollDice3.php program is interesting because it defies normal server-side programming behavior. In a normal PHP program, every time you refresh the browser, the program starts over from scratch. Every variable starts out new.
The rollDice3.php program acts differently. It has a mechanism for keeping track of the total rolls and number of visits to the page.
When a visitor accesses your website, she's automatically assigned a unique session id. The session id is either stored in a cookie or in the URL. Sessions allow you to keep track of things for that specific user during her time on your site and during future visits if she's not cleared her cache or deleted her cookies.
Sessions are great because they are like a big box that the user carries around with him that you can just throw stuff into. Even if the user comes back to the site multiple times, the variables stored in the session retain their values. If you have hundreds of users accessing your site at the same time, each one will still have access to only their own versions of the variable.
Here's the code for rollDice3.php:
{<?php
{ session_start();
{?>
{<!DOCTYPE html>
{<html lang = "en-US">
{ <head>
{ <meta charset = "UTF-8">
{ <title>rollDice3.php</title>
{ </head>
{ <body>
{ <h1>RollDice 3</h1>
{ <h2>Uses a Session Variable</h2>
{ <?php
{function init(){
{ global $count;
{ global $total;
{ //increment count if it exists
{ if (isset($_SESSION["count"])){
{ $count = $_SESSION["count"];
{ $count++;
{ $_SESSION["count"] = $count;
{ } else {
{ //if count doesn't exist, this is our first pass,
{ //so initialize both session variables
{ $_SESSION["count"] = 1;
{ $_SESSION["total"] = 0;
{ $count = 1;
{ } // end if
{} // end init
{function rollDie(){
{ global $total;
{ $roll = rand(1,6);
{ $image = "dado_$roll.png";
{ print <<< HERE
{ <img src = "$image"
{ alt = "roll: $roll"
{ height = "100px"
{ width = "100px" />
{HERE;
{ $total = $_SESSION["total"];
{ $total += $roll;
{ $_SESSION["total"] = $total;
{} // end rollDie
{init();
{rollDie();
{print " <p>Rolls: $count</p>
";
{print " <p>Total: $total</p>
";
{ ?>
{ </body>
{</html>
This program rolls a die, but it uses session variables to keep track of the number of rolls and total value rolled. The session variable is updated every time the same user (using the same browser) visits the site.
Here's how to incorporate sessions into your programs:
If you want to use session variables, your code must begin with a session_start() call, even before the DOCTYPE definition. I put a tiny <?php ?> block at the beginning of the program to enable sessions:
<?php
session_start();
?>
The most common error with sessions is to not begin with session_start(). Session variables use HTTP headers as part of the communication process, and any other code (even a blank line or innocent HTML code) before the session_start will cause the header to be sent without the session information. Every program that includes session variables must begin with a session_start() call.
Like form variables, session variables may or may not exist when the program is executed. If this is the first pass through the program, the session variables may not have been created yet. The init() function checks whether the count session variable exists. If so, it will increment the counter; if not, it will initialize the sessions. $_SESSION is a superglobal array (much like $_REQUEST).
if (isset($_SESSION["count"])){
Create a local variable and extract the current value from the $_SESSION associative array:
$count = $_SESSION["count"];
Note that this line may trigger an error if you haven't already initialized the variable. Some PHP configurations are set up to automatically assign 0 to a nonexistent session variable, and some trigger an error.
The $count variable is now an ordinary variable, so you can add a value to it in the ordinary way:
$count++;
You can manipulate the local variable, but if you want to use the value the next time the program runs for this user, you need to store the value back into the session after you change it.
For example, the following code loads the variable $count from the session, adds 1 to it, and stores it back into the session:
$count = $_SESSION["count"];
$count++;
$_SESSION["count"] = $count;
Sometimes you need access to a session variable, but that session doesn't already exist. Usually, this will happen on the first pass of a program meant to run multiple times. It will also happen if the user jumps straight into a program without going through the appropriate prior programs (say you have got a system with three PHP programs and the user uses a bookmark to jump straight to program 3 without going to program 1, which sets up the sessions). In these situations, you'll either want to pass an error message or quietly create new session variables. In my example, I simply create a new session if it doesn't already exist. It's an easy matter of assigning values to the $_SESSION superglobal:
//if count doesn't exist, this is our first pass,
//so initialize both session variables
$_SESSION["count"] = 1;
$_SESSION["total"] = 0;
$count = 1;