Chapter 6: Using Functions and
Session Variables
Mark: This chapter is an aggregate of the original chapter 3 with some material from original
chapter 6. All the form stuff that was in the previous incarnation of this chapter is superceded
by the new chapter 3. Andy
PHP programs are used to solve interesting problems, which can get quite
complex. In this chapter you learn 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.
Creating your own functions
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 6-1.
Figure 6-1 This program rolls 5 dice
Rolling dice the old-fashioned way
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 rollDice.php program creates five random numbers and displays a
graphic for each die. Here’s the code:
rollDice1.php
RollDice 1
Uses Sequential Programming
HERE;
$roll = rand(1,6);
$image = "die$roll.jpg";
print
HERE;
$roll = rand(1,6);
$image = "die$roll.jpg";
print
HERE;
$roll = rand(1,6);
$image = "die$roll.jpg";
print
HERE;
$roll = rand(1,6);
$image = "die$roll.jpg";
print
HERE;
?>
There are some interesting features of this code:
The built-in rand() function rolls a random number.
Whenever possible, try to find functions that can help you. The rand()
function produces a random integer. If you use two parameters, the resulting
number will be in the given range. To roll a standard six -sided die, use
rand(1,6)
$roll = rand(1,6);
I have created an image for each possible roll.
To make this program more visually appealing, I created an image for each
possible die roll. The images are called “die1.jpg”, “die2.jpg”, and so on.
All these images are stored in the same directory as the PHP program.
The img tag is created based on the die roll.
Once I have a die roll, it’s easy to create an image based on that roll.
$image = "die$roll.jpg";
print
HERE;
The die-rolling code is repeated five times.
If you can roll one die, you can easily roll five. I just copied and pasted the
code. This seems pretty easy, but it leads to problems. What if I want to
change the way I roll the dice? If so, I’ll have to change the code five times.
What if I want to roll 100 dice? The program will quickly become
unwieldy. In general, if you find yourself copying and pasting code, you can
improve the code by adding a function.
Improving code with functions
Functions are code pre-defined code fragments. Once you define a function,
you can use it as many times as you wish. The outward appearance of this
program is identical to rollDice1.php (so I won’t show a screenshot) but the
internal organization is quite different:
rollDice2.php
RollDice 2
Uses Functions
HERE;
} // end rollDie
for ($i = 0; $i
Here’s how things have changed in this version:
1. Use the function keyword to define a function.
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(){
2. Give the function a name.
The function name should indicate what the function does. I call my
function rollDie() because that’s what it does (roll a die)
function rollDie(){
3. Specify arguments with parentheses.
You can send arguments (special variables for your function to work with)
by indicating them in the parentheses. This function does not need
arguments, so I leave the parentheses empty.
function rollDie(){
For more information on functions, arguments, and the return statement,
look at Book IV, chapter 4. Functions in PHP act almost exactly like their
cousins in JavaScript.
4. Begin the function definition with a left brace ({).
The left brace is used to indicate the beginning of the function code.
5. Indent the code that makes up your function.
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 = "die$roll.jpg";
print
HERE;
} // end rollDie
6. Denote the end of the function with a right brace (}).
7. Call the function by referring to it.
Once 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 hello world!";
function helloWorld(){
global $output;
print $output;
}
function helloWorld2(){
print $output;
}
helloWorld();
helloWorld2();
?>
Figure 6-2: Demonstrates global and local scope.
Chris: Above yellow, can you add a descriptive caption?—Mark Done! -Chris
We 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,
we let it know we were referring to a global variable defined outside the
function.
PHP defaults to local inside variables because it doesn’t want you to
accidentally access or overwrite other variables throughout the program. For
more information about global and local scoping, check out
http://us3.php.net/global.
Returning data from functions
At the end of the function, you can tell the function to return one (and on ly
one) thing. The return statement should be the last statement of your
function. The return statement isn’t required, but it can be handy.
Chris: Green: What is “it” here? The function? Thanks, Jen yep. Thanks, Chris
Chris: Above first yellow, is my edit right? Second yellow, what do you mean by "that's the
end of the function?"—Mark Fixed. Thanks! -Chris
Let’s not emphasize multiple returns, as it’s a poor coding practice, and never necessary
Chris: Blue: Please double-check this cross-reference. Thanks, Jen Andy? –Chris gone. Andy
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 co de
and Figure 6-3:
Chris: Above yellow, return is a function?—Mark Fixed. -Chris
Hello" . getName() . "";
$name = getName();
print $name, welcome to our site. We are so very happy to have you here.
If you would like to contact us $name, just use the form on the contact
page.
Chris: Above yellow, should this say "would"?—Mark Yep! Thanks. -Chris
HERE;
?>
Figure 6-3: An example of a function with a return statement.
Chris: Above yellow, can you add a descriptive caption?—Mark Sure! -Chris
For more on return statements see http://de3.php.net/return.
Sidebar is unneeded, as it’s a repeat of earlier information.
Managing Persistence with Session Variables
Server-side programming is very handy, but it has one major flaw. Every
connection to the server is an entirely different transaction. S ometimes
you’ll want to re-use a variable between several calls of the program. As an
example, take a look at rollDice3.php in figure 6-4
Figure 6-4 This page displays a roll, the number of rolls, and the total rolls so far
The interesting feature of rollDice3.php happens when you reload the page.
Take a look at figure 6-5. This is still rollDice3.php, after I refreshed the
browser a few times. Take a look at the total. It increases with each roll.
Figure 6-5 The count and total values keep on growing.
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.
Understanding session variables
This program (rollDice3.php) 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 Web site, he’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.
Any mundane hacker can sniff out your session ids if you allow them to be
stored in the URL. To keep this from happening, use the
session.use_only_cookies directive in your PHP configuration file. This may
be inconvenient to users who don’t want you to have a cookie stored on their
machine, but it’s necessary if you’re storing anything sensitive in their
session.
Above tip is expanded into a sidebar.
Chris: Green: Please define for the reader. Thanks, JenDone-Chris
I guess I don’t know how we are doing it for the rest of the book, but I prefer the gender
neutral “he” to the gender specific “she”. To avoid any conflict I’ve been putting “they”
because some people mistake “he” for being gender specific (When it’s not, whereas “she”
can’t be anything but gender specific). Not my call though I guess…
Also, I see someone has highlighted the green references to “cracker”. Yeah, it’s supposed to
be cracker, but since I do recognize that few people actually understand the difference
between a hacker and a cracker anymore, I won’t complain too much about this being
changed to hacker (even though that’s wrong)
I agree with what Chris is saying, but that’s not a hill I’m ready to die on. -Andy
If you are at all interested (which you probably aren’t) see Eric S. Raymond’s “How To
Become A Hacker” essay (included in the book “The Cathedral & The Bazaar” from
O’Reilly) here: http://catb.org/~esr/faqs/hacker-howto.html. Basically, to sum it up, Hackers
make things, Crackers break them. The original great computer programmers called
themselves Hackers. Then crackers came along and started calling themselves hackers, and
then the media got a hold of the term and confused it and ruined it.
-Chris
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:
rollDice3.php
RollDice 3
Uses a Session Variable
HERE;
$total = $_SESSION["total"];
$total += $roll;
$_SESSION["total"] = $total;
} // end rollDie
$count = $_SESSION["count"];
$count++;
$_SESSION["count"] = $count;
rollDie();
print " Rolls: $count \n";
print " Total: $total \n";
?>
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.
Adding session variables to your code
Here’s how to incorporate sessions into your programs
1. Begin your code with a call to session_start()
If you want to use session variables, your code must begin with a
session_start() call. This must be the absolute first part of your program,
even before the Doctype definition. I put a tiny block at the
beginning of the program to enable sessions.
2. Load session variables from the $_SESSION superglobal
$_SESSION is a superglobal array (much like $_REQUEST.) Create a local
variable and extract the current value from the $_SESSION associative
array.
$total = $_SESSION["total"];
If there is no total element in the $_SESSION array, a null value is
assigned to the variable instead (which evaluates to zero in a numeric
context.)
3. Store session variables in the $_SESSION superglobal
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 one to it, and stores it back into the session:
$count = $_SESSION["count"];
$count++;
$_SESSION["count"] = $count;
Sessions and Security
The session mechanism is powerful and easy to use. It isn’t quite foolproof, though.
Sessions are automatically handled through a browser mechanism called cookies. Cookies
aren’t inherently good or evil, but they’ve gotten a bad reputation because some programs
use them maliciously. You’ll occasionally run across a user who’s turned cookies off, but this
is not a major problem, as PHP can automatically use other options when cookies are not
available. There’s rarely a need to work with cookies directly in PHP, as sessions are a
higher-level abstraction of the cookie concept.
Like all data passed through the HTTP protocol, session and cookie information is passed
entirely in the clear. A person with evil intent can capture your session information and use it
to do bad things.
Generally you should stay away from sensitive information (credit card data, social security
numbers, and so on) unless you’re extremely comfortable with security measures. If you
must pass potentially sensitive data in your PHP program, investigate a technology called
TLS (Transport Layer Security,) which automatically encrypts all data transferred through
your site. TLS replaces the older SSL technology, and is available as a free plugin to apache
servers.
If you want to reset your sessions for testing purposes, you can write a quick
program to set the variables to zero, or you can use the Web Developer
Toolbar: Cookies @@nd Clear session cookies. Note that the session data
itself isn’t stored in the cookie. The cookie just contains a reference number
so the server can look up the session data in a file stored on the server.
Following is good material, but I took it out. Include is convered in VIII.4 I would have kept
it, but frankly I don’t have time to do a new example, and the RPG example (cool as it is)
didn’t make the cut.
OOP stuff was a noble effort that didn’t work. It seems disingenuous to insist that OOP is the
way to go in this chapter, and to then never build another object in the book. It’s true that
OOP is probably the future of PHP, but the present is firmly entrenched in procedural
programming. If we wanted to make this a more forward-looking mini-book, we could, but
we’d then have the obligation to make all later chapters OOP, sacrificing some readability.
This was a hard decision for me, but I think a good one. I still need to do DB stuff today.
-Andy