Anda di halaman 1dari 168

Introduction to PHP

Lesso n 1: Int ro duct io n


Wo rking in Co deRunner
Creating a File
Managing yo ur Files

Fo ur characteristics o f PHP
1. PHP is a server-side language, with HTML embedding.
2. PHP is a Parsed language.
3. PHP wo rks jo intly with SQL.
4. PHP is part o f the LAMP, WAMP, and MAMP stack.

Lesso n 2: PHP Basics


PHP Delimiters and Co mments
Variables in PHP
Mo difying Variables and Values with Operato rs
Superglo bals
$GLOBALS
$_SERVER:
$_GET
$_POST

Lesso n 3: De cisio ns
Co mpariso n Operato rs and Co nditio ns
IF and ELSE Co ntro l Structure
Lo gical Operato rs
A Brief Preview o f Fo rms

Lesso n 4: Mult iple Co nt ro l St ruct ure s and Lo o ps


Multiple Co ntro l Structures
WHILE and FOR Lo o ps

Lesso n 5: Funct io ns
Creating Co de Reusability with Functio ns
Functio n and Variable Sco pes
Using Functio ns with Parameters and Return Values
Sneaking In with Parameters
Sneaking o ut with Return Values
Multiple Parameters and Default Values

Lesso n 6 : Arrays
Creating an Array
Asso ciative Arrays
Creating Multi-Dimensio nal Arrays
Traversing and Manipulating Arrays
Traversing Asso ciative Arrays with list() and each()

Mo re built-in functio ns
Lesso n 7: St rings
What's a String Anyway?
Manipulating Strings
Other nifty string sho rtcuts

Built-in String Functio ns


Regular Expressio ns
Character Ranges and Number o f Occurrences
Excluding Characters
Escaping Characters

Lesso n 8 : Fixing Bro ke n PHP


Things Pro fesso rs Do n't Talk Abo ut Eno ugh
Debugging Tips
Utilizing Erro r Messages
Riddle-Me-This Erro r Messages
Erro rs witho ut Erro r Messages
Lo gical Erro rs
Infinite Lo o ps, Infinite Headaches

No tes o n Scalable Pro gramming


Befo re yo u Co de, Pseudo co de
Make yo ur Pro gram Readable
Co mment Until Yo u're Blue in the Face
Co de in Bite-Size Chunks
Debug as Yo u Wo rk
Reuse Functio ns as Much as Po ssible
Utilize Available Reso urces

Lesso n 9 : Fo rm s in PHP
Fo rms Review
Using Superglo bals to Read Fo rm Inputs
Extracting Superglo bals into Variables
Nesting Variable Names

Lesso n 10 : Ut ilizing Int e rne t T o o ls


Enviro nment and Server Variables
Using HTTP Headers
Manipulating Query Strings
Custo mizing specific erro r messages

Sending Emails

Lesso n 11: Dat e and T im e


Date and Time Standards
Date and Time Functio ns
Co nstructing Dates and Times

Lesso n 12: Using File s


Including and Requiring Files
Reading and Writing Files
Allo wing Users to Do wnlo ad Files

Lesso n 13: Co o kie s and Se ssio ns


Using Co o kies
Kno wing the User Thro ugh Sessio ns
Deleting Sessio ns

Lesso n 14: Final Pro je ct


Final Pro ject

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Introduction
Welco me to the O'Reilly Scho o l o f Techno lo gy Int ro duct io n t o PHP co urse!

In this PHP class, yo u will learn basic to intermediate pro gramming aspects o f PHP--hypertext prepro cesso r. PHP is a versatile
server-side pro gramming language that wo rks hand-in-hand with fro nt-end web languages such as HTML and JavaScript. PHP
can be used to create all types o f dynamic web interfaces, and because o f its o pen-so urce ro bustness, has beco me o ne o f the
mo st widely used pro gramming languages fo r the internet.

Course Objectives
When yo u co mplete this co urse, yo u will be able to :

develo p web applicatio ns using basic PHP elements such as delimiters, co ntro l structures, o perato rs, variables,
arrays, and functio ns.
manipulate dates and strings using built-in PHP functio ns and regular expressio ns.
debug and impro ve co de fo r better reusability and scalability.
create dynamic web fo rms using internet to o ls such as input, enviro nment and server variables, HTTP headers, and
query strings.
read, write, manage and do wnlo ad files thro ugh PHP-based web applicatio ns.
track user info rmatio n using co o kies and sessio ns.
build a full-fledged sho pping cart system.

Fro m beginning to end,yo u will learn by do ing yo ur o wn PHP based pro jects. These pro jects, as well as the final pro ject, will
add to yo ur po rtfo lio and pro vide needed experience. Besides a bro wser and internet co nnectio n, all so ftware is pro vided
o nline by the O'Reilly Scho o l o f Techno lo gy.

Learning with O'Reilly School of T echnology Courses


As with every O'Reilly Scho o l o f Techno lo gy co urse, we'll take a user-active appro ach to learning. This means that yo u
(the user) will be active! Yo u'll learn by do ing, building live pro grams, testing them and experimenting with them—
hands-o n!

To learn a new skill o r techno lo gy, yo u have to experiment. The mo re yo u experiment, the mo re yo u learn. Our system
is designed to maximize experimentatio n and help yo u learn to learn a new skill.

We'll pro gram as much as po ssible to be sure that the principles sink in and stay with yo u.

Each time we discuss a new co ncept, yo u'll put it into co de and see what YOU can do with it. On o ccasio n we'll even
give yo u co de that do esn't wo rk, so yo u can see co mmo n mistakes and ho w to reco ver fro m them. Making mistakes
is actually ano ther go o d way to learn.

Abo ve all, we want to help yo u to learn to learn. We give yo u the to o ls to take co ntro l o f yo ur o wn learning experience.

When yo u co mplete an OST co urse, yo u kno w the subject matter, and yo u kno w ho w to expand yo ur kno wledge, so
yo u can handle changes like so ftware and o perating system updates.

Here are so me tips fo r using O'Reilly Scho o l o f Techno lo gy co urses effectively:

T ype t he co de . Resist the temptatio n to cut and paste the example co de we give yo u. Typing the co de
actually gives yo u a feel fo r the pro gramming task. Then play aro und with the examples to find o ut what else
yo u can make them do , and to check yo ur understanding. It's highly unlikely yo u'll break anything by
experimentatio n. If yo u do break so mething, that's an indicatio n to us that we need to impro ve o ur system!
T ake yo ur t im e . Learning takes time. Rushing can have negative effects o n yo ur pro gress. Slo w do wn and
let yo ur brain abso rb the new info rmatio n tho ro ughly. Taking yo ur time helps to maintain a relaxed, po sitive
appro ach. It also gives yo u the chance to try new things and learn mo re than yo u o therwise wo uld if yo u
blew thro ugh all o f the co ursewo rk to o quickly.
Expe rim e nt . Wander fro m the path o ften and explo re the po ssibilities. We can't anticipate all o f yo ur
questio ns and ideas, so it's up to yo u to experiment and create o n yo ur o wn. Yo ur instructo r will help if yo u
go co mpletely o ff the rails.
Acce pt guidance , but do n't de pe nd o n it . Try to so lve pro blems o n yo ur o wn. Go ing fro m
misunderstanding to understanding is the best way to acquire a new skill. Part o f what yo u're learning is
pro blem so lving. Of co urse, yo u can always co ntact yo ur instructo r fo r hints when yo u need them.
Use all available re so urce s! In real-life pro blem-so lving, yo u aren't bo und by false limitatio ns; in OST
co urses, yo u are free to use any reso urces at yo ur dispo sal to so lve pro blems yo u enco unter: the Internet,
reference bo o ks, and o nline help are all fair game.
Have f un! Relax, keep practicing, and do n't be afraid to make mistakes! Yo ur instructo r will keep yo u at it
until yo u've mastered the skill. We want yo u to get that satisfied, "I'm so co o l! I did it!" feeling. And yo u'll have
so me pro jects to sho w o ff when yo u're do ne.

Lesson Format
We'll try o ut lo ts o f examples in each lesso n. We'll have yo u write co de, lo o k at co de, and edit existing co de. The co de
will be presented in bo xes that will indicate what needs to be do ne to the co de inside.

Whenever yo u see white bo xes like the o ne belo w, yo u'll type the co ntents into the edito r windo w to try the example
yo urself. The CODE TO TYPE bar o n to p o f the white bo x co ntains directio ns fo r yo u to fo llo w:

CODE TO TYPE:
White boxes like this contain code for you to try out (type into a file to run).

If you have already written some of the code, new code for you to add looks like this.

If we want you to remove existing code, the code to remove will look like this.

We may also include instructive comments that you don't need to type.

We may run pro grams and do so me o ther activities in a terminal sessio n in the o perating system o r o ther co mmand-
line enviro nment. These will be sho wn like this:

INTERACTIVE SESSION:

The plain black text that we present in these INTERACTIVE boxes is


provided by the system (not for you to type). The commands we want you to type look lik
e this.

Co de and info rmatio n presented in a gray OBSERVE bo x is fo r yo u to inspect and absorb. This info rmatio n is o ften
co lo r-co ded, and fo llo wed by text explaining the co de in detail:

OBSERVE:
Gray "Observe" boxes like this contain information (usually code specifics) for you to
observe.

The paragraph(s) that fo llo w may pro vide additio n details o n inf o rm at io n that was highlighted in the Observe bo x.

We'll also set especially pertinent info rmatio n apart in "No te" bo xes:

Note No tes pro vide info rmatio n that is useful, but no t abso lutely necessary fo r perfo rming the tasks at hand.

T ip Tips pro vide info rmatio n that might help make the to o ls easier fo r yo u to use, such as sho rtcut keys.

WARNING Warnings pro vide info rmatio n that can help prevent pro gram crashes and data lo ss.

T he CodeRunner Screen
This co urse is presented in Co deRunner, OST's self-co ntained enviro nment. We'll discuss the details later, but here's
a quick o verview o f the vario us areas o f the screen:
These video s explain ho w to use Co deRunner:

File Management Demo

Co de Edito r Demo

Co ursewo rk Demo

Working in CodeRunner
Since Co deRunner is a multi-purpo se edito r, yo u need to make sure yo u're using the co rrect synt ax. In this co urse,
yo u will be using HTML and PHP. To start using HTML, cho o se the HT ML o ptio n:

To change to PHP, cho o se the PHP o ptio n:

Creating a File
Let's create a file no w. Select the HTML syntax and type the co de as sho wn belo w.

Make sure yo u're using HTML syntax and type the fo llo wing into Co deRunner:
Four characteristics of PHP:

<ol>
<li> PHP is a server-side language with HTML embedding.</li>
<li> PHP is a parsed language.</li>
<li> PHP works hand-in-hand with SQL.</li>
<li> PHP is part of the LAMP stack.</li>
</ol>

Managing your Files


Click the butto n. In the Save As text bo x, type f o urf act s.ht m l (be sure to include the html extensio n when
yo u Save html files).

Yo u can also use the Save As ( ) butto n to save a file with a different name. Try it no w with the name
f o urf act s2.ht m l. No te that yo u are no w editing fo urfacts2.html, no t fo urfacts.html.

After yo u successfully save yo ur file, anybo dy can go o n the web, type the URL
(http://yourusername.o reillystudent.co m/fo urfacts.html) in the lo catio n bar o f their bro wser, and see this page.

To retrieve the o riginal f o urf act s.ht m l, click the Lo ad File ( ) butto n o r do uble-click the file name in the
File Bro wse r windo w.

Four characteristics of PHP


Lo o k again at the HTML to p-fo ur list yo u just typed into Co deRunner, and click Preview:

Keep in mind that every time yo u Preview a file, yo ur changes will be saved. Think abo ut whether yo u
Note want the previo us co de o verwritten o r no t. If no t, use Save As befo re yo u Preview.

Four characteristics of PHP:

1. PHP is a server-side language with HTML embedding.


2. PHP is a parsed language.
3. PHP works hand-in-hand with SQL.
4. PHP is part of the LAMP stack.

If the Preview butto n do esn't wo rk fo r yo u, yo u may be blo cking po p-up windo ws in yo ur bro wser. To fix
Note this, change yo ur co nfiguratio n settings to allo w po p-ups fro m the OST servers, o r view yo ur page
directly at http://yourusername.o reillystudent.co m/fo urfacts.html.

This example serves mo re than o ne purpo se fo r us. It demo nstrates ho w to use Co deRunner and it intro duces so me
keys to using PHP. Of co urse there's much mo re to PHP than this, but let's start with this.

1. PHP is a server-side language, with HT ML embedding.


On the web there are two sides to everything: the Client Side and the Server Side. The Client side is the side
yo u are o n right no w. It co nsists o f yo ur co mputer and yo ur web bro wser. The server side is the side where
the web pages are sto red and where pro grams are executed to build dynamic web pages with PHP.
Still have yo ur HTML list? It's time to co nvert it to PHP. Swit ch Co de Runne r t o PHP, and retype the to p fo ur
list into the edito r. Then add the blue co de belo w:

Make sure yo u're using PHP then type the fo llo wing into Co deRunner:
<?php echo "Four characteristics of PHP:"; ?>

<ol>
<li> PHP is a server-side language with HTML embedding. </li>
<li> PHP is a parsed language. </li>
<li> PHP works hand-in-hand with SQL. </li>
<li> PHP is part of the LAMP stack. </li>
</ol>

Click Pre vie w. This time save with the php (.php) extensio n. It lo o ks exactly the same, right? But so mething
mo re happened this time o n the back end.

Yo u see, HTML is a Client side language. When yo u clicked Pre vie w while in HT ML, the Sandbo x simply
asked yo ur bro wser to pro cess the HTML tags witho ut any o utside help.

Co nversely, PHP is a server side scripting language and builds HTML dynamically befo re sending to yo ur
bro wser. Here's a diagram o f ho w PHP wo rks:

When yo u used Pre vie w after adding the PHP co de while using PHP syntax, the Learning Sandbo x:

To o k yo ur co de back to yo ur Lab Acco unt o n o ur web server


Parsed it using the PHP Engine that's installed within yo ur acco unt
Returned the results to the bro wser as HTML

Then yo ur bro wser rendered the HTML to make it lo o k pretty. Did yo u no tice ho w the additio n o f PHP co de at
the to p o f the file did no thing to change the HTML list belo w? This is because the HTML is embedded into the
PHP file, and do esn't require anything else to o utput it.

2. PHP is a Parsed language.


The fact that PHP is a parsed language as o ppo sed to a co mpiled language is a technical co ncern and
pro bably o nly interesting to pro grammers with experience in Compiled pro gramming languages like Java o r
C++. Tho se languages perfo rm an additio nal task called co mpiling that turns the text fro m the pro gram into a
fo rm the co mputer understands. A binary file is created that serves as the thing that gets executed when a
pro gram is running.

PHP is a Parse d language, meaning that yo u can see the results o f yo ur co de immediately after saving the
file, witho ut any co mpiling o r linking steps in between. That's because the co mpiled PHP engine installed o n
yo ur acco unt takes the PHP file yo u've created and "parses" it and uses the co mmands yo u created to make
the server do so mething. All the wo rk is still do ne by a co mpiled pro gram, but the pro gram yo u created
do esn't have to be co mpiled, since it just tells the co mpiled pro gram what to do .
Fo r the geeks o ut there, this is similar to an Int e rpre t e d language such as Perl; ho wever, the parsing
pro cess has been o ptimized to use a co mbinatio n o f interpreting and co mpiling at run-t im e , enabling PHP
to be po werful AND fast.

The bo tto m line is the parsing actio n o f PHP makes yo ur life easier. If yo u want to kno w mo re abo ut parsed,
interpreted, and co mpiled languages, here's a go o d link.

3. PHP works jointly with SQL.


Let's lo o k at yo ur first PHP script again and add o ne mo re little piece o f co de. Do n't wo rry yet abo ut what the
co de means, at this po int we're just playing aro und.

Type the fo llo wing (in BLUE) into Co deRunner:

<?php echo "Four facts about PHP:"; ?>


<ol style="font-size:16px;">
<li> PHP is a server-side language with HTML embedding. </li>
<li> PHP is a parsed language. </li>
<li> PHP works hand-in-hand with SQL. </li>
<? printf("MySQL client info: %s\n", mysqli_get_client_info()); ?>
<li> PHP is part of the LAMP stack. </li>
</ol>

Click Pre vie w. No w yo u sho uld see the versio n o f MySQL library that's included with yo ur acco unt's PHP
engine, embedded within yo ur HTML list. Yo u'll learn a lo t mo re abo ut the MySQL database in later co urses,
but fo r no w just ro ll with it.

PHP makes it easy to add database-driven co ntent to any website. It suppo rts po pular database systems -
MySQL, Po stgreSQL, Oracle, and o thers - with libraries o f built-in f unct io ns like the o ne yo u added abo ve.
These libraries can be referred to by the acro nym DBI: Database Interface.

Other pro gramming languages such as Perl co ntain their o wn sets o f DBI libraries to o . Ho wever, unlike Perl,
PHP was designed with database-driven websites in mind, and has beco me so clo sely intertwined with
MySQL that the two o rganizatio ns no w wo rk to gether to ensure co ntinued recipro cal suppo rt.

Here's a go o d O'Reilly article abo ut PHP and MySQL.

4. PHP is part of the LAMP, WAMP, and MAMP stack.


What's a (L|W|M)AMP St ack?

It's yet ano ther acro nym.

Linux, Windo ws, Mac


Apache
MySQL
PHP (o r Perl, o r bo th)

The St ack part refers to a gro up o f techno lo gies which, when used to gether, create po werful and dynamic
web applicatio ns. There are co mpeting stacks, such as Micro so ft's .NET framewo rk and Sun's Java/J2EE
techno lo gies. Ho wever, co rpo ratio ns are realizing mo re and mo re that the free, o pen-so urce LAMP Stack can
be just as po werful, safe, and lucrative fo r their businesses as the expensive, pro prietary co mpetito rs.

And by the way, lucky yo u! Yo u have all the LAMP techno lo gies yo u need at yo ur fingertips RIGHT NOW:

Yo ur Learning Lab acco unt is o n a Linux Re dHat server.


It's equipped with its o wn Apache web server.
The Apache server has MySQL installed o n it.
It also has PHP AND Pe rl o n it.

Alright, yo u're do ing great so far! Do n't fo rget to Save yo ur first PHP file (call it " f irst .php" ), and wo rk o n this lesso n's
assignments o n the syllabus page. Be sure to read the co mments o n each pro ject o r quiz using the "Graded" link. See yo u in
the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.


Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
PHP Basics
Welco me back! In the next three lesso ns, we'll be playing aro und with a make-believe pro gram to help demo nstrate a few
pro gramming co ncepts. While the faux-pro gram isn't o ne yo u'd likely create while o n the jo b, the co ncepts and techniques used
are the same. Let's get started!

PHP Delimiters and Comments


Open the file f irst .php. Or, if yo u're co mpletely sick o f the To p Fo ur list, start a new file. Make sure yo u're using PHP.

Type the fo llo wing green and blue co de into yo ur cho sen file in Co deRunner:
<ol style="font-size:16px;">
<li>
PHP is a server-side language, with HTML embedding.
</li><br/>
For instance:<br\>
<ul>
<?php
echo "<li style='color:blue;'>
This PHP code is INSIDE the PHP delimiters
</li>";
?>
<li style="color:green;">
This HTML code is OUTSIDE the PHP delimiters
</li>
</ul>
</ol>

No w click Pre vie w to see the results. What happened?

It sho uld lo o k so mething like this:

1. PHP is a server-side language, with HTML embedding.


For instance:
This PHP code is INSIDE the PHP delimiters.
This HTML code is OUTSIDE the PHP delimiters.

PHP co de is separated fro m embedded HT ML with de lim it e rs. The delimiters are the <?php and the ?>. All PHP is
written between these delimeters. An o pen delimiter <?php must have a clo sing delimiter ?>. Try taking the delimiters
away and see what happens.

Take a lo o k at the PHP - no tice that between the delimiters (<?php and ?>), the wo rd e cho sho wed up. That's a PHP
co mmand that means "make this sho w up." Witho ut echo , it wo n't sho w up. Remo ve the echo co mmand and check
o ut the results.

Here the e cho st at e m e nt is used to return text to the web bro wser fro m a PHP script. The "echo " co mmand just
means "print this o ut." And o ne mo re thing, all statements in PHP must end with a semico lo n (;).

By the way, why did we put in tho se slashes (//) in the sample co de abo ve? Well, tho se are called "co mments."
Co mmenting is a co mmo n practice in pro gramming. Co mmenting reco rds the specific reaso ns yo u had fo r writing the
pro gram a particular way.
Type the blue text belo w into Co deRunner:
<ol style="font-size:16px;">
<li> PHP is a server-side language, with HTML embedding.</li>
<br/> For instance: <ul>

<?php
//Jerry says, "What's the deal with this line of PHP code?"
/* Elaine says, "I want to talk about this line, that line, AND the other line!"
*/
#George says, "...yadda yadda yadda..."
echo "<li style='color:blue;'>
This PHP code is INSIDE the PHP delimiters
</li>";
?>
<li style="color:green;">
This HTML code is OUTSIDE the PHP delimiters
</li>
</ul>
</ol>

No w click Pre vie w to see the results. No tice what ISN'T printed o ut o n the screen. Our results lo o k exactly the same
as befo re.

What happened to the entire co nversatio n we added?

Ah, Jerry, Elaine, and Geo rge, always co mmenting o n everything, yet do ing pretty much no thing. In fact, they behave a
lo t like co m m e nt s in PHP, but in PHP, it's a develo per who co mments o n the co de witho ut impacting the results at all.

Two slashes (//) o r o ne po und sign (# ) will "co mment o ut" the line that fo llo ws it. Or, yo u can co mment
Note o ut multiple lines by surro unding them with /* and */. Play aro und a bit to get the hang o f it.

Co mments may no t seem like a big deal (they didn't to me at first either), but as o ur pro grams beco me mo re
co mplicated, it's useful to have reminders (in yo ur o wn wo rds) o f the specific reaso ns yo u cho se to write yo ur co de a
certain way. Also , co mments are essential fo r reusing and sharing co de. They allo w o ther develo pers to decipher and
understand the specifics o f the co de yo u've written.

Let's experiment to disco ver the answers to these questio ns:

Can de lim it e rs share the same line as the PHP co de?


Can they share the same line as HTML?
Can multiple st at e m e nt s share one line?
Can st at e m e nt s span multiple lines?
Do es it matter whether yo u use <?php o r just <? ?
Can yo u mix a line o f co de with a co mment?

Variables in PHP
Every pro gramming language has variable s. Variables are places to sto re things. Yo u can insert values into variables
and yo u can extract them. Variables are a lo t like dresser drawers. Yo u can put things in and then take them o ut, and
yo u usually kno w what each drawer co ntains.
Add the fo llo wing blue text to yo ur file in Co deRunner:
<ol style="font-size:16px;">
<li> PHP is part of the LAMP stack.</li>
<?php
$lamp_l = "Linux";
$lamp_a = "Apache";
$lamp_m = "MySQL";
$lamp_p = "PHP";
?>
</ol>

No w Preview that.

No t much happening, right? That's because we fo rgo t to echo so mething. Let's go ahead and do that so we get an
o utput.

Add the fo llo wing blue text to yo ur file in Co deRunner:


<ol style="font-size:16px;">
<li> PHP is part of the LAMP stack.</li>
<?php
$lamp_l = "Linux";
$lamp_a = "Apache";
$lamp_m = "MySQL";
$lamp_p = "PHP";
echo $lamp_a;
?>
</ol>

No w yo u sho uld see the wo rd Apache printed o n yo ur page. Why do yo u suppo se that is? After all, we wro te Echo
$ lam p_a;, yo u'd think that wo uld be the wo rd that printed. Well, as it turns o ut, $ lam p_a is a variable. Variables in PHP
always begin with a $ . And, as if $ lam p_a was a drawer, we put so mething in it, we inserted = " Apache " . Then, in
o rder to get so mething o ut o f the variable $ lam p_a, we "echo ed" by adding e cho $ lam p_a. Finally, "Apache," the
value we put into the variable (o r drawer) in the first place was printed o ut. They are called "variables" because the
value can vary. We can change the co ntents o f the variable at anytime, and that makes them very useful fo r sto ring and
retrieving values dynamically.

Just like yo u can put different items in the appro priate drawers o f yo ur dresser--yo u might have a so ck drawer fo r yo ur
so cks, a shirt drawer fo r yo ur shirts, etc.--yo u can put different kinds o f values in variables. In the example abo ve,
we've entered wo rds into o ur variables. In pro gramming, these wo rds are called st rings because they co mprise a
string o f letters o r characters.

Let's put different kinds o f values into so me o ther variables.

Add the fo llo wing blue text to yo ur file in Co deRunner:


<ol style="font-size:16px;">
<li> PHP is part of the LAMP stack.</li>
<?php
$lamp_l = "Linux"; $lamp_a = "Apache"; $lamp_m = "MySQL"; $lamp_p = "PHP";
?>
/* Here are some imaginary numbers for a possible salary package associated with the
skills we're learning in this course (play along!): */
<?php
$base_salary = 158470;
//whoa. we hit the jackpot
$bonus = 25815.25;
$benefits = 0.2;
//percentage of total
$time_off = 6476; //in dollars
?>
</ol>

Here we're assigning different kinds o f value s (like 15 84 7 0 ) to variable s. In this co ntext, assigning simply means to
"fill" the variable with a value.
We've assigned the vario us PHP variables values o f three basic t ype s: int e ge r, f lo at ing po int (de cim al), and
st ring. Integers are who le numbers, including negative numbers and 0 . Flo ating po int numbers are numbers that may
have a decimal po int. Strings, as we already mentio ned, are simply successive strings o f characters.

Belo w is a list o f the t ype s we've assigned to the variables listed:

Variable Nam e Assigne d Value Value T ype


$lamp_l "Linux" string
$lamp_a "Apache" string
$lamp_m "MySQL" string
$lamp_p "PHP" string
$base_salary 158 470 integer
$bo nus 258 15.25 flo at
$benefits 0 .2 flo at
$time_o ff 6 476 integer

Let's go back to o ur dresser analo gy fo r a mo ment. It will help us to understand the difference between "stro ngly typed"
pro gramming languages and languages like PHP, which are no t stro ngly typed. Pro gramming languages that are
strongly typed require yo u to decide the types o f variables yo u're go ing to have upo n creating yo ur files. Once yo u've
created yo ur variables, yo u are co mmitted. They canno t be revised. It's like labeling yo ur drawers, so that yo u can o nly
put so cks in yo ur so ck labeled drawer and shirts in yo ur shirt labeled drawer. And after yo u've labled these drawers,
yo u can't change them. PHP, ho wever, is no t stro ngly typed. Therefo re, the variables remain flexible, we are allo wed to
change them, and we can put any type o f info rmatio n into a PHP file that we wish.

Since PHP is NOT a st ro ngly t ype d pro gramming language, the fo llo wing wo n't break yo ur script:

Type the fo llo wing blue text belo w into Co deRunner:


<ol style="font-size:16px;">
<li> PHP is part of the LAMP stack. </li>
<?php
$lamp_l = "Linux";
$lamp_a = "Apache";
$lamp_m = "MySQL";
$lamp_p = "PHP";
?>
<?php
/* Here are some imaginary numbers for a possible salary package for the skills we'
re learning: */
$base_salary = 158470;
$bonus = 25815.25;
$benefits = 0.2;
//percentage of total
$time_off = 6476;
//in dollars
$benefits = "this is a string now"; // You just changed the value of $benefits from
a float number to a string!
?>
</ol>

Go ahead and Preview it. Our variables are shy creatures! So far they've been hiding like co mments when we
Pre vie w. Let's add so me HTML and echo o ut so me o f tho se variables.
Type the fo llo wing blue and green text into yo ur do cument in Co deRunner:

<ol style="font-size:16px;">
<li> PHP is part of the LAMP stack. </li>
<?php
$lamp_l = "Linux";
$lamp_a = "Apache";
$lamp_m = "MySQL";
$lamp_p = "PHP";
?>

<?php
/* Here are some imaginary numbers for a possible salary package for the skills we'
re learning: */
$base_salary = 158470;
$bonus = 25815.25;
$benefits = 0.2;
//percentage of total
$time_off = 6476;
//in dollars
$benefits = "this is a string now"; // You just changed the value of $benefits from
a float number to a string!
?>

<br/>
<ul>
<li> My Base Salary might be: <?php echo $base_salary; ?> </li>
<li> My Bonus might be: <?php echo $bonus; ?> </li>
<li> My Benefits might be: <?php echo $benefits; ?> </li>
<li> My Time Off might be worth: <?php echo $time_off; ?> </li>
</ul>
</ol>

Click Pre vie w. Tho se variables sho uld sho w up no w.

1. PHP is part of the LAMP stack.


My Base Salary might be: 158470
My Bonus might be: 25815.25
My Benefits might be: To be determined
My Time Off might be worth: 6476

There they are. Actually, instead o f displaying themselves, o ur variables displayed the value s they were ho lding.

By the way, they're no t just sneaky; they're picky to o . Turns o ut, variable nam e s may co nsist o f o nly le t t e rs,
num be rs, and t he unde rsco re (_) charact e r. No t just that, the first character o f the variable name CANNOT be a
number.

Here's a list o f valid and invalid variable names:

VALID variable names:

$ _var
$ he re s_a_nam e
$ t 1234 5
$x

INVALID variable names:

$ 1_var
$ he re 's-a-nam e
$ t +1234 5
$ x?

Modifying Variables and Values with Operators


Variables are no t useful unless they've been mo dified. Ope rat o rs can be used to mo dify variables and their values.
Operato rs are fairly simple to use, in fact, yo u've already learned o ne: the assignm e nt o perato r, represented by the
equal sign (=). The assignment o perato r is a quick, easy, and intuitive way to instruct a variable to ho ld a certain value.

But what if we want to change a variable's value?

Type the fo llo wing into Co deRunner:


<ol style="font-size:16px;">
<li> PHP is part of the LAMP stack. </li>
<?php
$lamp_l = "Linux";
$lamp_a = "Apache";
$lamp_m = "MySQL";
$lamp_p = "PHP";
?>
<?php
/* Here are some imaginary numbers for a possible salary package for the skills we'
re learning: */
$base_salary = 158470;
$bonus = 25815.25;
$benefits = 0.2;
//percentage of total
$time_off = 6476;
//in dollars
$benefits = "this is a string now"; // You just changed the value of $benefits from
a float number to a string!
?>
<br/>
<ul>
<li> My Base Salary might be: <?php echo $base_salary; ?> </li>
<li> My Bonus might be: <?php echo $bonus; ?> </li>
<li> My Benefits might be: <?php echo $benefits; ?> </li>
<li> My Time Off might be worth: <?php echo $time_off; ?> </li>
<li> My Base Salary plus Bonus would total: <?php echo $base_salary + $bonus; ?> </l
i>
</ul>
</ol>

Preview this co de. We added the values o f the variable's $base_salary and $bonus. Sweet.

1. PHP is part of the LAMP stack.


My Base Salary might be: 158470
My Bonus might be: 25815.25
My Benefits might be: To be determined
My Time Off might be worth: 6476
My Base Salary plus Bonus would total: 184285.25

The plus sign (+) is also an o pe rat o r. Mo re specifically, a binary o pe rat o r, since it takes two variables o r values (in
this case, called argum e nt s), perfo rms the additio n o peratio n o n them, and returns the result - just like tho se shy
variables do . In this case, we displayed the result thro ugh the "echo " statement.

Belo w is a list o f so me binary o perato rs, and so me examples o f them in actio n.

Assum ing $ i = 12 and $ j = 5 t he n...

Ope rat o r Nam e Usage Re sult


= assign $i = $j 5
+ add $i + $j 17
- subtract $i - $j 7
* multiply $i * $j 60
/ divide $i / $j 2.4
% mo d (remainder o f divisio n) $i % $j 2

Play aro und with these in yo ur pro gram and see what yo u get. Serio usly, practice! Try applying different o perato rs to
the example yo u've been wo rking o n in this lesso n, and echo o ut the results.

The o peratio ns (except fo r additio n) need to be executed in the o rder they appear, fro m left to right, to wo rk pro perly.

By the way, the o perato rs abo ve o nly o perate o n integers and flo ating po int number values. There are different
o perato rs that wo rk o n strings. Mo st specifically, the co ncat e nat io n o perato r. Here is an example using
co ncatenatio n. No tice the perio d in fro nt o f $lamp_l:

Type the fo llo wing into Co deRunner:


<ol style="font-size:16px;">
<li> PHP is part of the LAMP stack. </li>
<?php
$lamp_l = "Linux";
$lamp_a = "Apache";
$lamp_m = "MySQL";
$lamp_p = "PHP";
echo "<br />The stack begins with " . $lamp_l;
?>
<?php
/* Here are some imaginary numbers for a possible salary package for the skills we'
re learning: */
$base_salary = 158470;
$bonus = 25815.25;
$benefits = 0.2;
//percentage of total
$time_off = 6476;
//in dollars
$benefits = "this is a string now"; // You just changed the value of $benefits from
a float number to a string!
?>
<br/>
<ul>
<li> My Base Salary might be: <?php echo $base_salary; ?> </li>
<li> My Bonus might be: <?php echo $bonus; ?> </li>
<li> My Benefits might be: <?php echo $benefits; ?> </li>
<li> My Time Off might be worth: <?php echo $time_off; ?> </li>
<li> My Base Salary plus Bonus would total: <?php echo $base_salary + $bonus; ?> </
li>
</ul>
</ol>

Preview the co de and see what happens. After yo u Preview yo u sho uld see the fo llo wing sentence o n yo ur page:

T he st ack be gins wit h Linux.

Let's break it do wn. Ho w did this:

e cho " T he st ack be gins wit h " . $ lam p_l;

beco me this?:

T he st ack be gins wit h Linux.

Well, the first part in quo tatio n marks is a string and the $lamp_l is a variable ho lding the string "Linux". To "add" them
to gether, we use a perio d . which is the co ncatenatio n o perato r. Did yo u understand that? If no t lo o k again...
e cho " T he st ack be gins wit h " .$ lam p_l;

When used pro perly in PHP, suddenly that lo wly punctuatio n mark, the perio d (.), beco mes a po werful co ncatenatio n
to o l. Yes, the co ncatenatio n o perato r (.) is yet ano ther binary o pe rat o r in PHP, and an extremely useful o ne at that.

But the mo st useful characteristic o f these o perato rs is that they can be ne st e d. To nest o perato rs essentially means
we can use them to gether.

Type the fo llo wing blue co de (no tice the perio ds in red) into Co deRunner:
<ol style="font-size:16px;">
<li> PHP is part of the LAMP stack. </li>
<?php
$lamp_l = "Linux";
$lamp_a = "Apache";
$lamp_m = "MySQL";
$lamp_p = "PHP";
echo "<br />The stack begins with " . $lamp_l . " and goes on to include " . $lamp_
a . ", and " . $lamp_p . "!<br />";
?>
<?php
/* Here are some imaginary numbers for a possible salary package for the skills we'
re learning: */
$base_salary = 158470;
$bonus = 25815.25;
$benefits = 0.2;
//percentage of total
$time_off = 6476;
//in dollars
$benefits = "This is a string now."; // You just changed the value of $benefits fro
m a float number to a string!
$total = $base_salary + $bonus + $time_off;
$total_compensation = $total + ($total * 0.2); // Adding in benefits
?>
<br/>
<ul>
<li> My Base Salary might be: <?php echo $base_salary; ?> </li>
<li> My Bonus might be: <?php echo $bonus; ?> </li>
<li> My Benefits might be: <?php echo $benefits; ?> </li>
<li> My Time Off might be worth: <?php echo $time_off; ?> </li>
<li> My Base Salary plus Bonus would total: <?php echo $base_salary + $bonus; ?> </
li>
<li> My total compensation would be <?php echo $total . " without benefits, and " .
$total_compensation . " with benefits."; ?> </li>
</ul>
</ol>

In the co de abo ve there is o perato r nesting happening all o ver the place. Preview yo ur file. Yo u sho uld get so mething
like this:
1. PHP is part of the LAMP stack.
The stack begins with Linux, and goes on to include Apache, MySQL, and PHP!

My Base Salary might be: 158470


My Bonus might be: 25815.25
My Benefits might be: To be determined
My Time Off might be worth: 6476
My Base Salary plus Bonus would total: 184285.25
Your total compensation would be 190761.25 without benefits, and 228913.5 with
benefits.

It appears that o perato r nesting wo rked just fine. That's no t to say that o ur binary o perato rs started taking o n mo re
than two arguments. Instead, we've executed a successio n o f binary o peratio ns, with the o ne o peratio n taking the
results o f the last o peratio n into co nsideratio n.

Here are a co uple mo re things to co nsider:

Why do yo u suppo se the "co ncat" o perato r (.) had no pro blem mixing strings, flo ats, and integers?
Were the parentheses (()) necessary in the $to tal_co mpensatio n line?
What ro le do yo u think the parentheses play?

Finally, here are so me useful PHP "sho rtcut" o perato rs. These o perato rs reduce the need fo r nesting to execute so me
co mmo n tasks and they are really handy. Can yo u figure o ut which o perato rs are unary o pe rat o rs? (Hint: unary
o perato rs need o nly one argument.)

Play aro und with these and see what yo u get:

Ope rat o r Equivale nt


$i += $j $i = $i + $j
$i -= $j $i = $i - $j
$i *= $j $i = $i * $j
$i /= $j $i = $i / $j
$i++ $i = $i + 1
$i-- $i = $i - 1
$i .= $j $i = $i . $j

Superglobals
PHP has a set o f predefined variables to make o ur lives easier. Superglo bals can be accessed by classes, functio ns,
o r files at any time witho ut having to do anything special! Very nice. So , what are these Superglobals?

Befo re we delve to o deeply, let's get a small taste o f what's to co me. After all, we can't simply give o ut all the secrets in
the beginning. There wo uldn't be anything to lo o k fo rward to !

$GLOBALS
1. References all variables that are in the glo bal sco pe.
2. Asso ciative array.
3. Variable names are keys o f $GLOBALS array.
CODE TO TYPE: $GLOBALS example

<?php
function testScope() {
echo "The variable in the main code doesn't extend to within the function: $sc
ope<br>";

//assign a value to the variable named $scope that IS within function scope
$scope = "WITHIN FUNCTION";
echo "The local scope within the function: $scope<br>";

//the superglobal DOES extend within the function


echo "The global scope: {$GLOBALS['foo']}<br>";
}

//define $scope in the main code


$scope = "MAIN CODE";
echo "The local scope in the main code body: $scope<br>";

//define a global value (


$GLOBALS['foo'] = "SUPERGLOBAL";
echo "The value in the superglobal is {$GLOBALS['foo']}<br>";

//now run function, which has separate scope and $scope variable
testScope();

//show that main code's $scope is unaffected


echo "The local scope in the main code body: $scope<br>";
?>

$_SERVER:
1. Array co ntaining info rmatio n to Headers, Paths, and Script lo catio ns.
2. Entries generated by web server.

CODE TO TYPE: $_SERVER example


<?php
echo $_SERVER['SERVER_NAME'];
?>

$_GET
1. Asso ciative array.
2. Po pulated by URL parameters.
CODE TO TYPE: $_GET example
<form action="" method="get">
Enter your name: <input type="text" name="myname" placeholder="Tim O'Reilly"/>
<input type="submit" />
</form>
<?php
echo "Your name is: " . htmlspecialchars($_GET["myname"]);
?>

$_POST
1. Asso ciative array.
2. Array is passed via HTTP POST metho d.

CODE TO TYPE: $_POST example


<form action="" method="post">
Enter the next phrase: <input type="text" name="next_phrase" size="50" placehold
er="he played knick-knack on my door."/>
<input type="submit" />
</form>
<?php
echo "This old man, he played four, " . htmlspecialchars($_POST["next_phrase"])
;
?>

This is no t an exhaustive list o f PHP's Superglo bals; ho wever, click here fo r a full list with examples,
Note definitio ns, and a peek o f what's to co me!

Phew! We've co vered a lo t o f gro und. Do n't fo rget to Save yo ur wo rk, and hand in the assignments fro m yo ur syllabus. See yo u
at the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Decisions
In the last lesso n we learned that sto ring values in variables and manipulating them with o perato rs are amo ng the mo st
impo rtant to o ls we have fo r pro gramming in PHP. No w let's talk abo ut auto mating repetitive tasks and the decisio ns yo u'll
make based o n the values present in yo ur pro grams.

Comparison Operators and Conditions


We make co mpariso ns everyday. When we sho p, we lo o k at prices o f similar items to determine which deals are best.
When we take a trip, we co mpare alternative ro utes to decide which will be mo st expedient. Well, it turns o ut that we can
do co mpariso ns in PHP and o ther co mputer languages as well. Let's lo o k at this pro cess using a simple example.
Let's try a co mpariso n o f Capt ain Crunch breakfast cereal to Fro st e d Flake s breakfast cereal.

Suppo se Captain Crunch is 4 do llars a bo x, while Fro sted Flakes is 5 do llars. We can use PHP to figure o ut which
price is greater. (We realize yo u can determine this fairly easily witho ut PHP, but let's go ahead and wo rk the example
anyway so we can see ho w PHP wo rks.)

Add the fo llo wing BLUE and GREEN co de to yo ur file in Co deRunner:


<?php
$captain_crunch = 4;
$frosted_flakes = 5;
?>
Does Captain Crunch cost less than Frosted Flakes? <?php echo ($captain_crunch < $frost
ed_flakes); ?>
<br />
<br />
Or, is Captain Crunch priced greater than Frosted Flakes? <?php echo ($captain_crunch >
$frosted_flakes); ?>

Preview that. What was returned fro m the echo co mmand here?

In the the last lesso n we learned to mo dify variables using so me o f the standard o perato rs: add, subtract, co ncatenate,
and o thers. The co m pariso n o pe rat o rs we're using no w co mpare two variables, pro ducing TRUE o r FALSE results.

Fo r instance, the pro gram abo ve co mpares two integers to determine if o ne is larger than the o ther. ("<" is a symbo l
that means "less than," while ">" means "greater than").

This statement is TRUE:


4 < 5

We all kno w that 4 is less than 5.

This statement is FALSE:


4 > 5

So ho w did yo ur pro gram answer the questio n it was asked abo ut Captain Crunch and Fro sted Flakes?

Here's what yo u saw:

Does Captain Crunch cost less than Frosted Flakes? 1

Or, is Captain Crunch priced greater than Frosted Flakes?

Obvio usly, in o ur example, Captain Crunch is less (expensive) than Fro sted Flakes, but what's with the number o ne (1)
at the end there? Was that a typo ?
No , that wasn't a typo . Turns o ut, this is ho w PHP interprets the Bo o le an result "TRUE." (Bo o lean, by the way, is just a
fancy pro gramming wo rd referring to the results o f "true o r false" inquiries.) Similarly, instead o f returning "FALSE" o r
"no " when asked if Captain Crunch is greater than Fro sted Flakes, yo ur pro gram returned the NULL character. "Null" is
co mputer-speak fo r "no thing." When things are false, no thing gets returned, so no thing is printed.

Here's a table o f values that PHP can interpret as TRUE o r FALSE:

FALSE T RUE No t e s
0 (zero ) any no n-zero number no n-zero examples: 1, -1, 0 .5
false true no quo tes ("), o therwise it's just a string
NULL, null, '', o r "" any no n-null string The space (" ") character is NOT the same as the null ("") character

Here's a list o f co mpariso n o perato rs yo u can experiment with in yo ur pro gram:


Ope rat o r Nam e Usage Re sult
== Equal $a == $b TRUE if $a and $b are equal.
TRUE if $a and $b are equal AND if they are o f the same
=== Identical $a === $b
type (ie $a and $b are bo th integers).
!= $a != $b
No t equal TRUE if $a and $b are no t equal.
<> $a <> $b
TRUE if $a is no t equal to $b OR if $a and $b are no t o f
!== No t identical $a !== $b
the same type.
< Less than $a < $b TRUE if $a is less than $b.
> Greater than $a > $b TRUE if $a is greater than $b.
<= Less than o r equal to $a <= $b TRUE if $a is less than OR equal to $b.
>= Greater than o r equal to $a >= $b TRUE if $a is greater than OR equal to $b.

In PHP we use two equal signs (==) to test fo r equality. (When yo u use "==" yo u're essentially asking:
Are t he se value s e qual?). Two equal signs, like $a == $b, co mpare $a to $b (in English it wo uld read
Note "is $a equal to $b?"), whereas o ne equal sign $a = $b assigns $b to $a (in English it wo uld read "set $a
is equal to $b").

IF and ELSE Control Structure


Yo u may no t kno w it, but yo u actually already understand if and e lse co ntro l structures. Yo u use them everyday when
yo u decide things like " I'll buy Capt ain Crunch if it 's le ss e xpe nsive t han Fro st e d Flake s, o r e lse I'll buy
Fro st e d Flake s. Yo u've set co nditio ns and also decided o n an alternative co urse o f actio n sho uld tho se co nditio ns
fail to be met. In a pro gram, this is called a co ntro l structure.

In PHP, yo u wo uld write the sentence abo ve like this:

Type the fo llo wing into a new file in Co deRunner:


<?php $Captain_Crunch = 4; $Frosted_Flakes = 5; if ($Captain_Crunch
< $Frosted_Flakes) { echo "I'll buy Captain Crunch"; }
else { echo "I'll buy Frosted Flakes"; } ?>

Preview the co de abo ve. Which cereal do es PHP instruct yo u to buy? Try changing the numbers assigned to
$Captain_Crunch and $Fro sted_Flakes to see what happens.

if statements have a specific fo rm.

OBSERVE:
if (expression){
statement(s) executed if expression is TRUE } else {
(optional) statement(s) executed if expression IS FALSE
}
Again, this if statement is also referred to as a co nt ro l st at e m e nt . PHP first evaluates the e xpre ssio n to see if it is
true o r false. If the e xpre ssio n is true, then the statements in blue are executed. If no t, then the statements in BLUE
are no t executed, but the gre e n o nes are.

Logical Operators
Questio ns can be mo re co mplicated than statements. Fo r instance, if Captain Crunch is mo re (expensive) than
Fro sted Flakes, but Fruit Lo o ps are less (expensive) than Fro sted Flakes, we might want to cho o se Fruit Lo o ps. The
fo llo wing co de can handle these kinds o f co mplicatio ns:

Add the co lo red co de belo w into yo ur do cument in Co deRunner:


<?php $Captain_Crunch = 5; $Frosted_Flakes = 4;
$Fruit_Loops = 3;
if ($Captain_Crunch < $Frosted_Flakes) {
echo "I'll buy Captain Crunch";
} else if ($Captain_Crunch > $Frosted_Flakes && $Frosted_Flakes > $Fruit_Loops) {
echo "I'll buy Fruit Loops.";
} else { echo "I'll buy Frosted Flakes.";
}
?>

Preview this co de. Which cereal do es PHP reco mmend that yo u buy? Try changing the numbers representing the
prices and o bserve the results.

In this example, we've added a co uple o f things fo r yo ur co nsideratio n. First we added a lo gical o pe rat o r. We used
&& which simply means AND. The o ther additio n was the e lse if . We can have as many o f tho se within an if
statement as we need.

So no w the line reads:

OBSERVE:
else if ($Captain_Crunch > $Frosted_Flakes && $Frosted_Flakes > $Fruit_Loops) {
echo "I'll buy Fruit Loops.";

In English, the line reads:

OBSERVE:
"Or else if Captain Crunch is greater than Frosted Flakes,
AND
Frosted Flakes is greater than Froot Loops, then I'll buy Fruit Loops.

No tice that when Captain Crunch is 6 do llars and Fro sted Flakes is 5 do llars and Fruit Lo o ps is 4 do llars, t he n
$ Capt ain_Crunch > $ Fro st e d_Flake s is T RUE, and that $ Fro st e d_Flake s > $ Fruit _Lo o ps is T RUE. So the
who le thing is TRUE and so yo u'll buy Fruit Lo o ps!

Here are so me rules to remember abo ut lo gical o perato rs:

(T RUE AND T RUE) is T RUE


(T RUE AND FALSE) is FALSE
(T RUE OR FALSE) is T RUE
(FALSE OR FALSE) is FALSE

Like co mpariso n o perato rs, the lo gical o perato r perfo rms a co mpariso n o n two arguments, and returns a TRUE o r
FALSE (1 o r null) answer. Ho wever, the lo gical o perato r co mpares things that are already TRUE o r FALSE.

Belo w is a list o f lo gical o perato rs.

Ope rat o r Nam e Usage Re sult


AND $a AND $b
AND TRUE if $a and $b are TRUE.
AND TRUE if $a and $b are TRUE.
&& $a && $b
OR $a OR $b
OR TRUE if $a o r $b is TRUE.
|| $a || $b
XOR Exclusive OR $a XOR $b TRUE if $a OR $b is TRUE, but no t bo th.

Lo o k again at this co nditio n:


($Captain_Crunch >= 3 && $Frosted_Flakes < 10)

Remember that nested o perato rs perfo rm in a certain o rder, depending o n certain rules? There are rules here to o .
Specifically, the co mpariso n o perato rs are evaluated before the lo gical evaluato r. This way, the lo gical evaluato r o nly
needs to lo o k at the TRUE o r FALSE results, and act acco rdingly.

Like this:
(($Captain_Crunch >= 3) &&
($Frosted_Flakes < 10)) ((TRUE) &&
(TRUE)) (TRUE)

Ope rat o r ne st ing is really useful. And fo rtunately, yo u can do it with lo gical o perato rs to o .

Type the fo llo wing into Co deRunner:


<?php
$Captain_Crunch = 5;
$Frosted_Flakes = 4;
$Fruit_Loops = 5;
$Oatmeal = 2;
if ($Captain_Crunch < $Frosted_Flakes) {
echo "I'll buy Captain Crunch";
} else if ($Captain_Crunch > $Frosted_Flakes && $Frosted_Flakes > $Fruit_Loops) {
echo "I'll buy Fruit Loops.";
} else if ($Captain_Crunch > 4 && $Fruit_Loops > 4 && $Oatmeal < 4 ) {
echo "I'll get some Oatmeal.";
}
?>

Play with this o ne fo r a while—try entering different values fo r the different cereals. Be sure to Preview o ften to see what
happens.

NOT ICE: Befo re yo u mo ve o n, Save the PHP file yo u've been wo rking o n as co m pare .php.

A Brief Preview of Forms


Befo re we co ntinue o n with co ntro l structures, let's make these examples a little mo re interesting by getting
yo ur PHP pro gram to take input fro m a user o n the web. We're go ing to make a fo rm that will help us
understand these co ntro l structures better. This is a brief intro ductio n. We'll co ver fo rms in much mo re detail
later in the co urse.

So far in this lesso n, we've been changing the values in the variables $ Capt ain_Crunch,
$ Fro st e d_Flake s, $ Fruit _Lo o ps, and $ Oat m e al by hand. Typically tho ugh, co ntro l structures evaluate
changes made to variables and then react to tho se changes. If the user changes an input, we can acco unt fo r
all the po ssibilities thro ugh co ntro l structures.

To make o ur pro gram mo re interactive, we're go ing to make a web page with a few input fo rms we'll use to
submit values to o ur PHP pro gram. Then we're go ing to take tho se inputs and assign them to the variables
listed abo ve.

Let's make an HTML fo rm.


Make sure yo u're in HTML and type the fo llo wing into Co deRunner:
<body>
<h3>Choosing your Cereal</h3>
<form method="GET" action="compare.php"> Enter the price of Captain Crunch:
<input type="text" size="25" name="crunch_price" value="" />
<br /> Enter the price of Fruit Loops: <input type="text" size="25"
name="loops_price" value="" />
<br /> Cash in my wallet: <select name="cash_money">
<option value="">How much cash?</option>
<option value="1">$1.00</option>
<option value="2">$2.00</option>
<option value="3">$3.00</option>
<option value="4">$4.00</option>
<option value="5">$5.00</option>
<option value="10">$10.00</option>
</select>
<input type="submit" value="SUBMIT" />
</form>
</body>

No w Preview this in HTML. If yo u select an item and click submit, it wo n't do anything. Yo u sho uld see a page
that lo o ks like this:

Choosing your cereal

Enter the price of Captain Crunch:


Enter the price of Fruit Loops:

Cash in my wallet: How much cash do you have? SUBM IT

Save this page as use rinput .ht m l, o r anything yo u like, so lo ng as yo u can remember the name.

No w we've made a web page that will take input fro m a web user, and then send that input to the PHP pro gram
that we'll use to pro cess it. No w we just need to make o ur PHP pro gram retrieve the input. To do this, we have
to use so mething called a supe rglo bal array. No w that's a mo uthful! We'll actually study superglo bals in
detail in a later lesso n. Fo r no w let's just try it!

Switch back to PHP with the co m pare .php PHP pro gram we've been using, and make the fo llo wing
changes.

Type the changes in BLUE into Co deRunner:


<?php
$Captain_Crunch = $_GET["crunch_price"];
$Frosted_Flakes = 4;
$Fruit_Loops = $_GET["loops_price"];
$Oatmeal = 2;
$my_cash = $_GET["cash_money"];
$total = $Captain_Crunch + $Frosted_Flakes;
if ($total < $my_cash) {
echo "I'll buy both Captain Crunch and Frosted Flakes!";
} else if ($Captain_Crunch < $my_cash ) {
echo "I'll buy Captain Crunch.";
} else if ($Captain_Crunch > $my_cash && $Fruit_Loops < $my_cash ){
echo "I'll buy some Fruit Loops.";
} else {
echo "Forget it, I'm going home.";
}
?>

No w Save this PHP pro gram as co m pare .php, then go back to yo ur use rinput .ht m l file in HTML. Preview
it. Enter different prices fo r the two cereals, select the amo unt o f cash yo u have in yo ur wallet, then click
submit. No w yo ur pro gram sho uld change acco rding to the input yo u submitted in the fo rm. Co o l, huh?

We're just getting started with co nt ro l st ruct ure s, so be sure to save yo ur wo rk and hand in yo ur assignments. See yo u in the
next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Multiple Control Structures and Loops
Let's co ntinue o n fro m the last lesso n. Make sure yo u've o pened use rinput .ht m l in HT ML, and co m pare .php in PHP.
Ready? Let's go !

Multiple Control Structures


In the last lesso n we intro duced the e lse if statement, which allo ws us to wo rk with multiple co nditio ns.

Check o ut this else if statement:


<?
if ($total < $my_cash) {
echo "I'll buy both Captain Crunch and Frosted Flakes!";
}
else if ($Captain_Crunch < $my_cash ) {
echo "I'll buy Captain Crunch.";
}
else if ($Captain_Crunch > $my_cash && $Fruit_Loops < $my_cash ){
echo "I'll get some Fruit Loops.";
}
else {
echo "Forget it, I'm going home.";
}

?>

When the first if statement fails, PHP checks the e lse if statement befo re go ing o n to e lse . As lo ng as yo u begin with
an if and end with an e lse , (if yo u have a default actio n), yo u can add any number o f e lse if statements in the middle.
This way we can check and react to a lo t o f co nditio ns. Let's add so me co nditio ns to the example we wo rked o n last
lesso n.
Type the co de in blue into yo ur PHP pro gram in Co deRunner:

<?

$Captain_Crunch = 5;
$Frosted_Flakes = 4;
$Fruit_Loops = 3;
$Oatmeal = 2;
$my_cash = $_GET["cash_money"];

$total = $Captain_Crunch + $Frosted_Flakes;

if ($my_cash == 10) {
echo "I'll buy both Captain Crunch and Frosted Flakes!";
}
else if ($my_cash == 5 ){
echo "I'll buy Captain Crunch.";
}
else if ($my_cash == 4){
echo "I'll buy Frosted Flakes.";
}
else if ($my_cash == 3 ){
echo "I'll buy Fruit Loops.";
}
else if ($my_cash == 2){
echo "I'll buy Oatmeal.";
}
else {
echo "Forget it, I'm going home.";
}

?>

Save this co de using the filename co mpare.php, and o pen yo ur use rinput .ht m l file in HTML. Try entering so me
numbers fo r the amo unt o f mo ney yo u have and Preview it (the o ther variables are set in the pro gram, so the input fo r
tho se fields wo n't matter in this example).

Even tho ugh the abo ve co de wo rks just fine, the pro cedure co uld be streamlined by using a swit ch statement. The
switch co ntro l structure is similar to the if co ntro l structure, but it's especially useful when yo u have o ne variable with
many po ssible values. The switch co ntro l structure is a mo re efficient means o f acco mplishing the same task. It's up to
yo u decide which co ntro l structure yo u like better.

This is ho w we'd change o ur co de into a switch statement:

switch($my_cash) {
case "10":
echo "I'll buy both Captain Crunch and Frosted Flakes.";
break;
case "5":
echo "I'll buy Captain Crunch.";
break;
case "4":
echo "I'll buy Frosted Flakes.";
break;
case "3":
echo "I'll buy Fruit Loops.";
break;
case "2":
echo "I'll buy Oatmeal.";
break;
default:
echo "Forget it, I'm going home.";
}
Give it a try. Save the o ld file as new_file.php (do n't fo rget to make a new HTML file as well), then replace the blo ck o f
co de that co ntains the if statements with the switch statements abo ve. Use whichever metho d yo u prefer, it's yo ur call.

And o f co urse we want yo u to practice! Especially since we're go ing to assign this task as an o bjective later.

Befo re we go o n, experiment and find answers to these questio ns:

What happens when you nest comparison operators?


Would (null == 0) be TRUE or FALSE?
How about (null === 0)?
In an If statement, do you have to have parentheses (()) around the condition?

What about brackets ({})?


Hint: Try this with one action statement AND with two.
Can you put the whole if control structure in one line?
Do you always need to have an else statement?
When nesting logical operators, do you need parentheses?
What happens when you remove break; statements?

WHILE and FOR Loops


A lo o p is a repetitive task that go es o n while so mething is true o r for so me number o f steps. That's why they are
called "while" and "fo r" lo o ps.

A while lo o p has the fo llo wing structure:

while (something is t rue ) { do so m e st uf f } ;

As so o n as that so mething is false, the while lo o p sto ps.

Whereas a f o r lo o p has the fo llo wing structure:

f o r (so m e num be r o f st e ps) { do so m e st uf f } ;

Let's lo o k at an example. Type this into a new PHP file in Co deRunner:


<?

echo "Hide and go seek, I'm counting to 25:<br>";

$counts = 1;
while ($counts <= 25) {
echo $counts." Mississippi...<br>";
$counts++;
}

echo "Ready or not, here I come!<br>";

?>

In case yo u didn't play hide-and-seek in yo ur childho o d, this is ho w yo u'd co unt o ut lo ud while giving the o ther kids a
chance to hide. Such fun!

We have intro duced a new fo rm o f co ntro l structure - the WHILE lo o p. And like with any co ntro l structure, the WHILE
lo o p do es so mething in respo nse to a TRUE co nditio nal statement. In this case, ho wever, the lo o p co ntinues to
repeat the actio n until the co nditio nal statement is FALSE.

All lo o ps have f o ur e sse nt ial part s:

1. The init ial value st at e m e nt , in this case $ co unt s = 1;


2. The co ndit io nal st at e m e nt , in this case $ co unt s <= 25
3. The act io n st at e m e nt (s), in this case e cho $ co unt s." Mississippi...<br>" ;
4. The incre m e nt st at e m e nt , in this case $ co unt s++; (Remember this unary o pe rat o r?)

In o rder fo r a lo o p to wo rk, it has to have a starting po int, an ending po int, and so mething to do in between. What wo uld
happen if any o f the fo ur elements in o ur example were missing? Try messing with them, and yo u'll find o ut. (Go
ahead, try. I'll wait.)

Lo o ps fo llo w the same scheme as any co ntro l structure, in that yo u can ne st all kinds o f co nditio nal
Note statements and actio ns within them, including mo re lo o ps. This can be lo ts o f fun -- especially fo r duping
yo ur buddies into thinking the co mputer screen is po ssessed by gremlins!

Our counting lo o p example abo ve is a really co mmo n lo o p--so co mmo n, in fact, that almo st all pro gramming
languages have develo ped an alternate type o f lo o p that can be used as a sho rtcut: the FOR lo o p.

The FOR lo o p structure lo o ks like this:


for ($counts = 1; $counts <= 25; $counts++) {
echo $counts." Mississippi...<br>";
}

Try replacing yo ur WHILE lo o p with this FOR lo o p, then Preview the co de. Yo u sho uld see the exact same result. In
fact, the FOR lo o p has exactly the same fo ur elements as the WHILE lo o p. The o nly difference is the o rder o f the
elements in the syntax. Well, that, and if yo u fo rget the incre m e nt st at e m e nt in this o ne, PHP will yell at yo u. So unds
mean, but so metimes we need a little kick to keep fro m inadvertently causing an inf init e lo o p. Yuck.

Yo u may think that learning bo th WHILE lo o ps and FOR lo o ps in PHP is needless and redundant, and it's true that
mo st o f the time they are interchangeable. Ho wever, as yo ur scripts gain mo re co mplexity, yo u'll find that so me tasks
are a perfect fit fo r using FOR, while using WHILE is best fo r o thers.

Yo u've co me really far! No w yo u can pro gram the majo rity o f what yo u'll need in PHP. Co ngratulatio ns! Yo u are o ne o f the best
PHP pro grammers in the wo rld!

...Circa 19 9 5, that is. To create cutting-edge web so ftware fo r this century, we have a ways to go . Take heart—yo u've
acco mplished a lo t already. Save yo ur wo rk, and do n't fo rget the assignments. See yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Functions
A f unct io n acts like a small pro gram within yo ur larger pro gram. Yo u invo ke a functio n, send it info rmatio n, and get so mething
back. A great way to learn to use functio ns, is to create o ne and use it. Let's go !

Creating Code Reusability with Functions


Let's create a new pro gram so we can practice using functio ns. Our new pro gram will take user input just like o ur
previo us pro grams, o nly this time we'll inquire abo ut the user's state o f mind and reco mmend a mantra fo r them to
repeat.

Make sure yo u're in HTML syntax and type the fo llo wing into Co deRunner:
<body>

<h3>OST's Mantra generator</h3>

<form method="GET" action="mantra.php">

My current mood:
<select name="my_mood">
<option value="">Please choose...</option>
<option value="happy">I'm happy.</option>
<option value="sad">I'm sad.</option>
<option value="angry">I'm angry.</option>
<option value="indifferent">I'm indifferent.</option>
</select>

<input type="submit" value="SUBMIT" />

</form>

</body>

Save this HTML file as m o o dinput .ht m l


In PHP Mo de, type the fo llo wing co de highlighted in BLUE into Co deRunner:

<?
$my_mood = $_GET["my_mood"];

if ($my_mood == "happy") {

echo "Repeat the following: <br><br>";

for ($chant = 1; $chant <= 10; $chant++) {


echo " OM... ";
}

}
else if ($my_mood == "sad") {

echo "Repeat the following: <br><br>";

for ($chant = 1; $chant <= 10; $chant++) {


echo " okay... ";
}

}
else if ($my_mood == "angry") {

echo "Repeat the following: <br><br>";

for ($chant = 1; $chant <= 10; $chant++) {


echo " Mississippi... ";
}

}
else if ($my_mood == "indifferent") {

echo "Repeat the following: <br><br>";

for ($chant = 1; $chant <= 10; $chant++) {


echo " Wake up... ";
}

}
else {

echo "Repeat the following: <br><br>";

for ($chant = 1; $chant <= 10; $chant++) {


echo " Try harder... ";
}

?>

Save this co de as m ant ra.php and, o nce again, o pen up the HTML file mo o dinput.html.

Preview the HTML. Enter different values fo r yo ur mo o d (after all, we're all pretty mo o dy).

We have used pretty much the same PHP co de in several places. When yo u have the same co de o r similar co de in
lo ts o f different places, use a f unct io n. It will make yo ur pro gram mo re readable and save time. Say we decided to
reco mmend chanting o ur mantra 20 times instead o f 10 . Unless we used a functio n, we'd have to change the co de by
hand in each o f the "fo r" lo o ps. Even fo r a simple co de like o urs, that wo uld be truly anno ying. Yo u can imagine trying
to do this with lo ng and co mplicated co de--it co uld get do wnright ugly. Fo rtunately, f unct io ns enable us to avo id
such unpleasantness. We can create a functio n to execute a particular task each time we enter the name o f the functio n
into o ur pro gram. This is referred to as "calling" a functio n. Change yo ur pro gram so it lo o ks like the stuff belo w—be
sure to remo ve the "fo r" lo o ps within the "else if" statements.
Switch back to PHP and add the fo llo wing co de in BLUE into Co deRunner:
<?

function mantra($the_sound) {

for ($chant = 1; $chant <= 10; $chant++) {


echo $the_sound . "... ";
}
}

$my_mood = $_GET["my_mood"];

if ($my_mood == "happy") {

mantra("OM");

}
else if ($my_mood == "sad") {

mantra("okay");

}
else if ($my_mood == "angry") {

mantra("mississippi");

}
else if ($my_mood == "indifferent") {

mantra("Wake up");

}
else {

mantra("Try harder");

}
?>

Save this file as m ant ra.php and then switch back to yo ur m o o dinput .ht m l file. Try entering different mo o ds. Yo u
sho uld get the same results as befo re, but this time yo u used functio ns.

Each time the m ant ra(" so m e t hing" ) functio n is enco untered by PHP, it calls the functio n definitio n f unct io n
m ant ra($ t he _so und). The variable ($ t he _so und in this case) is set to whatever is in between the parentheses
when mantra("so mething") is enco untered. Fo r instance, m ant ra(" OM" ) is calling the f unct io n
m ant ra($ t he _so und) and setting $ t he _so und = " OM" . This is kno wn in functio ns as "setting a parameter." This
particular functio n takes o ne parameter: $the_so und. Ho wever, functio ns can take no parameters at all o r many
different parameters.

Much like a variable ho lds values, f unct io ns ho ld pro ce sse s (snippets o f co de) that we want to reuse. So instead o f
having to add the same co de o ver and o ver again, we can simply call the f unct io n. In this case, when m ant ra() is
enco untered, the co de inside o f the brackets { and } in the definitio n f unct io n m ant ra(){ } is executed. Functio ns will
o nly be executed when they are called. Try remo ving the calls to mantra(). Yo u'll see that the functio n do esn't do
anything then.

If the functio n yo u've created do esn't have any parameters, yo u still need to have the parentheses in
place, they just wo n't co ntain anything. No tice ho w no do llar signs ($ ) are used in the functio n name
Note m ant ra, but instead we fo llo w the name with parentheses(()). They need to be there, that's just the way it
is.

Co ngratulatio ns—yo u've just wo rked thro ugh yo ur first example o f co de re usabilit y!

Function and Variable Scopes


Sco pe refers to a variable's area o f influence. If a variable is defined inside o f a functio n, then its area o f influence is
o nly within that functio n. That means we can use that variable name again in ano ther functio n--setting values to it in
o ne functio n wo n't affect the setting in ano ther functio n. Let's try using a functio n to encapsulate tho se "if" statements in
o ur example fro m the last sectio n. In the pro cess, we can see ho w sco pe may affect the o utco me o f o ur pro gram.

Revise yo ur PHP pro gram so it lo o ks like this in Co deRunner:


<?

function mantra($the_sound) {

for ($chant = 1; $chant <= 10; $chant++) {


echo $the_sound . "... ";
}

function Mood_Chant(){

if ($my_mood == "happy") {

mantra("OM");

}
else if ($my_mood == "sad") {

mantra("okay");

}
else if ($my_mood == "angry") {

mantra("mississippi");

}
else if ($my_mood == "indifferent") {

mantra("Wake up");

}
else {

mantra("Try harder");

$my_mood = $_GET["my_mood"];

Mood_Chant();

?>

Save this as m ant ra.php, then o pen yo ur m o o dinput .ht m l file. Try altering ANY o f the mo o ds o n the list. No matter
what yo u cho o se, this co de will always return T ry Harde r as the o utput.

So why is the pro gram returning T ry Harde r as a result, no matter what we select? Let's perfo rm so me diagno stic
tests to find o ut. We'll enter so me echo statements to print o ut variable values in different parts o f o ur pro gram. Then
we can use the info rmatio n we get to determine the path o ur pro gram is taking and the steps we need to take to co rrect
o ur pro blem. Let's try it.
Add so me echo statements into Co deRunner:
<?
function mantra($the_sound) {

for ($chant = 1; $chant <= 10; $chant++) {


echo $the_sound . "... ";
}

function Mood_Chant(){

echo "INSIDE the Mood_Chant function, your mood is ".$my_mood.".<br>";

if ($my_mood == "happy") {

mantra("OM");

}
else if ($my_mood == "sad") {

mantra("okay");

}
else if ($my_mood == "angry") {

mantra("mississippi");

}
else if ($my_mood == "indifferent") {

mantra("Wake up");

}
else {

mantra("Try harder");

$my_mood = $_GET["my_mood"];

echo "OUTSIDE the Mood_Chant function, your mood is ".$my_mood.".<br>";

Mood_Chant();

?>

Once again, Save this as m ant ra.php, then go back to yo ur m o o dinput .ht m l page. Select angry fro m the dro p
do wn list and submit it.

Yo u sho uld get so mething like this:


OUTSIDE the Mood_Chant function, your mood is angry.
INSIDE the Mood_Chant function, your mood is .
Try Harder...Try Harder...Try Harder...Try Harder...Try Harder...Try Harder...Try Harder...Try Harder...Try
Harder...Try Harder...

Lo o k clo sely. What printed o ut? What didn't? The first result printed o ut OUT SIDE t he Mo o d_Chant f unct io n, yo ur
m o o d is angry. We asked PHP to print it with the statement e cho " OUT SIDE t he Mo o d_Chant f unct io n, yo ur
m o o d is " .$ m y_m o o d." ." ;. So as expected, the variable $my_mood was defined as angry. Ho wever, the seco nd
result printed INSIDE t he Mo o d_Chant f unct io n, yo ur m o o d is . Even tho ugh we asked PHP to print e cho
" INSIDE t he Mo o d_Chant f unct io n, yo ur m o o d is " .$ m y_m o o d." ." ; , it didn't print a value fo r $my_mo o d.
" INSIDE t he Mo o d_Chant f unct io n, yo ur m o o d is " .$ m y_m o o d." ." ; , it didn't print a value fo r $my_mo o d.

In the abo ve example, yo u wo uld think the value o f $ m y_m o o d (" angry" ) wo uld print bo th inside and o utside o f the
functio n Mo o d_Chant (). But, o nce the functio n was called, the value $ m y_m o o d wasn't seen INSIDE o f the
Mo o d_Chant() functio n at all. This is because the variable $ m y_m o o d is co mpletely different depending o n whether it
is lo cated o utside o r inside o f the functio n. Altho ugh variables may share the same name, their lo catio n determines
their effect o n the pro gram. When a variable within a functio n is encapsulated, as if the functio n was its o wn pro gram,
this is referred to in pro gramming as the functio n's sco pe .

In the next sectio n, we'll learn to set parameters so that sco pe do esn't prevent us fro m using functio ns to the fullest.

PHP isn't as strict with sco pe as so me o ther languages are. Since PHP isn't stro ngly typed, yo u're no t
required to de clare variables befo re yo u use them. Therefo re, within a PHP functio n, a variable declared
Note within a lo o p will retain its value o utside o f that lo o p. To see this co ncept at wo rk, try using e cho to
o utput $ chant after the f o r lo o p is finished in m ant ra().)

Using Functions with Parameters and Return Values


As interesting as sco pe can be, it do esn't help lighten yo ur wo rk lo ad. What's the use o f reusing yo ur co de in a
functio n, if yo u have to re-define $ m y_m o o d within the functio n? Wo rse, what if yo u want to have different values fo r
$ m y_m o o d anytime yo u use the functio n Mo o d_Chant ()? We co uld save o urselves a lo t o f wo rk if we co uld feed
o ur functio n different values and get an o utput each time. We already did this in the first sectio n abo ve using
param e t e rs.

Sneaking In with Parameters


Type the fo llo wing into Co deRunner:
<?

function mantra($the_sound) {

for ($chant = 1; $chant <= 10; $chant++) {


echo $the_sound . "... ";
}

function Mood_Chant($my_mood){

echo "INSIDE the Mood_Chant function, your mood is ".$my_mood.".<br>";

if ($my_mood == "happy") {

mantra("OM");

}
else if ($my_mood == "sad") {

mantra("okay");

}
else if ($my_mood == "angry") {

mantra("mississippi");

}
else if ($my_mood == "indifferent") {

mantra("Wake up");

}
else {

mantra("Try harder");

$my_mood = $_GET["my_mood"];

echo "OUTSIDE the Mood_Chant function, your mood is ".$my_mood.".<br>";


Mood_Chant($my_mood);

?>

Save this as m ant ra.php, o pen m o o dinput .ht m l, and select angry fro m the dro p-do wn list. This time, yo u
sho uld have go tten the results yo u expected.
Lo o k at yo ur functio n again:
function Mood_Chant($my_mood) {

//code that processes the value of $my_mood

.
.
.

//passing the value of $my_mood UP to the Mood_Chant function above


Mood_Chant($my_mood);

Passing a param e t e r essentially drills thro ugh the wall o f yo ur functio n's sco pe, making it a mo re useful
machine.

Whatever param e t e r we call to Mo o d_Chant (param e t e r); beco mes the value fo r $ m y_m o o d. And yo u
do n't even have to use the name $ m y_m o o d, since it's a co mpletely different variable within the functio n and
o utside the functio n. Try using this o n yo ur o wn.

Lo o k at yo ur functio n again:
function Mood_Chant($my_mood) {

//code that processes the value of $my_mood


}

.
.
.

//passing the value of $my_mood up to the Mood_Chant function above


Mood_Chant("happy");

The value o f $ m y_m o o d inside o f the functio n Mo o d_Chant($my_mo o d) is " happy" . It's like setting
$my_mood = "happy" INSIDE o f the functio n.

No w that we've snuck in with parameters, let's sneak out with return values.

Sneaking out with Return Values


In the examples abo ve, we saw that we can sneak into a functio n using parameters. We can also sneak o ut
using re t urn values. The best way to understand "return" is to use it. Let's get to it.
Type the fo llo wing into Co deRunner:
<?

function mantra($the_sound) {

for ($chant = 1; $chant <= 10; $chant++) {


echo $the_sound . "... ";
}

function Mood_Chant($my_mood){

if ($my_mood == "happy") {

mantra("OM");
$after_chant = "<br>I feel serene now.";

}
else if ($my_mood == "sad") {

mantra("okay");
$after_chant = "<br>I feel better now.";

}
else if ($my_mood == "angry") {

mantra("mississippi");
$after_chant = "<br>I've calmed down now.";

}
else if ($my_mood == "indifferent") {

mantra("Wake up");
$after_chant = "<br>I'm awake now.";

}
else {

mantra("Try harder");
$after_chant = "<br>I'll try harder now.";

return $after_chant;
}

$my_mood = $_GET["my_mood"];

$after_chant_mood = Mood_Chant($my_mood);

echo $after_chant_mood;

?>

Save this as m ant ra.php, o pen up m o o dinput .ht m l, and select anything yo u like fro m the dro p do wn list.
No w yo u sho uld get the chant and at the end yo u sho uld have an "after-chant mo o d" expressed. All we did
here was add so me statements into the variable $after_chant and then use re t urn $ af t e rchant at the end o f
the functio n. When we use return, we are setting a value in place o f the functio n.

But instead o f just letting a parameter sneak in, yo u've allo wed a re t urn value to sneak out o f the functio n
sco pe. Suddenly, yo ur functio n is an efficient facto ry, taking in raw ingredients (parameters) and spitting o ut a
refined pro duct -- that is, it returned a value. Allo wing a return value to sneak o ut o f the functio n sco pe is used
o ften in pro gramming to return true o r false values in functio ns that perfo rm tests.

Multiple Parameters and Default Values


We practiced using parameters earlier in the lesso n and no w we can pass parameters to a functio n. Let's
change o ur functio n so that the end user can set ho w many times we chant o ur mantra.

Type the fo llo wing co de into yo ur mo o dinput.html file in Co deRunner:

<body>

<h3>OST's Mantra generator</h3>

<form method="GET" action="mantra.php">

My current mood:
<select name="my_mood">
<option value="">Please choose...</option>
<option value="happy">I'm happy.</option>
<option value="sad">I'm sad.</option>
<option value="angry">I'm angry.</option>
<option value="indifferent">I'm indifferent.</option>
</select>

Pick a number:
<select name="my_number">
<option value="2">Please choose...</option>
<option value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="40">40</option>
</select>

<input type="submit" value="SUBMIT" />

</form>
</body>

Save this as m o o dinput .ht m l again. We've added the o ptio n o f selecting a number, so let's change o ur
pro gram to accept this info rmatio n and pro cess it.
Type the fo llo wing in yo ur PHP file in Co deRunner:
<?

function mantra($the_sound,$the_number = 10) {

for ($chant = 1; $chant <= $the_number; $chant++) {


echo $the_sound . "... ";
}

function Mood_Chant($my_mood, $chant_number = 10){

if ($my_mood == "happy") {

mantra("OM",$chant_number);
$after_chant = "<br>I feel serene now.";

}
else if ($my_mood == "sad") {

mantra("okay",$chant_number);
$after_chant = "<br>I feel better now.";

}
else if ($my_mood == "angry") {

mantra("mississippi",$chant_number);
$after_chant = "<br>I've calmed down now.";

}
else if ($my_mood == "indifferent") {

mantra("Wake up",$chant_number);
$after_chant = "<br>I'm awake now.";

}
else {

mantra("Try harder",$chant_number);
$after_chant = "<br>I'll try harder now.";

return $after_chant;
}

$my_mood = $_GET["my_mood"];
$chant_number = $_GET["my_number"];

$after_chant_mood = Mood_Chant($my_mood, $chant_number);

echo $after_chant_mood;

?>

Save this as m ant ra.php, o pen m o o dinput .ht m l, and Preview.

In this pro gram we let the user select a number. Then inside o f the mo o d_chant functio n we call Mantra(first
parameter, seco nd paramter) where the seco nd parameter is the number the end user cho se o n the fo rm in
the first place. No tice we changed the functio n Mantra() to accept two parameters.

By adding a de f ault value to the parameter $ t he _num be r, yo u made that parameter co mpletely optional
when yo u call Mant ra. To see this in actio n, try changing the pro gram so that o ne o f the calls to Mantra() has
o nly o ne parameter being set.
Yo u can have as many parameters and default values as yo u want in a functio n. But yo u have to
Note make sure that the default-valued parameters are at the end o f the parameter list. Any idea why?
Experiment to find o ut!

Be sure to save yo ur wo rk and hand in yo ur assignments. See yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Arrays
Have yo u ever used o ne o f tho se weekly pill co ntainers? Yo u kno w, the o nes that keep yo ur vitamins o r medicine o rganized fo r
each day? Surely yo u've at least seen o ne:

This is an excellent representatio n o f this entire lesso n—that bo x is just an array o f co ntainers with o bjects in them. Let's get
started with a fresh file and take a breather fro m the mo nster we've created.

Creating an Array
Open a new PHP file and type this co de into Co deRunner:

<?php

$names = array("scott","kendell","Trish","Tony","Mike","Debra","Curt");

echo "<pre>";
print_r($names);
echo "</pre>";

?>

Save and preview the file:

Array
(
[0] => scott
[1] => kendell
[2] => Trish
[3] => Tony
[4] => Mike
[5] => Debra
[6] => Curt
)

Yo u've just defined an array named nam e s, by passing the seven names as parameters to the built-in PHP array()
co nstruct. If yo u think in terms o f the pill bo x abo ve—a huge, peo ple-sized pill bo x—it wo uld lo o k like this:

No w, the great thing abo ut arrays is that yo u can access and mess with any o ne o f the e le m e nt s—names, pills,
whatever values are in the bo xes—by using the array keys. Let's give Mike a call:
Type the fo llo wing into Co deRunner:
<?php

$names = array("scott","kendell","Trish","Tony","Mike","Debra","Curt");

echo "Who is it? ...".$names[4]."<br/>";

echo "<pre>";
print_r($names);
echo "</pre>";

?>

Preview this. Did yo u see Mike's name? All yo u did here is retrieve the value o f the array e le m e nt at the 4th po sitio n,
o r inde x. In this case, yo u used the index 4 as the ke y. Fo r kicks, let's replace Mike:

Type the fo llo wing into Co deRunner:


<?php

$names = array("scott","kendell","Trish","Tony","Mike","Debra","Curt");

echo $names[4];

$names[4] = "Josh";
echo "Who is it? ...".$names[4]."<br/>";

echo "<pre>";
print_r($names);
echo "</pre>";

?>

See, this is why we lo ve arrays. No sco pe to co ntend with, just a simple o rganizatio n o f values that we can mess with
at will. So no w the $ nam e s array lo o ks like this:

No tice the new, super-handy, built-in functio n called print _r, which prints o ut an array in a really nice,
Note readable fo rmat. With a little experimentatio n, yo u can figure o ut why we used the <pre> and </pre> tags,
to o . Yo u can find o ut mo re abo ut this functio n at php.net.

Associative Arrays
If we wanted to represent the pill bo x in PHP, it wo uld make sense to use the labels that already exist to mark each bo x
fo r o ur purpo ses as well. Here's o ne way to do it:
Type the fo llo wing into Co deRunner:
<?php

$weekly_pills = array("S" => "vitamin C",


"M" => "Echinacea",
"T" => "antibiotic",
"W" => "calcium",
"Th" => "zinc",
"F" => "multivitamin",
"Sa" => "alka seltzer");

echo "<pre>";
print_r($weekly_pills);
echo "</pre>";

?>

Save it as pills.php and preview:

Array
(
[S] => vitamin C
[M] => Echinacea
[T] => antibiotic
[W] => calcium
[Th] => zinc
[F] => multivitamin
[Sa] => alka seltzer
)

Yo u've just defined an associative array. By using the => o perato r, yo u've associated each array element value to its
o wn index, o r key, so that yo u can access it mo re intuitively. In o ther wo rds, an asso ciative array is a way o f naming
each slo t o f the array. In this case, the slo ts are named S,M, T , W, T h, F, and Sa, respectively. So no w we can sto re
and access values in an array based o n these names instead o f using indices. Experiment with this:
Type the fo llo wing into Co deRunner:
<?php

$weekly_pills = array("S" => "vitamin C",


"M" => "Echinacea",
"T" => "antibiotic",
"W" => "calcium",
"Th" => "zinc",
"F" => "multivitamin",
"Sa" => "alka seltzer");

echo "<pre>";
print_r($weekly_pills);
echo "</pre>";

//assign a new pill to Thursday


$weekly_pills["Th"] = 'aspirin';

//Does Thursday correspond to index 4? Let's see...


$weekly_pills[4] = 'garlic';

//Let's be lazy and see what happens...


$weekly_pills[] = 'glucose';

echo "<pre>";
print_r($weekly_pills);
echo "</pre>";

?>

Save and preview this:

Array
(
[S] => vitamin C
[M] => Echinacea
[T] => antibiotic
[W] => calcium
[Th] => zinc
[F] => multivitamin
[Sa] => alka seltzer
)

Array
(
[S] => vitamin C
[M] => Echinacea
[T] => antibiotic
[W] => calcium
[Th] => aspirin
[F] => multivitamin
[Sa] => alka seltzer
[4] => garlic
[5] => glucose
)

By the way, all arrays in PHP are asso ciative. Every array value is assigned to a key index, regardless o f whether we
defined it. When yo u don't define a key index fo r an element value, PHP auto matically assigns a default index to that
value fo r yo u. Specifically, it assigns the next increment after the highest integer index used. That's why 'gluco se' was
assigned to the index 5 —we'd already used 4 .
Type the fo llo wing into Co deRunner:

<?php

$months_of_the_year = array(1 => "January", "February", 4 => "April", 3 => "March",


"May", "June", "July", "August", "September", 12 => "Decemb
er",
10 => "October", 11 => "November");

echo "<pre>";
print_r($months_of_the_year);
echo "</pre>";

?>

Save it as m o nt hs.php and preview it. Play aro und with it. Beco me o ne with array elements and keys. Oh, and do n't
fo rget to study yo ur bo o k o r php.net fo r mo re fun examples.

Creating Multi-Dimensional Arrays


A multi-dimensio nal array is simply an array o f arrays. That is, we can put arrays in fo r the values o f an array which
wo uld be a two-dimensional array. A three-dimensio nal array wo uld be an array o f arrays o f arrays. Ah, nesting. One o f
PHP's little jo ys. Let's mo dify o ur pills.php to see ho w it wo rks.

Type the fo llo wing into Co deRunner:


<?php

$weekly_pills = array("S" => array("8am" => "vitamin C",


"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"),
"M" => array("8am" => "vitamin C",
"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"),
"T" => array("8am" => "vitamin C",
"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"),
"W" => array("8am" => "vitamin C",
"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"),
"Th" => array("8am" => "vitamin C",
"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"),
"F" => array("8am" => "vitamin C",
"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"),
"Sa" => array("8am" => "vitamin C",
"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"));

echo "<pre>";
print_r($weekly_pills);
echo "</pre>";

echo "What pill should I pop right now? ...".$weekly_pills["Th"]["6pm"];

?>
Save and preview this co de. Wo w. That's a lo t o f pills! But it seems that there are eno ugh peo ple taking eno ugh pills
that a co ntainer indeed exists that represents this matrix o f do sages:

Creating a multi-dimensional array is as simple as nesting the array() co nstruct to yo ur heart's co ntent, to create useful
representatio ns o f just abo ut anything.

T raversing and Manipulating Arrays


Let's have so me fun and send a sho ut-o ut to everyo ne in the $ nam e s array. Mo dify array.php as sho wn

We're feeling friendly. Type the fo llo wing into Co deRunner:


<?php

$names = array("scott","kendell","Trish","Tony","Mike","Debra","Curt");

echo "There are ".count($names)." names in the \$names array.<br/>";


for ($i = 0; $i < count($names); $i++) {
echo "Dialing index ".$i."...";
echo "Hey there, ".$names[$i]."!!<br/>";
}

?>

Yet ano ther excellent built-in PHP functio n is co unt (). We're sure yo u can guess what it do es, but we still
Note enco urage yo u to check it o ut at php.net.

Preview this co de and feel the lo ve:

There are 7 names in the $names array.


Dialing index 0...Hey there, scott!!
Dialing index 1...Hey there, kendell!!
Dialing index 2...Hey there, Trish!!
Dialing index 3...Hey there, Tony!!
Dialing index 4...Hey there, Mike!!
Dialing index 5...Hey there, Debra!!
Dialing index 6...Hey there, Curt!!

Just by being friendly, yo u've traversed an array. Traversing simply requires that yo u ho psco tch thro ugh all the
elements o f yo ur array and do so mething with each value. "Fo r" and "while" lo o ps are great fo r that, especially when
yo u use numerical indices.

T raversing Associative Arrays with list() and each()


Here's o ne guarantee: yo u're go ing to use arrays a lot. Yo u can create, access, traverse, and manipulate
arrays fairly easily IF yo u kno w exactly what is go ing into them, how many elements they have, and how deep
the nesting go es in every case. But mo st o f the time, yo u wo n't kno w all that. Yo u'll need to wo rk aro und any
gaps with so me nifty pro gramming o r so me great built-in PHP array functio ns, like co unt ().

Fo r instance, ho w wo uld yo u traverse the asso ciative $ we e kly_pills array? Using numerical co unters wo n't
help. But do n't wo rry, yo u have o ptio ns. Here's o ur reco mmended way to do it:

Type the fo llo wing into Co deRunner:


<?php

$weekly_pills = array("Sunday" => array("8am" => "vitamin C",


"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"),
"Monday" => array("8am" => "vitamin C",
"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"),
"Tuesday" => array("8am" => "vitamin C",
"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"),
"Wednesday" => array("8am" => "vitamin C",
"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"),
"Thursday" => array("8am" => "vitamin C",
"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"),
"Friday" => array("8am" => "vitamin C",
"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"),
"Saturday" => array("8am" => "vitamin C",
"1pm" => "antibiotic",
"6pm" => "zinc",
"11pm" => "alka seltzer"));

while (list($key, $value) = each($weekly_pills)) {


echo "Here's what you should take on ".$key.":<br/>";

echo "<pre>";
print_r($value);
echo "</pre>";
}

?>

Save and preview it:

Here's what you should take on Sunday:


Array
(
[8am] => vitamin C
[1pm] => antibiotic
[6pm] => zinc
[11pm] => alka seltzer
)

Ho w did yo u get all that o utput? Well, there are two built-in functio ns wo rking to gether here.
Let's break it do wn:

while (list($key, $value) = each($weekly_pills)) {


echo "Here's what you should take on ".$key.":<br/>";
.
.
.
}

list () is no t really co nsidered a function, but a language construct, because it do esn't fo llo w the no rmal
"Parameter in/Return value o ut" functio n rule. list () is simply a sho rtcut which, when used with the
assignment o perato r (=) and an array, assigns each value o f that array to the parameter variables within
list ().

In o ther wo rds, this:


list($parameter1, $parameter2, $parameter3) = array("value1", "value2", "value3"
);

...is the same as this:


$parameter1 = "value1";
$parameter2 = "value2";
$parameter3 = "value3";

No w let's go o n to e ach(), which may be even trickier than list (). Trickier, because it intro duces an aspect o f
arrays that we haven't discussed until no w: the array cursor.

Take a lo o k at the graphical representatio n o f $ nam e s again:

No w, take yo ur mo use curso r and point to each bo x, o ne by o ne, starting with the first entry. Yo u've just
demo nstrated the way an array curso r wo rks: it points to array elements. The array curso r always begins by
po inting to an array's first element, and stays where it is until mo ved by a built-in PHP functio n.

Here's where e ach() co mes in:

Type the fo llo wing into Co deRunner:


<?
$test_array = array("key1" => "value1",
"key2" => "value2",
"key3" => "value3");

//start with the beginning


$new_array1 = each($test_array);

echo "<pre>";
print_r($new_array1);
echo "</pre>";

?>

Save it as e ach.php and preview it:


Array
(
[1] => value1
[value] => value1
[0] => key1
[key] => key1
)

As yo u may have guessed, e ach() takes an array as its parameter. But what yo u may not have guessed is
that it also has an array as its return value. Only the array returned is different fro m the array passed in.

e ach() uses the array curso r to access the element currently being po inted to by that curso r. This is called the
current element. In o ur abo ve example, the current element is the first element o f $ t e st _array. After
accessing the element, e ach() creates a new array with fo ur elements—using the key and value fro m the
current element o f the parameter array—and returns that array. In o ur example, we assigned that array to
$ ne w_array1. Finally, e ach() increments the array curso r so it po ints to the next element in the array.

Why fo ur elements in the return array? So that the new array can be accessed bo th numerically AND
asso ciatively. The ke y o f the parameter array's current element beco mes the value fo r two o f the new array's
elements, accessed by the keys 0 and " ke y" . The value o f the parameter array's current element beco mes
the value fo r the o ther two elements o f the new array, accessed by the keys 1 and " value " .

Since list () can o nly deal with numerical keys (it igno res asso ciative keys), the fo ur-element return array is
especially handy.

Let's put it all to gether:

while (list($key, $value) = each($weekly_pills)) {


echo "Here's what you should take on ".$key.":<br/>";
.
.
.
}

In this example, the "while" lo o p is mo nito ring the curso r o f o ur $ we e kly_pills array. We can trust that the
lo o p wo n't be infinite because o f e ach(). The array curso r will eventually reach the end o f the array and po int
to null, but each time it lo o ps, the current element's key (in this case, the day o f the week) wo uld be assigned
to the variable $ ke y. Similarly, the current element's value (in this case, ano ther array co ntaining that day's
pills) wo uld be assigned to the variable $ value .

Yikes! That's no t just tricky, that's do wnright eye-cro ssing. When yo u do get the hang o f it tho ugh, this little
PHP co nco ctio n will serve yo u well, no t o nly with arrays, but with SQL co mmands and lo ts o f o ther
pro gramming.

As an alternative to using list() and each() inside the co nditio n o f a while lo o p, check o ut
Note fo reach() lo o ps at php.net.

More built-in functions


Ho w do yo u kno w if an element exists in an array? What if yo u need distinct array elements? Ho w abo ut so rting and
merging? All these questio ns can be answered with built-in PHP functio ns. Like we said earlier, it wo uld take ages to
go thro ugh them all, but we sho uld definitely go o ver so me o f the majo r o nes.

To cap o ff o ur intensive array wo rko ut, we leave yo u with a mo ntage o f fun PHP functio ns. Play, experiment, and refer
back to yo ur bo o k o r to php.net o ften. Think abo ut ho w the functio ns wo rk. Are array curso rs used? What are the
parameters? What is the functio n returning?

Finally, think abo ut ho w yo u wo uld write yo ur o wn PHP functio ns to perfo rm the same tasks. Wo uld yo u make the
same cho ices as the PHP fo lks?
Type the fo llo wing into Co deRunner:
<?php

$scotts_phonebook = array("kendell" => "555-1234",


"Trish" => "555-2345",
"Tony" => "555-3456",
"Mike" => "555-4567",
"Debra" => "555-5678",
"Curt" => "555-6789");

$kendells_phonebook = array("scott" => "555-7890",


"Trish" => "555-2345",
"Tony" => "555-3456",
"Debra" => "555-5678",
"Kate" => "555-8901");

//here's a phonebook combining both Scott's and Kendell's contacts, no duplicates

$combined_phonebook = array_unique(array_merge($scotts_phonebook, $kendells_phonebook))


;

echo "<pre> Combined Phonebook:";


print_r($combined_phonebook);
echo "</pre>";

//sort by name - why do you suppose we aren't assigning the return value to anything?

ksort($combined_phonebook);

echo "<pre>Sorted Phonebook:";


print_r($combined_phonebook);
echo "</pre>";

//here's a phonebook containing only mutual friends of Scott and Kendell

$mutual_friends = array_intersect($scotts_phonebook, $kendells_phonebook);

echo "<pre>Mutual Friends:";


print_r($mutual_friends);
echo "</pre>";

//in this custom function called "invite_friend," a phone number is


//called and that friend is invited to a party.

function invite_friend($phone_number, $name) {


echo "Calling phone number $phone_number...";
echo "Hello $name! You're invited to a party!<br/>";
}

//Here's a REALLY tricky built-in function we can use to invite ALL friends to the part
y.
//Careful, this one has lots of rules regarding the second parameter.

array_walk($combined_phonebook, 'invite_friend');

//Finally, generate a random phone number and see if it's in the phonebook.

$random_phonenumber = "555-".strval(rand(1000,9999));

if (in_array($random_phonenumber, $combined_phonebook)) {
echo "Phone number ".$random_phonenumber." is in the phonebook.";
}
else {
echo "Phone number ".$random_phonenumber." is not in the phonebook.";
}

?>

Save it as pho ne bo o ks.php and preview.

Were yo u able to figure them o ut? If no t, give yo urself so me time and do n't stress—remember, these are functio ns
built by so meo ne else to save time. If any built-in functio n do esn't suit yo ur purpo se, lo o k fo r ano ther o ne...o r just write
o ne yo urself.

Do n't fo rget to Save yo ur wo rk! And be sure to wo rk o n the assignments in yo ur syllabus when yo u're do ne here. See
yo u at the next lesso n...

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Strings
Welco me back. So , yo u already kno w that st rings are o ne type o f PHP variable . And yo u've been using strings thro ugho ut the
last five lesso ns with e cho , the co ncat o perato r (.), and in all kinds o f functio ns and lo o ps. Yo u've go t strings do wn, baby.

So why spend an entire lesso n o n the letters, numbers, and symbo ls that make up strings?

The truth is, we've o nly explo red the tip o f the pro verbial iceberg when it co mes to strings. In fact, they are the co rnersto nes o f
many a web-based, database-driven applicatio n. Like piranha, yo u sho uld never underestimate the feisty little critters.

So get yo ur waist-high galo shes o n, fire up PHP in Co deRunner, and let's get cracking.

What's a String Anyway?


And what is it hiding fro m us? String is its real name, right? Let's see what's go ing o n here. Remember o ur LAMP
acro nym?:

Type the fo llo wing into a new PHP file in Co deRunner:

<?php

$lamp_l = "Linux";
$lamp_a = "Apache";
$lamp_m = "MySQL";
$lamp_p = "PHP";

echo "<br/>The stack begins with ".$lamp_l.", and goes on to include "
.$lamp_a.", ".$lamp_m.", and ".$lamp_p."!<br/>";

//These supposedly simple strings are hiding something...

echo "Gimme an L! ".$lamp_l[0]."!<br/>";


echo "Gimme an A! ".$lamp_a[0]."!<br/>";
echo "Gimme an M! ".$lamp_m[0]."!<br/>";
echo "Gimme a P! ".$lamp_p[0]."!<br/>";

?>

Save it as st rings.php, then click Preview. Yo u sho uld see this:

The stack begins with Linux, and goes on to include Apache, MySQL, and PHP!
Gimme an L! L!
Gimme an A! A!
Gimme an M! M!
Gimme a P! P!

Wait a minute. Why were we just able to use the array o perato r [] to access the first letters o f the LAMP acro nym? Aha,
no w the truth co mes fo rth.

That sneaky string do esn't want yo u to kno w it has a secret identity. Yo u see, a st ring is a special type o f array, o ne
where each charact e r --letter, number, symbo l, newline, whatever takes up o ne byte o f space -- is assigned a
numerical key index. Here's what the string "Linux" wo uld lo o k like in o ur pillbo x representatio n fro m the arrays lesso n:

The last bo x yo u see co ntains simply the NULL character, which has always been used to terminate
Note strings in the C language - the language PHP is based upo n. (Check o ut the histo ry o f PHP.)

Manipulating Strings
Let's explo re strings further. We're go ing to make a new PHP file called bo lo gna.php.
Type the fo llo wing into Co deRunner:

<?php

function spell_me($mystring) {
$i = 0;
while ($mystring[$i] != null) {
if ($i == 0) {
echo $mystring[$i];
}
else {
echo " - ".$mystring[$i];
}
$i++;
}
}

$string_1 = "bologna";
$string_2 = "oscar";
$string_3 = $string_2;

$string_3[0] = 'm';
$string_3[1] = 'a';
$string_3[2] = 'y';
$string_3[3] = 'e';

//Sing along if you remember the commercial!

echo "My ".$string_1." has a first name, it's ";


spell_me($string_2);
echo "<br/>";

echo "My ".$string_1." has a second name, it's ";


spell_me($string_3);
echo "<br/>";

?>

Oh I love to eat it every day, <br/>


And if you ask me, why I'll say...<br/>

<?

echo "That ".$string_2." ".$string_3." has a way<br/>


With ";
spell_me($string_1);
echo "!";

?>

Note Fo r reference here's the Oscar Mayer bo lo gna so ng

Preview fo r the lyrics o f the so ng:

My bologna has a first name, it's o - s - c - a - r


My bologna has a second name, it's m - a - y - e - r
Oh I love to eat it every day,
And if you ask me, why I'll say...
That oscar mayer has a way
With b - o - l - o - g - n - a!

Thro ugh the po wer o f co mmercial jingles, we're able to unco ver two mo re truths abo ut strings: no t o nly can we access
the characters within a string using the [] o perato r, but we can use the same o perato r to traverse and manipulate
strings, just like arrays.
Take ano ther lo o k:

function spell_me($mystring) {
$i = 0;
while ($mystring[$i] != null) {
if ($i == 0) {
echo $mystring[$i];
}
else {
echo " - ".$mystring[$i];
}
$i++;
}
}

$string_1 = "bologna";
$string_2 = "oscar";
$string_3 = $string_2;

$string_3[0] = 'm';
$string_3[1] = 'a';
$string_3[2] = 'y';
$string_3[3] = 'e';

.
.
.

In o ur functio n spe ll_m e (), we used a while lo o p to traverse the string parameter, sto pping when we reached the null
character. Then we manipulated $ st ring_3 by assigning new characters to the indices we wanted to change. In no
time, "o scar" turned to "mayer," and all were spelled co rrectly.

Go ahead, keep humming the tune - we do n't mind.

Other nifty string shortcuts


Type the BLUE stuff into yo ur do cument in Co deRunner:

<?php

function spell_me($mystring) {
$i = 0;
while ($mystring[$i] != null) {
if ($i == 0) {
echo $mystring[$i];
}
else {
echo " - ".$mystring[$i];
}
$i++;
}
}

$string_1 = "bologna";
$string_2 = "oscar";
$string_3 = $string_2;

$string_3[0] = 'm';
$string_3[1] = 'a';
$string_3[2] = 'y';
$string_3[3] = 'e';

//Sing along if you remember the commercial!

echo "My $string_1 has a first name, it's "; //we took out the concat operators
spell_me($string_2);
echo "<br/>";

echo "My $string_1 has a second name, it's ";


spell_me($string_3);
echo "<br/>";

?>

Oh I love to eat it every day, <br/>


And if you ask me, why I'll say...<br/>

<?

echo "That $string_2 $string_3 has a way<br/>


With ";
spell_me($string_1);
echo "!";

?>

Preview this. No thing changed, right? This is a co o l sho rtcut created especially fo r strings in PHP, called
embedding variables. Since yo u'll mo st likely use PHP in web pages, yo u can thank us later fo r sho wing yo u
this sho rtcut. It pro vides a mo re intuitive metho d o f creating and o utputting dynamic strings witho ut the need
fo r all tho se anno ying co ncat o perato rs and quo tatio n marks.

There's o nly o ne small co mplicatio n with this sho rtcut. What happens if yo u want to display an actual do llar
sign ($ ) alo ng with all the embedded variables?
Type the fo llo wing into Co deRunner:

<?php

function spell_me($mystring) {
$i = 0;
while ($mystring[$i] != null) {
if ($i == 0) {
echo $mystring[$i];
}
else {
echo " - ".$mystring[$i];
}
$i++;
}
}

$string_1 = "bologna";
$string_2 = "oscar";
$string_3 = $string_2;

$string_3[0] = 'm';
$string_3[1] = 'a';
$string_3[2] = 'y';
$string_3[3] = 'e';

//Sing along if you remember the commercial!

echo "My $string_1 has a first name, it's "; //we took out the concat operators
spell_me($string_2);
echo "<br/>";

echo "My $string_1 has a second name, it's ";


spell_me($string_3);
echo "<br/>";

?>

Oh I love to eat it every day, <br/>


And if you ask me, why I'll say...<br/>

<?

echo "That $string_2 $string_3 has a way<br/>


With ";
spell_me($string_1);
echo "!";

echo "<br/>As you can see, $string_1 was passed into the parameter $mystring.";

?>

Yo u sho uld get so mething like this:

My bologna has a first name, it's o - s - c - a - r


My bologna has a second name, it's m - a - y - e - r
Oh I love to eat it every day,
And if you ask me, why I'll say...
That oscar mayer has a way
With b - o - l - o - g - n - a!
As you can see, bologna was passed into the parameter .

Well, that's a bunch o f bo lo gna. While we wanted to o utput the actual variable names, the e cho co mmand
tried to replace them with their values instead. This happens anytime echo sees a do llar sign ($ ) fo llo wed by
so mething that co uld pass as a variable name.

Ho w can we sto p it? Escape it.


Type the fo llo wing into Co deRunner:

<?php

function spell_me($mystring) {
$i = 0;
while ($mystring[$i] != null) {
if ($i == 0) {
echo $mystring[$i];
}
else {
echo " - ".$mystring[$i];
}
$i++;
}
}

$string_1 = "bologna";
$string_2 = "oscar";
$string_3 = $string_2;

$string_3[0] = 'm';
$string_3[1] = 'a';
$string_3[2] = 'y';
$string_3[3] = 'e';

//Sing along if you remember the commercial!

echo "My $string_1 has a first name, it's "; //we took out the concat operators
spell_me($string_2);
echo "<br/>";

echo "My $string_1 has a second name, it's ";


spell_me($string_3);
echo "<br/>";

?>

Oh I love to eat it every day, <br/>


And if you ask me, why I'll say...<br/>

<?

echo "That $string_2 $string_3 has a way<br/>


With ";
spell_me($string_1);
echo "!";

echo "<br/>As you can see, \$string_1 was passed into the parameter \$mystring."
;

?>

Yo u sho uld get this:

My bologna has a first name, it's o - s - c - a - r


My bologna has a second name, it's m - a - y - e - r
Oh I love to eat it every day,
And if you ask me, why I'll say...
That oscar mayer has a way
With b - o - l - o - g - n - a!
As you can see, $string_1 was passed into the parameter $mystring.

Ah, much better. Just by adding a little backslash (\) befo re each do llar sign ($ ), we're able to tell PHP that we
really do want the name itself displayed, no t the value.

That backslash is handy fo r escaping several o ther characters to o . Refer to yo ur bo o k o r to php.net to embed
them all into yo ur subco nscio us.

Built-in String Functions


"String functio ns?" yo u say, "I do n't need no stinking string functio ns. I co uld use all the built-in array functio ns o n
strings to o !"

While that may be true in C, PHP treats strings as a different t ype with its o wn set o f built-in functio ns, generally
keeping their secret identity under wraps. Try using an array functio n to traverse a string:
Type the fo llo wing into Co deRunner:

<?php

function spell_me($mystring) {
for ($i = 0; $i < count($mystring); $i++) {
if ($i == 0) {
echo $mystring[$i];
}
else {
echo " - ".$mystring[$i];
}
}
}

$string_1 = "bologna";
$string_2 = "oscar";
$string_3 = $string_2;

$string_3[0] = 'm';
$string_3[1] = 'a';
$string_3[2] = 'y';
$string_3[3] = 'e';

//Sing along if you remember the commercial!

echo "My $string_1 has a first name, it's "; //we took out the concat operators
spell_me($string_2);
echo "<br/>";

echo "My $string_1 has a second name, it's ";


spell_me($string_3);
echo "<br/>";

?>

Oh I love to eat it every day, <br/>


And if you ask me, why I'll say...<br/>

<?

echo "That $string_2 $string_3 has a way<br/>


With ";
spell_me($string_1);
echo "!";

echo "<br/>As you can see, \$string_1 was passed into the parameter \$mystring.";

?>

Preview it and yo u sho uld get this:

My bologna has a first name, it's o


My bologna has a second name, it's m
Oh I love to eat it every day,
And if you ask me, why I'll say...
That oscar mayer has a way
With b!
As you can see, $string_1 was passed into the parameter $mystring.

No t exactly the catchiest lyrics anymo re. No w try it with a built-in string functio n.
Type the fo llo wing into Co deRunner:

<?php

function spell_me($mystring) {
for ($i = 0; $i < strlen($mystring); $i++) {
if ($i == 0) {
echo $mystring[$i];
}
else {
echo " - ".$mystring[$i];
}
}
}

$string_1 = "bologna";
$string_2 = "oscar";
$string_3 = $string_2;

$string_3[0] = 'm';
$string_3[1] = 'a';
$string_3[2] = 'y';
$string_3[3] = 'e';

//Sing along if you remember the commercial!

echo "My $string_1 has a first name, it's "; //we took out the concat operators
spell_me($string_2);
echo "<br/>";

echo "My $string_1 has a second name, it's ";


spell_me($string_3);
echo "<br/>";

?>

Oh I love to eat it every day, <br/>


And if you ask me, why I'll say...<br/>

<?

echo "That $string_2 $string_3 has a way<br/>


With ";
spell_me($string_1);
echo "!";

echo "<br/>As you can see, \$string_1 was passed into the parameter \$mystring.";

?>

Yo u sho uld get this:

My bologna has a first name, it's o - s - c - a - r


My bologna has a second name, it's m - a - y - e - r
Oh I love to eat it every day,
And if you ask me, why I'll say...
That oscar mayer has a way
With b - o - l - o - g - n - a!
As you can see, $string_1 was passed into the parameter $mystring.

See, it's no t such a bad thing. Having specialized string functio ns means they'll be faster, easier, and mo re intuitive to
use.

So o n we'll be wo rking with HTML fo rms and dynamic inputs, which really flex the muscles o f built-in PHP string
functio ns. Ho wever, even witho ut fo rms, string functio ns have tho usands o f uses. Here we have peppered o ur o scar
mayer so ng with a pletho ra o f useful string functio ns. Play, experiment, and refer back to yo ur bo o k o r to php.net as
much as yo u need. Try o ut the co de belo w. Can yo u figure o ut ho w they all wo rk?
Type the fo llo wing into Co deRunner:

<?php

function spell_me($mystring) {
for ($i = 0; $i < strlen($mystring); $i++) {
if ($i == 0) {
echo strtoupper($mystring[$i]);
}
else {
echo " - ".strtoupper($mystring[$i]);
}
}
}

$string_1 = "bologna";
$string_2 = "oscar mayer";
$space_index = strpos($string_2, " ");

//let's spell boloney how we really say it...


echo "My ".str_replace('gna','ney',$string_1)." has a first name, it's ";
spell_me(substr($string_2,0,$space_index));
echo "<br/>";

echo "My $string_1 has a second name, it's ";


spell_me(substr($string_2,$space_index+1)); //notice this has only two parameters
echo "<br/>";

?>

Oh I love to eat it every day, <br/>


And if you ask me, why I'll say...<br/>

<?

//we're tired of putting in the HTML <br/> tags...


echo "That $string_2 ".nl2br("has a way
With ");
spell_me($string_1);
echo "!";

$sale_price = 1; //a dollar


echo "<br/>On sale for ".number_format($sale_price, 2)."!";

?>

Befo re we mo ve o n, experiment with these questio ns in Co deRunner:

Does it matter whether you use single quotation marks (') or double quotation m
arks (") with strings?
Can you mix the two types of quotation marks? Do you have to escape them if yo
u do?
Are there any built-in array functions that do work with strings?
Would you have built the substr() function differently?

Regular Expressions
No t many subjects can make a pro grammer gro an like that o f re gular e xpre ssio ns. They are immensely useful, yes
- they are used to create "wildcard" strings so that yo u can, say, verify that so meo ne has entered a valid email address
o r a co rrect pho ne number fo rmat. Ho wever, learning "Regex" patterns can so metimes feel as tho ugh yo u're
deciphering the Ro setta Sto ne. Even the ever-helpful php.net pawns yo u o ff to a cryptic "man page" when dealing with
Regex rules. Aargh.

But hey! We've go t "learning by do ing" o n o ur side. And when we learn by do ing, we can acco mplish anything.
Type the fo llo wing into a new PHP file in Co deRunner:

<?php

//here's a simple function to check Regex patterns against string parameters

function check_regex($myregex, $mystring) {


if (preg_match("/$myregex/", $mystring)) {
echo "The pattern '$myregex' is found in $mystring.<br/>";
}
else {
echo "The pattern '$myregex' is NOT found in $mystring.<br/>";
}
}

$regex_1 = "log";

$string_1 = "bologna";
check_regex($regex_1, $string_1);

?>

Yo u sho uld get:

The pattern 'log' is found in bologna.

Here we have an example o f a re gular e xpre ssio n -- a simple string: "lo g." And by using the built-in PHP functio n
pre g_m at ch(), we are simply checking to see if a "lo g" is fo und in "bo lo gna." Of co urse it is. No tice the quo tes and
fo rward slashes needed aro und the $myregex variable. These are needed because preg_match is a PERL style regex
matching functio n and regex's in PERL must have fo rward slashes. See what happens if yo u remo ve the slashes.

So , yo u may wo nder why we didn't just use the built-in string functio n st rpo s(). We co uld have. But here's where it
gets interesting...

The plo t thickens. Type the fo llo wing into Co deRunner:

<?php

//here's a simple function to check Regex patterns against string parameters

function check_regex($myregex, $mystring) {


if (preg_match("/$myregex/", $mystring)) {
echo "The pattern '$myregex' is found in $mystring.<br/>";
}
else {
echo "The pattern '$myregex' is NOT found in $mystring.<br/>";
}
}

$regex_1 = "log$";

$string_1 = "bologna";
check_regex($regex_1, $string_1);

$string_2 = "catalog";
check_regex($regex_1, $string_2);

?>

Preview this:

The pattern 'log$' is NOT found in bologna.


The pattern 'log$' is found in catalog.

No w THIS result we co uld no t get fro m st rpo s. Since when is a do llar sign ($ ) fo und in the wo rd "catalo g"?

As it turns o ut, the do llar sign has a special meaning in regular expressio ns, and it's different fro m the meaning it
usually has fo r PHP variables. In regular expressio ns, placing a do llar sign ($ ) after a string means "at the end of the
string".
Take ano ther lo o k:

<?php

.
.
.

$regex_1 = "log$";

$string_1 = "bologna";
check_regex($regex_1, $string_1);

$string_2 = "catalog";
check_regex($regex_1, $string_2);

?>

Because we specified $ re ge x_1 to be " lo g$ " and no t just " lo g" , o ur functio n che ck_re ge x() no w checks to see if
" lo g" is fo und at the end o f each o f o ur strings. This is why it returned t rue fo r "catalo g," but f alse fo r "bo lo gna."

This is the key to regular expressio ns. Mo re than just a rando m string to o l, regular expressio ns are an entirely different
language fo r creating and co mparing strings with very specific patterns in mind: the presence o f specific characters, the
number o f o ccurrences o f each character, and their lo catio n in the string. In this case, we were co ncerned with the
lo catio n o f the string "lo g." Let's try ano ther o ne...

Type the fo llo wing into Co deRunner:

<?php

//here's a simple function to check Regex patterns against string parameters

function check_regex($myregex, $mystring) {


if (preg_match("/$myregex/", $mystring)) {
echo "The pattern '$myregex' is found in $mystring.<br/>";
}
else {
echo "The pattern '$myregex' is NOT found in $mystring.<br/>";
}
}

$regex_1 = "^cat";

$string_1 = "concatenate";
check_regex($regex_1, $string_1);

$string_2 = "catalog";
check_regex($regex_1, $string_2);

?>

The pattern '^cat' is NOT found in concatenate.


The pattern '^cat' is found in catalog.

Yo u guessed it. Placing a carat (^) in fro nt o f yo ur Regex string means "at the beginning of the string."

Character Ranges and Number of Occurrences


Type the fo llo wing into Co deRunner:

<?php

//here's a simple function to check Regex patterns against string parameters

function check_regex($myregex, $mystring) {


if (preg_match("/$myregex/", $mystring)) {
echo "The pattern '$myregex' is found in $mystring.<br/>";
}
else {
echo "The pattern '$myregex' is NOT found in $mystring.<br/>";
}
}

$regex_1 = "cat.*a";

$string_1 = "concatenate";
check_regex($regex_1, $string_1);

$string_2 = "catalog";
check_regex($regex_1, $string_2);

?>

Preview this:

The pattern 'cat.*a' is found in concatenate.


The pattern 'cat.*a' is found in catalog.

Who a. That is a crazy Regex pattern. Yet it was fo und in the strings "co ncatenate" AND "catalo g." What gives?

And speaking o f co ncatenate, isn't that perio d (.) the co ncatenate o perato r in PHP? No t this time. Just like the
do llar sign ($ ), the perio d (.) has a much different meaning when it co mes to regular expressio ns. In this case,
it represents any character, like a wildcard.

As fo r the asterisk (*), that means "zero or more". Put it all to gether, and the regular expressio n " cat .*a"
means "the string 'cat,' followed by zero or more characters, followed by an 'a'".

Is that fo und in " co ncat e nat e " ? Yes: the string 'cat ' is fo und, fo llo wed by two characters 'e ' and 'n',
fo llo wed by an 'a'. Ho w abo ut " cat alo g" ? Yep: 'cat ' is fo llo wed by zero characters, fo llo wed by an 'a'. Let's
try a REALLY crazy Regex:

Type the fo llo wing into Co deRunner:

<?php

//here's a simple function to check Regex patterns against string parameters

function check_regex($myregex, $mystring) {


if (preg_match("/$myregex/", $mystring)) {
echo "The pattern '$myregex' is found in $mystring.<br/>";
}
else {
echo "The pattern '$myregex' is NOT found in $mystring.<br/>";
}
}

$regex_1 = "cat(a|e)+[a-z]{2,5}";

$string_1 = "concatenate";
check_regex($regex_1, $string_1);

$string_2 = "catalog";
check_regex($regex_1, $string_2);

$string_3 = "catamaran";
check_regex($regex_1, $string_3);

$string_4 = "scathing";
check_regex($regex_1, $string_4);

$string_5 = "pontificates";
check_regex($regex_1, $string_5);

?>

Preview this:
The pattern 'cat(a|e)+[a-z]{2,5}' is found in concatenate.
The pattern 'cat(a|e)+[a-z]{2,5}' is found in catalog.
The pattern 'cat(a|e)+[a-z]{2,5}' is found in catamaran.
The pattern 'cat(a|e)+[a-z]{2,5}' is NOT found in scathing.
The pattern 'cat(a|e)+[a-z]{2,5}' is NOT found in pontificates.

No w, this may seem o verwhelming, but it's actually just a series o f simple Regex patterns. Let's break them
do wn:

cat (a|e )+[a-z]{2,5 }

(a|e ): The pipe character (|) in regular expressio ns means OR, so in this case we're lo o king fo r
"either an 'a' or an 'e'". Parentheses(()) are used to separate o ut expressio ns when we are nesting
them, just like always.
+: The plus sign (+) is just like the asterisk (*), except it's lo o king fo r o ne o r m o re o f the
characters it fo llo ws. Since we preceded it with the expressio n (a|e ), in this case it means "one or
more of either 'a' or 'e'".
[a-z]: To allo w entire ranges o f characters as a sho rtcut, we use square brackets ([]) and the dash
(-). So in this case, we're lo o king fo r "any lowercase letter from 'a' to 'z'".
{2,5 } : Curly braces ({} ) are used like the plus sign and asterisk, indicating a range o f o ccurrences
o f the preceding expressio n. In this case, because {2,5 } fo llo ws [a-z], we're lo o king fo r "2 to 5
occurrences of any lowercase letter from 'a' to 'z'".

Put it all to gether, and we find that the pattern cat (a|e )+[a-z]{2,5 } in Regex-speak means "The string 'cat',
followed by one or more 'a's or 'e's, followed by at least 2, but not more than 5 lowercase letters, from 'a' to 'z'."

Can yo u figure o ut why it's no t fo und in " scat hing" o r " po nt if icat e s" ?

Excluding Characters
No w, if yo u tho ught THAT was co nfusing, co nsider this: What if yo u had the all-impo rtant task o f, say,
removing funky characters fro m a file name and replacing them with so mething benign? Here's where things
REALLY get screwy.

Type the fo llo wing into Co deRunner:

<?php

//here's a simple function to check Regex patterns against string parameters

function check_regex($myregex, $mystring) {


if (preg_match("/$myregex/", $mystring)) {
echo "The pattern '$myregex' is found in $mystring.<br/>";
}
else {
echo "The pattern '$myregex' is NOT found in $mystring.<br/>";
}
}

//here's a function that takes in a file name, and replaces all funky characters
with an underscore "_"

function clean_filename($file_name) {
$bad_characters = "[^a-zA-Z0-9.]";
$new_filename = preg_replace("/$bad_characters/", "_", $file_name);
return $new_filename;
}

$bad_filename = "file[3*1 name.doc";

$good_filename = clean_filename($bad_filename);

echo "'$bad_filename' has been changed to '$good_filename'.";

?>

Preview this:

'file[3*1 name.doc' has been changed to 'file_3_1_name.doc'.

We kno w, we kno w, this makes no sense at all. First o f all, the carat (^) is suppo sed to mean "at the beginning
of the string." The perio d (.) is suppo sed to represent a wildcard character. And what's with the ranges o f
characters -- a-z, A-Z , and 0 -9 -- stuck to gether like that? Gro an.

Well, as it turns o ut, when it co mes to whatever's in the square brackets ([]), the rules change. Let's take a
clo ser lo o k at brackets in regular expressio ns.
[^a-zA-Z 0 -9 .]

^: When used within square brackets, the carat (^) negates everything after it - just like the
exclamatio n po int(!) in PHP. So in this case it's lo o king fo r characters that DON'T match what's
inside the brackets.
a-zA-Z 0 -9 : Everything within square brackets co mes to gether to represent o nly o ne character.
Therefo re, characters placed within the brackets are treated as if a pipe character (|) was inserted in
between each o ne. Fo r instance, [abcd] is the same as (a|b|c|d), and in this case, a-zA-Z 0 -9 is
the same as ([a-z]|[A-Z ]|[0 -9 ]), o r mo re simply, "any alphanumeric character".
.: Within square brackets, every character except fo r the carat(^), the dash(-), and the right bracket
itself(]) is taken as a literal character - including the perio d(.) that wo uld no rmally be co nsidered a
wildcard character.

Put it all to gether, and we find that the pattern [^a-zA-Z 0 -9 .] actually means "any character which is NOT an
alphanumeric character or a period.".

Escaping Characters
Re gular Expre ssio ns are extremely useful in PHP - especially since yo u'll be do ing a lo t o f HTML fo rm
pro cessing. Fo r instance, ho w can yo u ensure that so meo ne's entered their pho ne number pro perly?

Type the fo llo wing into Co deRunner:

<?php

//here's a simple function to check Regex patterns against string parameters

function check_regex($myregex, $mystring) {


if (preg_match("/$myregex/", $mystring)) {
echo "The pattern '$myregex' is found in $mystring.<br/>";
}
else {
echo "The pattern '$myregex' is NOT found in $mystring.<br/>";
}
}

//here's a function that takes in a file name, and replaces all funky characters
with an underscore "_"

function clean_filename($file_name) {
$bad_characters = "[^a-zA-Z0-9.]";
$new_filename = preg_replace("/$bad_characters/", "_", $file_name);
return $new_filename;
}

//here's a function which validates an American phone number

function validate_phone($phone_number) {
$good_phone = "^\(?[0-9]{3}\)?( |-|\.)[0-9]{3}(-|\.)[0-9]{4}$";

if (preg_match("/$good_phone/", $phone_number)) {
echo "$phone_number is valid.<br/>";
}
else echo "$phone_number is NOT valid.<br/>";
}

$phone_number1 = "34x.d98.1123";
validate_phone($phone_number1);

$phone_number2 = "(217) 555-1212";


validate_phone($phone_number2);

?>

Preview this:

34x.d98.1123 is NOT valid.


(217) 555-1212 is valid.

Let's break this do wn: ^\(?[0 -9 ]{3} \)?( |-|\.)[0 -9 ]{3} (-|\.)[0 -9 ]{4 } $

^: Since we're o utside any square brackets, the carat (^) takes o n its o riginal meaning—"at the
beginning of the string." By the same to ken, we use the do llar sign ($ ) to mean "at the end of the
string," so that we have an exact match.
\(?: So me Americans use parentheses (()) to enclo se the 3-digit area co de o f their pho ne
numbers. To allo w this po ssibility, we use the questio n mark (?) much like the asterisk o r plus
sign, o nly this time to deno te "zero or one" o f the leading parenthesis ((). Ho wever, because
parentheses usually mean nesting, we use a backslash (\) to escape the character. This must
always be do ne when no t within the square brackets. The same is true with \)?.
[0 -9 ]{3} : Since the area co de o f the American pho ne number system uses exactly 3 digits, we use
{3} to require exactly 3 o f any digit, deno ted by [0 -9 ]. We use the same lo gic with the 3-digit prefix,
as well as the ending 4 digits o f the pho ne number.
( |-|\.) Usually between the area co de and the prefix o f a pho ne number, fo lks use either a space ("
"), a dash (-), o r a perio d(.). Therefo re, we use the parentheses(()) alo ng with the pipe character (|)
to say "either a space or a dash or a period." We put a backslash befo re the perio d because we
must escape it. An unescaped perio d matches a single character witho ut caring what that character
is. So since we want a literal perio d, we add the backslash to "escape" the character having that
special meaning.

In case yo ur eyes are cro ssing right no w, remember that re gular e xpre ssio ns take a lo t o f patience, practice, and
trial-and-erro r to get right. Refer back to this lesso n, to bo o ks yo u may have, o r to the web, o ften. Here's a great article
o n regular expressio ns in PHP.

Whew! We've co vered a lo t o f gro und. Do n't fo rget to Save yo ur wo rk and hand in yo ur assignm e nt s fro m yo ur syllabus. See
yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Fixing Broken PHP

This lesso n is all abo ut frustratio n. Frustratio n that co mes in the fo rm o f parse e rro rs, inf init e
lo o ps, unm at che d bracke t s, and lo gical m ist ake s. Frustratio n that makes yo ur face
grimace and yo ur fingers type furio usly, po unding as if sheer fo rce co uld will the keys into
assembling pro per PHP co de fro m the mangled mess that is yo ur o wn pro gram. Ah yes, we
kno w this feeling well.

In previo us lesso ns we fo cused o n the basics o f PHP, keeping examples and pro jects to finite
blo cks o f co de. We're sure yo u've handled the frustrating erro rs like a tro o per so far. In the
upco ming lesso ns, we'll begin co nstructing mo re co mplex pro grams to so lve real-wo rld
pro blems, which means the threat o f frustratio n lo o ms larger than ever. Yo u're go ing to need
so me serio us ammo fo r creating and debugging scalable pro grams. Yo ur sanity just may
depend o n it.

So let's take a break fro m new PHP co ncepts and fo cus o n technique fo r a while. Go t Co deRunner in PHP syntax? Go o d - let's
get go ing.

T hings Professors Don't T alk About Enough


We're guilty o f it to o . We intro duce yo u to co ncepts that theo retically wo rk just fine, assuming that everything typed in
just so , and that we've explained the co ncept perfectly. So o f course these co ncepts will wo rk perfectly fo r yo u, every
time yo u apply them, right?

Let's find o ut using the fo llo wing silly pro gram we assembled fro m co ncepts co vered in previo us lesso ns.
It's o kay to co py and paste, JUST THIS ONCE! Paste this into Co deRunner:

<?
function mantra($the_sound,$the_number = 10) {
$chant = 1;
while ($chant <= $the_number;) {
echo $the_sound."... ";
}
}

function Mood_Chant($my_mood){
if ($my_mood == "happy") {
mantra("OM");
$after_chant = "<br/>I feel serene now.";
}
else if ($my_mood == "sad") {
mantra("okay");
$after_chant = "<br/>I feel better now.";
}
else if ($my_mood == "angry") {
mantra("mississippi");
$after_chant = "<br/>Ahhh, much better. I've calmed down now.";
}
else if ($my_outlook == "indifferent") {
mantra("Wake up");
$after_chant = "<br/>I'm awake now.";
}
else {
mantra("Try harder");
$after_chant = "<br/>I'll try harder now.";
}
return $after_chant;
}

function whats_my_emotion($cereal_prices, $cash_money) {


$total = array_sum($cereal_prices); //array_sum is a built-in PHP function
if ($total < $my_cash) {
$mood = "happy";
echo "I'll buy both Captain Crunch and Fruit Loops!";
}
else if ($cereal_prices['Captain_Crunch'] < $my_cash ) {
$mood = "indifferent";
echo "I'll buy Captain Crunch.";
}
else if ($cereal_prices['Captain_Crunch'] > $my_cash && $cereal_prices['Fruit_Loops'
] < $my_cash ){
$mood = "angry";
echo "Fine! I'll get some Fruit Loops.";
}
else {
$mood = "sad";
echo "Oh well, I'm going home.";
}
return $mood;
}
<h3>The emotional roller-coaster of buying breakfast cereal</h3>
<?
$cereal_prices = array('Captain_Crunch' => 5, 'Fruit_Loops' => 3);
$my_cash = 4;
?>
I have $<? echo $my_cash; ?> in my pocket, and I want to buy some Captain Crunch!<br/>
<ul>
<li>Captain Crunch costs $<? echo $cereal_prices['Captain_Crunch']; ?></li>
<li>Fruit Loops costs $<? echo $cereal_prices['Fruit_Loops']; ?></li>
</ul>

$my_mood = whats_my_emotion($cereal_prices, $my_cash);


if (!($my_mood == "sad")) {
$after_chant_mood = Mood_Chant($my_mood, $chant_number);
}
echo "<br/>".$after_chant_mood;

?>

Preview this:

Parse error: syntax error, unexpected ';' in /users/cert josh/useract ivepreviewt mp123.php3
line 4

Okay, WRONG. Even a benign-lo o king pro gram like the abo ve wo rks beautifully in theo ry, but never in practice -- at
least fo r the first hundred times yo u try it. Trust us. Do yo u think o ur examples wo rked perfectly the first time we wro te
them? Hardly.

But even with this relatively small amo unt o f co de, where do yo u begin to debug it? Here is where yo u're usually o n
yo ur o wn...

...but hey, no t in this lesso n! We're no t to o far remo ved fro m o ur humble beginnings to kno w ho w hard it is to master
debugging. Co nsider this a suppo rt gro up fo r frustrated co ders, and yo u're invited.

Debugging T ips
Utilizing Error Messages
Let's Preview again:

Parse error: syntax error, unexpected ';' in /users/cert josh/useract ivepreviewt mp123.php3
line 4

If yo u're lucky, yo u'll get an easy to see erro r message right away, like yo u're getting no w. In o ther situatio ns
yo u may have to ask yo ur system administrato r where she keeps the PHP erro r lo gs. In any case, the First
Rule o f Debugging is: check the error messages first. They may seem cryptic at times, but they almo st always
give yo u the info rmatio n yo u need. In particular, the line num be r where the pro blem is lo cated.

Since o ur erro r message indicated line 4 , go to that line. What do yo u see?

Suddenly, o ur parse e rro r is as lo ud as a mariachi band. There sho uldn't be a semico lo n (;) inside the
parentheses (()) o f a while lo o p! This is easy eno ugh to fix: just remo ve the semico lo n (;).

Go o d fo r yo u! Yo u fixed the erro r, and no w everything sho uld wo rk perfectly, right?

Riddle-Me-T his Error Messages


Cro ss yo ur fingers and Preview again:

Parse error: syntax error, unexpected '<' in /users/cert josh/useract ivepreviewt mp128.php3
line 53

Yikes, ano ther erro r message! Mild frustratio n ensues. Well, no pro blem, we'll just do the same thing we did

befo re. But this time try the Go To Line butto n. Type in line 5 3:

Hmm, that's strange. This isn't even PHP co de, it's HTML co de -- and perfect HTML co de, at that. Why wo uld
PHP single o ut a line o f go o d HTML co de in its erro r message?
We're go ing to have to lo o k aro und fo r mo re clues, which brings us to the Seco nd Rule o f Debugging: Check
lines closest to the error message second. Let's give that a sho t, by lo o king at line 5 2:

And there yo u have it - a tiny curly bracket (} ), indicative o f PHP co de. Were yo u able to so lve the riddle o f the
erro r message? We fo rgo t to delimit the PHP with a ?> between the PHP co de and the HTML co de, so the
PHP parser was attempting to read the HTML co de as PHP! Hence the message: "unexpected '<' o n line 5 3".
It didn't kno w any better.

Go ahead and add the delimiter (?>), and yo u have squashed ano ther bug in o ur pro gram. Let's ho pe that's
the last o ne.

Errors without Error Messages


Chant 'no erro r messages' three times, then Preview again:

The emotional roller-coaster of buying breakfast cereal


I have $4 in my pocket, and I want to buy some Captain Crunch!

Captain Crunch costs $5


Fruit Loops costs $3

$my_mood = whats_my_emotion($cereal_prices, $my_money); if (!($my_mood == "sad")) {


$after_chant_mood = Mood_Chant($my_mood, $chant_number); } echo "
".$after_chant_mood; ?>

Hey, the chant wo rked - no erro r messages! But wait - there's still an erro r. Lo o ks like "no erro r messages" is
no t the same as "no erro rs". Which brings us to the Third Rule o f Debugging: When there are no error
messages, check your output. Or, just wo rk o n yo ur chant.

Lo o k at yo ur Preview again. It seems that the tro uble starts right after the statement: "Fruit Loops costs $3".
After that, chao s erupts. So let's take a lo o k at o ur co de no w, and try to pinpo int the pro blem.
Pay attentio n to the erro rs we already fixed, and where the new erro r seems to be happening:
<?
function mantra($the_sound,$the_number = 10) {
$chant = 1;
while ($chant <= $the_number) { //first we took out the rogue semicolon...
echo $the_sound."... ";
}
}

function Mood_Chant($my_mood){
if ($my_mood == "happy") {
mantra("OM");
$after_chant = "<br/>I feel serene now.";
}
else if ($my_mood == "sad") {
mantra("okay");
$after_chant = "<br/>I feel better now.";
}
else if ($my_mood == "angry") {
mantra("mississippi");
$after_chant = "<br/>Ahhh, much better. I've calmed down now.";
}
else if ($my_outlook == "indifferent") {
mantra("Wake up");
$after_chant = "<br/>I'm awake now.";
}
else {
mantra("Try harder");
$after_chant = "<br/>I'll try harder now.";
}
return $after_chant;
}

function whats_my_emotion($cereal_prices, $cash_money) {


$total = array_sum($cereal_prices); //array_sum is a built-in PHP function
if ($total < $my_cash) {
$mood = "happy";
echo "I'll buy both Captain Crunch and Fruit Loops!";
}
else if ($cereal_prices['Captain_Crunch'] < $my_cash ) {
$mood = "indifferent";
echo "I'll buy Captain Crunch.";
}
else if ($cereal_prices['Captain_Crunch'] > $my_cash && $cereal_prices['Fruit
_Loops'] < $my_cash ){
$mood = "angry";
echo "Fine! I'll get some Fruit Loops.";
}
else {
$mood = "sad";
echo "Oh well, I'm going home.";
}
return $mood;
}
//then we added the delimiter here...
?>
<h3>The emotional roller-coaster of buying breakfast cereal</h3>
<?
$cereal_prices = array('Captain_Crunch' => 5, 'Fruit_Loops' => 3);
$my_cash = 4;
?>
I have $<? echo $my_cash; ?> in my pocket, and I want to buy some Captain Crunch
!<br/>
<ul>
<li>Captain Crunch costs $<? echo $cereal_prices['Captain_Crunch']; ?></li>
<li>Fruit Loops costs $<? echo $cereal_prices['Fruit_Loops']; ?></li>
</ul>
//BUT NOW THE PROBLEM APPEARS TO BE HERE

$my_mood = whats_my_emotion($cereal_prices, $my_cash);


if (!($my_mood == "sad")) {
$after_chant_mood = Mood_Chant($my_mood, $chant_number);
}
echo "<br/>".$after_chant_mood;

?>

Lo o king at the co de, we see no w that we've do ne it again - we've fo rgo tten a de lim it e r, this time an o pening
delimiter (<?). Why didn't we get an erro r message like befo re? Because this time the co de went fro m HTML
to PHP - so it was HTML attempting to render the PHP co de, no t the o ther way aro und. HTML is mo re
fo rgiving in this sense, and simply prints o ut the co de.

Be sure to add the delimiter <?. Are we do ne no w?

Logical Errors
Signs po int to no :

The emotional roller-coaster of buying breakfast cereal


I have $4 in my pocket, and I want to buy some Captain Crunch!

Captain Crunch costs $5


Fruit Loops costs $3

Oh well, I'm going home.

At first glance, everything appears to be co rrect. No erro r messages, no garbled o utput. But befo re yo u
breathe that sigh o f relief, remember that this silly pro gram is suppo sed to determine o ur mo o d and
purchasing behavio r, based o n cereal prices and ho w much mo ney we have.

Take ano ther lo o k at the co de:


function whats_my_emotion($cereal_prices, $cash_money) {
$total = array_sum($cereal_prices); //array_sum is a built-in PHP function
if ($total < $my_cash) {
$mood = "happy";
echo "I'll buy both Captain Crunch and Fruit Loops!";
}
else if ($cereal_prices['Captain_Crunch'] < $my_cash ) {
$mood = "indifferent";
echo "I'll buy Captain Crunch.";
}
else if ($cereal_prices['Captain_Crunch'] > $my_cash && $cereal_prices['Fruit
_Loops'] < $my_cash){
$mood = "angry";
echo "Fine! I'll get some Fruit Loops.";
}
else {
$mood = "sad";
echo "Oh well, I'm going home.";
}
return $mood;
}

Fro m o ur o utput, we see that we have $4 -- no t eno ugh to buy Captain Crunch fo r $5, but eno ugh to buy Fruit
Lo o ps fo r $3. In o ur pro gram, that's suppo sed to make us angry, but we'd rather invo ke a calming mantra
chant and buy Fruit Lo o ps anyway. So why are we dejected and go ing ho me?

This is called a lo gical e rro r, and unfo rtunately it seems that the o utput isn't helping us much in the way o f
clues to fix it. Which brings us to the Fo urth Rule o f Debugging: When the output doesn't show the error, create
strategic output that does.
Type the fo llo wing green co de into Co deRunner:
<?
function mantra($the_sound,$the_number = 10) {
$chant = 1;
while ($chant <= $the_number) { //first we took out the rogue semicolon...
echo $the_sound."... ";
}
}

function Mood_Chant($my_mood){
if ($my_mood == "happy") {
mantra("OM");
$after_chant = "<br/>I feel serene now.";
}
else if ($my_mood == "sad") {
mantra("okay");
$after_chant = "<br/>I feel better now.";
}
else if ($my_mood == "angry") {
mantra("mississippi");
$after_chant = "<br/>Ahhh, much better. I've calmed down now.";
}
else if ($my_outlook == "indifferent") {
mantra("Wake up");
$after_chant = "<br/>I'm awake now.";
}
else {
mantra("Try harder");
$after_chant = "<br/>I'll try harder now.";
}
return $after_chant;
}

function whats_my_emotion($cereal_prices, $cash_money) {


$total = array_sum($cereal_prices); //array_sum is a built-in PHP function
if ($total < $my_cash) {
$mood = "happy";
echo "I'll buy both Captain Crunch and Fruit Loops!";
}
else if ($cereal_prices['Captain_Crunch'] < $my_cash ) {
$mood = "indifferent";
echo "I'll buy Captain Crunch.";
}
else if ($cereal_prices['Captain_Crunch'] > $my_cash && $cereal_prices['Fruit
_Loops'] < $my_cash ){
$mood = "angry";
echo "Fine! I'll get some Fruit Loops.";
}
else {
$mood = "sad";
echo "Oh well, I'm going home.";
}
return $mood;
}
//then we added the delimiter here...
?>
<h3>The emotional roller-coaster of buying breakfast cereal</h3>
<?
$cereal_prices = array('Captain_Crunch' => 5, 'Fruit_Loops' => 3);
$my_cash = 4;
?>
I have $<?
//We know it's not here, because the output has been correct
echo $my_cash; ?> in my pocket, and I want to buy some Captain Crunch!<br/>
<ul>
<li>Captain Crunch costs $<? echo $cereal_prices['Captain_Crunch']; ?></li>
<li>Fruit Loops costs $<? echo $cereal_prices['Fruit_Loops']; ?></li>
</ul>

<?
//then we added the delimiter here...

$my_mood = whats_my_emotion($cereal_prices, $my_cash);


//Let's add some echo statements to figure out our logic.
echo "\$my_mood is $my_mood";

if (!($my_mood == "sad")) {
$after_chant_mood = Mood_Chant($my_mood, $chant_number);
}
echo "<br/>".$after_chant_mood;

?>

Preview this:

The emotional roller-coaster of buying breakfast cereal


I have $4 in my pocket, and I want to buy some Captain Crunch!

Captain Crunch costs $5


Fruit Loops costs $3

Oh well, I'm going home.$my_mood is sad

So we find that when the functio n what s_m y_e m o t io n() returns, its value is sad, no t angry. Since we kno w
the values o f $ m y_cash and $ ce re al_price s are co rrect, it lo o ks like we've narro wed the pro blem do wn to
what s_m y_e m o t io n(). No w what do we do ?

Let's add so me mo re echo statements - but this time use them within what s_m y_e m o t io n(), just to see
what happens.
Add the fo llo wing green co de into Co deRunner:
<?
function mantra($the_sound,$the_number = 10) {
$chant = 1;
while ($chant <= $the_number) { //first we took out the rogue semicolon...
echo $the_sound."... ";
}
}

function Mood_Chant($my_mood){
if ($my_mood == "happy") {
mantra("OM");
$after_chant = "<br/>I feel serene now.";
}
else if ($my_mood == "sad") {
mantra("okay");
$after_chant = "<br/>I feel better now.";
}
else if ($my_mood == "angry") {
mantra("mississippi");
$after_chant = "<br/>Ahhh, much better. I've calmed down now.";
}
else if ($my_outlook == "indifferent") {
mantra("Wake up");
$after_chant = "<br/>I'm awake now.";
}
else {
mantra("Try harder");
$after_chant = "<br/>I'll try harder now.";
}
return $after_chant;
}

function whats_my_emotion($cereal_prices, $cash_money) {


$total = array_sum($cereal_prices); //array_sum is a built-in PHP function
if ($total < $my_cash) {
$mood = "happy";
echo "I'll buy both Captain Crunch and Fruit Loops!";
}
else if ($cereal_prices['Captain_Crunch'] < $my_cash ) {
$mood = "indifferent";
echo "I'll buy Captain Crunch.";
}
else if ($cereal_prices['Captain_Crunch'] > $my_cash && $cereal_prices['Fruit
_Loops'] < $my_cash ){
$mood = "angry";
echo "Fine! I'll get some Fruit Loops.";
}
else {
//We know the output is coming from here, so let's add echo statements:
echo "Within whats_my_emotion, \$cereal_prices:<pre>";
print_r($cereal_prices);
echo "\$my_cash = ".$my_cash."</pre>";

$mood = "sad";
echo "Oh well, I'm going home.";
}
return $mood;
}
//then we added the delimiter here...
?>
<h3>The emotional roller-coaster of buying breakfast cereal</h3>
<?
$cereal_prices = array('Captain_Crunch' => 5, 'Fruit_Loops' => 3);
$my_cash = 4;
?>
I have $<?
//We know it's not here, because the output has been correct
echo $my_cash; ?> in my pocket, and I want to buy some Captain Crunch!<br/>
<ul>
<li>Captain Crunch costs $<? echo $cereal_prices['Captain_Crunch']; ?></li>
<li>Fruit Loops costs $<? echo $cereal_prices['Fruit_Loops']; ?></li>
</ul>

<?
//then we added the delimiter here...

$my_mood = whats_my_emotion($cereal_prices, $my_cash);


//Let's add some echo statements to figure out our logic.
echo "\$my_mood is $my_mood";

if (!($my_mood == "sad")) {
$after_chant_mood = Mood_Chant($my_mood, $chant_number);
}
echo "<br/>".$after_chant_mood;

?>

Preview this:

The emotional roller-coaster of buying breakfast cereal


I have $4 in my pocket, and I want to buy some Captain Crunch!

Captain Crunch costs $5


Fruit Loops costs $3

Within whats_my_emotion, $cereal_prices:


Array
(
[Captain_Crunch] => 5
[Fruit_Loops] => 3
)
$my_cash =

Oh well, I'm going home.$my_mood is sad

This is starting to lo o k pretty messy, but it do es tell us everything we need to kno w. Thro ugh o ur echo and
print_r statements, we can see that the lo gical e rro r is definitely within what s_m y_e m o t io n(). Why?
Because the parameter $ m y_cash was never pro perly passed in -- causing the resulting mo o d to be sad
instead o f angry.
Take a clo ser lo o k at whats_my_emo tio n():
function whats_my_emotion($cereal_prices, $cash_money) {
$total = array_sum($cereal_prices); //array_sum is a built-in PHP function
if ($total < $my_cash) {
$mood = "happy";
echo "I'll buy both Captain Crunch and Fruit Loops!";
}
else if ($cereal_prices['Captain_Crunch'] < $my_cash ) {
$mood = "indifferent";
echo "I'll buy Captain Crunch.";
}
else if ($cereal_prices['Captain_Crunch'] > $my_cash && $cereal_prices['Fruit
_Loops'] < $my_cash ){
$mood = "angry";
echo "Fine! I'll get some Fruit Loops.";
}
else {
//We know the output is coming from here, so let's add echo statements:
echo "Within whats_my_emotion, \$cereal_prices:<pre>";
print_r($cereal_prices);
echo "\$my_cash = ".$my_cash."</pre>";

$mood = "sad";
echo "Oh well, I'm going home.";
}
return $mood;
}

Lo o king at o ur if /e lse st at e m e nt s, we can see that we make all kinds o f co mpariso ns between $ m y_cash
and the vario us cereal prices, yet no matter what we set $ m y_cash to befo re we pass it to
what s_m y_e m o t io n(), it co mes up blank within what s_m y_e m o t io n(). And then the erro r beco mes
clear: within what s_m y_e m o t io n(), the parameter sho uld be called $ cash_m o ne y, NOT $my_cash!

And so , Sherlo ck, it lo o ks like we have so lved the mystery o f the lo gical e rro r. We can no w remove the
extraneo us echo and print_r statements and fix the pro blem, o nce and fo r all.
Type the fo llo wing green co de into Co deRunner:
<?
function mantra($the_sound,$the_number = 10) {
$chant = 1;
while ($chant <= $the_number) { //first we took out the rogue semicolon...
echo $the_sound."... ";
}
}

function Mood_Chant($my_mood){
if ($my_mood == "happy") {
mantra("OM");
$after_chant = "<br/>I feel serene now.";
}
else if ($my_mood == "sad") {
mantra("okay");
$after_chant = "<br/>I feel better now.";
}
else if ($my_mood == "angry") {
mantra("mississippi");
$after_chant = "<br/>Ahhh, much better. I've calmed down now.";
}
else if ($my_outlook == "indifferent") {
mantra("Wake up");
$after_chant = "<br/>I'm awake now.";
}
else {
mantra("Try harder");
$after_chant = "<br/>I'll try harder now.";
}
return $after_chant;
}

function whats_my_emotion($cereal_prices, $cash_money) {


$total = array_sum($cereal_prices); //array_sum is a built-in PHP function
if ($total < $cash_money) {
$mood = "happy";
echo "I'll buy both Captain Crunch and Fruit Loops!";
}
else if ($cereal_prices['Captain_Crunch'] < $cash_money ) {
$mood = "indifferent";
echo "I'll buy Captain Crunch.";
}
else if ($cereal_prices['Captain_Crunch'] > $cash_money && $cereal_prices['Fr
uit_Loops'] < $cash_money ){
$mood = "angry";
echo "Fine! I'll get some Fruit Loops.";
}
else {
$mood = "sad";
echo "Oh well, I'm going home.";
}
return $mood;
}
//then we added the delimiter here...
?>
<h3>The emotional roller-coaster of buying breakfast cereal</h3>
<?
$cereal_prices = array('Captain_Crunch' => 5, 'Fruit_Loops' => 3);
$my_cash = 4;
?>
I have $<? echo $my_cash; ?> in my pocket, and I want to buy some Captain Crunch
!<br/>
<ul>
<li>Captain Crunch costs $<? echo $cereal_prices['Captain_Crunch']; ?></li>
<li>Fruit Loops costs $<? echo $cereal_prices['Fruit_Loops']; ?></li>
</ul>
<?
//then we added the delimiter here...

$my_mood = whats_my_emotion($cereal_prices, $my_cash);


if (!($my_mood == "sad")) {
$after_chant_mood = Mood_Chant($my_mood, $chant_number);
}
echo "<br/>".$after_chant_mood;

?>

Infinite Loops, Infinite Headaches


Preview this:

The emotional roller-coaster of buying breakfast cereal


I have $4 in my pocket, and I want to buy some Captain Crunch!

Captain Crunch costs $5


Fruit Loops costs $3

Fine! I'll get some Fruit Loops.mississippi... mississippi... mississippi... mississippi... mississippi...
mississippi... mississippi... mississippi... mississippi... mississippi... mississippi... mississippi...
mississippi... mississippi... mississippi... mississippi... mississippi... mississippi... mississippi... mississippi...
mississippi... mississippi... mississippi... mississippi... mississippi... mississippi... mississippi... mississippi...
mississippi... mississippi... mississippi... mississippi... mississippi... mississippi... mississippi... mississippi...

YIKES, MAKE IT STOP! This is o ne o f the wo rst erro rs o f all: inf init e lo o ps. It causes memo ry leaks in yo ur
co mputer, aching in yo ur head, and it may very well have crashed yo ur entire bro wser...we ho pe that wasn't
the case.

This brings us to the Fifth Rule o f Debugging: Always end your loops!

Take a lo o k at o ur while lo o p:
function mantra($the_sound,$the_number = 10) {
$chant = 1;
while ($chant <= $the_number) {
echo $the_sound."... ";
}
}

The go o d news is, in o ur case it's easy to see what went wro ng. The while lo o p is set to end when $ chant is
gre at e r t han $ t he _num be r, which defaults to 10 . But we never increased $ chant . Let's fix it!
Type the fo llo wing into Co deRunner:
<?
function mantra($the_sound,$the_number = 10) {
$chant = 1;
while ($chant <= $the_number) { //first we took out the rogue semicolon...
echo $the_sound."... ";
$chant++;
}
}

function Mood_Chant($my_mood){
if ($my_mood == "happy") {
mantra("OM");
$after_chant = "<br/>I feel serene now.";
}
else if ($my_mood == "sad") {
mantra("okay");
$after_chant = "<br/>I feel better now.";
}
else if ($my_mood == "angry") {
mantra("mississippi");
$after_chant = "<br/>Ahhh, much better. I've calmed down now.";
}
else if ($my_outlook == "indifferent") {
mantra("Wake up");
$after_chant = "<br/>I'm awake now.";
}
else {
mantra("Try harder");
$after_chant = "<br/>I'll try harder now.";
}
return $after_chant;
}

function whats_my_emotion($cereal_prices, $cash_money) {


$total = array_sum($cereal_prices); //array_sum is a built-in PHP function
if ($total < $cash_money) {
$mood = "happy";
echo "I'll buy both Captain Crunch and Fruit Loops!";
}
else if ($cereal_prices['Captain_Crunch'] < $cash_money) {
$mood = "indifferent";
echo "I'll buy Captain Crunch.";
}
else if ($cereal_prices['Captain_Crunch'] > $cash_money && $cereal_prices['Fr
uit_Loops'] < $cash_money){
$mood = "angry";
echo "Fine! I'll get some Fruit Loops.";
}
else {
$mood = "sad";
echo "Oh well, I'm going home.";
}
return $mood;
}
//then we added the delimiter here...
?>
<h3>The emotional roller-coaster of buying breakfast cereal</h3>
<?
$cereal_prices = array('Captain_Crunch' => 5, 'Fruit_Loops' => 3);
$my_cash = 4;
?>
I have $<? echo $my_cash; ?> in my pocket, and I want to buy some Captain Crunch
!<br/>
<ul>
<li>Captain Crunch costs $<? echo $cereal_prices['Captain_Crunch']; ?></li>
<li>Fruit Loops costs $<? echo $cereal_prices['Fruit_Loops']; ?></li>
</ul>

<?
//then we added the delimiter here...

$my_mood = whats_my_emotion($cereal_prices, $my_cash);


if (!($my_mood == "sad")) {
$after_chant_mood = Mood_Chant($my_mood, $chant_number);
}
echo "<br/>".$after_chant_mood;

?>

Preview this:

The emotional roller-coaster of buying breakfast cereal


I have $4 in my pocket, and I want to buy some Captain Crunch!

Captain Crunch costs $5


Fruit Loops costs $3

Fine! I'll get some Fruit Loops.mississippi... mississippi... mississippi... mississippi... mississippi...
mississippi... mississippi... mississippi... mississippi... mississippi...

Ahhh, much better. I've calmed down now.

Ahh, much better. And altho ugh it was quite the o rdeal, we're all the better fo r it. Pat yo urself o n the back and raise yo ur
glass to stress relief thro ugh Debugging!

Notes on Scalable Programming


No w that yo u kno w the Rules o f Debugging, yo u're almo st ready to put them to the test by building so me large-scale
pro jects. Ho wever, befo re yo u go o n, it's impo rtant to stress so me very impo rtant po ints to help reduce your stress.

Before you Code, Pseudocode


What's pse udo co de ? Just a little jo t-do wn o f yo ur pro gram lo gic in English (o r whatever yo ur native
language may be). Like this:

Here's ho w we might pseudo co de whats_my_emo tio n():


If I have enough money to buy both cereals,
My mood is happy.
Otherwise, if I have enough money to buy Captain Crunch,
My mood is indifferent.
Otherwise, if I can't buy Captain Crunch, but can buy Fruit Loops,
My mood is angry.
Otherwise, I'm sad no matter what.

Pse udo co de is a way fo r yo u to o rganize yo ur tho ughts and design yo ur lo gic befo re yo u start co ding yo ur
pro gram. Think o f it as a blueprint fo r yo ur so ftware develo pment. Using pseudo co de, yo u can take a lo o k at
the big picture and catch any flaws in yo ur design--before they cause yo u a week's wo rth o f debugging. Plus,
yo u can refer back to it as yo u go to ensure that yo u're sticking to yo ur o riginal design.

Make your Program Readable


What if we had co ded whats_my_emo tio n() like this?

function what_is_it($a, $b = false) {


if ($a >= $b) {
$c = "happy";
}
else if ($d[0] < $b) {
$c = "indifferent";
}
else if ($d[0] > $b && $d[1] < $b) {
$c = "angry";
}
else {
$c = "sad";
}
return $c;
}

Sure, we kno w exactly what it means at the time we write it, but when we go back later, we might no t have a
clue what any o f it means, rendering it essentially wo rthless. And by the way, if yo u write co de like this, fo rget
ever getting pro mo ted - yo u wo n't find anyo ne who can decipher yo ur co de eno ugh to take o ver yo ur lo wer
po sitio n. Yo u'd be stuck with it, buddy.

So just be sure to use readable, intuitive variable, and functio n names all the time, every time. If yo u find
yo urself slipping into using vague names, just remember what we to ld yo u abo ut pro mo tio n. That sho uld
snap yo u back into shape.

Comment Until You're Blue in the Face


By the same to ken, yo u can kick yo ur pro gram's readability up a no tch by using co mments whenever yo u can.
Use them to help recall what yo u've do ne, o r to indicate to o ther pro grammers what yo ur functio ns do . That's
why they're there after all.

In particular, it's imperative that yo u start o ff each pro gram, and every functio n within it, with a syno psis o f the
functio ns it perfo rms, parameters it takes, and what it returns.

Like this:
function whats_my_emotion($cereal_prices, $cash_money) {
#whats_my_emotion returns an emotion of happy, indifferent, angry or sad base
d upon
#two parameters, $cereal_prices -- an array of floats -- and float $cash_mone
y.
$total = array_sum($cereal_prices); //array_sum is a built-in PHP function
if ($total < $cash_money) {
$mood = "happy";
echo "I'll buy both Captain Crunch and Fruit Loops!";
}
else if ($cereal_prices['Captain_Crunch'] < $cash_money) {
$mood = "indifferent";
echo "I'll buy Captain Crunch.";
}
else if ($cereal_prices['Captain_Crunch'] > $cash_money && $cereal_prices['Fr
uit_Loops'] < $cash_money){
$mood = "angry";
echo "Fine! I'll get some Fruit Loops.";
}
else {
$mood = "sad";
echo "Oh well, I'm going home.";
}
return $mood;
}

This will beco me mo re and mo re impo rtant as yo u build mo re reusable co de, and even libraries which can be
shared by o thers--either within yo ur co mpany, o r within the o pe n-so urce co m m unit y.

Code in Bite-Size Chunks


Yo u'll no tice thro ugho ut these lesso ns that o ur cho sen pro cess o f learning to build pro grams is extremely
repetitio us - we typed a bit o f co de, Previewed it, added a little mo re co de, Previewed it, and so o n.

If yo u pro gram o ne small part o f yo ur co de at a time, yo u'll be much less likely to be o verwhelmed with bugs
and lo gical erro rs when it co mes time to test. This is where yo ur pseudo co de can help as well, by sho wing
yo u where yo u can divide yo ur large pro gram into smaller, "bite-size" chunks to make it mo re manageable.

Debug as You Work


There's no thing wo rse than writing a HUGE amo unt o f co de, o nly to find it's a co mplete mess. As lo ng as yo u
Preview o ften, yo u'll catch bugs as yo u go alo ng, which will make yo ur life much easier in the lo ng run.

Reuse Functions as Much as Possible


What if we had written several different functio ns instead o f o ne what s_m y_e m o t io n(), o r simply co pied
and pasted the same co de thro ugho ut o ur pro gram? Instead o f fixing the co de o nce, we wo uld have had to
deal with it o ver and o ver again.

The biggest argument fo r creating f unct io ns fo r anything and everything: if so mething go es wro ng with the
co de, yo u o nly have to debug it o nce , then every time it's called, it wo rks.

Always create a functio n fo r any finite task, even if yo u're no t sure yo u'll use it mo re than o nce. Yo u'll be
surprised at ho w useful it will beco me as yo u co ntinue pro gramming.

Utilize Available Resources


As if we haven't been preaching it eno ugh: we live in an age where info rmatio n is always available. There are
reference bo o ks, Safari acco unts, and web sites like PHP.net. Use them. And if yo u can't find yo ur answer,
there are co mmunities o f millio ns o f PHP pro grammers just like yo urself yo u can co nsult. Do n't be afraid to
ask questio ns!

Can yo u believe ho w far yo u've co me? So far yo u've learned all the basics o f PHP yo u need to get go ing with so me meaty web
pro jects. And fro m no w o n, that's exactly what yo u're go ing to do .

Do n't fo rget to Save yo ur wo rk and hand in yo ur assignm e nt s fro m yo ur syllabus. See yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Forms in PHP
As pro mised, yo u're abo ut to put the material yo u've learned into ro bust, real-wo rld applicatio ns. Until no w, there has been o nly
o ne thing missing fro m yo ur skillset preventing this: use r input .

PHP was created specifically to wo rk with the internet - to make the web surfer's life easier by custo mizing his experience, and
to make the pro grammer's life easier by making that custo mizatio n co nvenient fo r her. But witho ut a way to gather info rmatio n
fro m the web surfer, all the co nvenience and po wer o f PHP is wo rthless. What go o d is custo mizatio n if the user's needs aren't
met?

We are able to gather user input thro ugh a little HTML tag called <f o rm >. Since we'll be using HTML and PHP in tandem, be
prepared to use bo t h HT ML and PHP synt ax. Let's go !

Forms Review
Start with an HTML fo rm. Make sure yo u're using HT ML syntax, and TYPE the fo llo wing:
CODE TO TYPE:

<body>
<h3>Contact ACME Corporation</h3>
<form method="POST" action="contact.php">
<table>
<tr>
<td align="right">
Name:
</td>
<td align="left">
<input type="text" size="25" name="name" value="">
</td>
</tr>
<tr>
<td align="right">
Email:
</td><td align="left">
<input type="text" size="25" name="email" value="">
</td>
</tr>
<tr>
<td align="right">
Type of Request:
</td>
<td align="left">
<select name="whoami">
<option value="" />Please choose...
<option value="newcustomer" />I am interested in becoming a customer.
<option value="customer" />I am a customer with a general question.
<option value="support" />I need technical help using the website.
<option value="billing" />I have a billing question.
</select>
</td>
</tr>
<tr>
<td align="right">
Subject:
</td>
<td align="left">
<input type="text" size="50" max="50" name="subject" value="">
</td>
</tr>
<tr>
<td align="right" valign="top">
Message:
</td>
<td align="left">
<textarea name="message" cols="50" rows="8">
</textarea>
</td>
</tr>
<tr>
<td colspan="2" align="left">
How did you hear about us?
<ul>
<input type="radio" name="found" value="wordofmouth" />Word of Mouth<br/>
<input type="radio" name="found" value="search" />Online Search<br/>
<input type="radio" name="found" value="article" />Printed publication/article<br/>
<input type="radio" name="found" value="website" />Online link/article<br/>
<input type="radio" name="found" value="other" />Other
</ul>
</td>
</tr>
<tr>
<td colspan="2">
<input type="checkbox" name="update1" checked="checked">Please email me updates about y
our products.<br/>
<input type="checkbox" name="update2">Please email me updates about products from third
-party partners.
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="SUBMIT" />
</td></tr>
</table>
</form>
</body>

Yo u'll see this:

Contact ACME Corporation

Name:
Email:

Type of Request: Please choose...


Subject:
Message:

How did you hear about us?

Word of Mouth
Online Search
Printed publication/article
Online link/article
Other

Please email me updates about your products.


Please email me updates about products from third-party partners.

SUBM IT

Lo o k familiar? This is a simple co ntact fo rm, where a user can inquire abo ut the services o n a website and give a little
info rmatio n abo ut him/herself. Also no tewo rthy is that it co ntains all the majo r fo rm types: t e xt , t e xt are a, se le ct ,
radio , che ckbo x, and subm it .

Each fo rm element has a nam e attribute and a value attribute, except fo r t e xt are a, which has an ending tag instead o f
a value attribute. Furthermo re, radio butto ns all have the same name to ensure o nly o ne is checked, while
che ckbo xes have different names so that any o f them can be checked. se le ct tags co ntain their names and values
within separate o pt io n tags, fo r that nice dro p-do wn-menu effect.
Yo u mean it doesn't lo o k familiar? We're assuming this is review fo r yo u - if yo u're co mpletely lo st, yo u
Note may want to take a lo o k at o ur HTML and CSS co urse.

It's a nice-lo o king fo rm, but if yo u want so mething do ne with that info rmatio n, yo u're go ing to have to create a PHP
script to pro cess the input. Go ahead and Save yo ur f o rm -- yo u can name it co nt act .ht m l.

Using Superglobals to Read Form Inputs


No w, let's switch Co deRunner to PHP and start a new file.

In PHP, type the fo llo wing:

<?php

echo "<h3>Thank you!</h3>";


echo "Here is a copy of your request:<br/><br/>";

echo "Name: ".$_POST['name']."<br/>";


echo "Email: ".$_POST['email']."<br/>";
echo "Type of Request: ".$_POST['whoami']."<br/>";
echo "Subject: ".$_POST['subject']."<br/>";
echo "Message: ".$_POST['message']."<br/>";
echo "How you heard about us: ".$_POST['found']."<br/>";
echo "Update you about our products: ".$_POST['update1']."<br/>";
echo "Update you about partners' products: ".$_POST['update2']."<br/>";

?>

Preview this:

Thank You!
Here is a copy of your request:

Name:
Email:
Type of Request:
Subject:
Message:
How you heard about us:
Update you about our products:
Update you about partners' products:

Well, that didn't do much go o d. And what's this $ _POST [] array anyway??

But wait, there's mo re. Save this PHP file and call it co nt act .php. No w, switch back to HT ML in Co deRunner, where
yo u sho uld still have yo ur co nt act .ht m l file ready.

Preview this, and fill in the fo rm:


Contact ACME Corporation

Name: Trish
Email: trish@myemail.com

Type of Request: I need technical help using the website.


Subject: Please help!
Message: I can't get the darn thing to work!

How did you hear about us?

Word of Mouth
Online Search
Printed publication/article
Online link/article
Other

Please email me updates about your products.


Please email me updates about products from third-party partners.

SUBM IT

No w, within yo ur Preview windo w, click SUBMIT. What did yo u get?

Ho pefully yo u go t so mething like this:

Thank You!
Here is a copy of your request:

Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please help!
Message: I can't get the darn thing to work!
How you heard about us: website
Update you about our products: on
Update you about partners' products:

So why did it wo rk this time? Here's where the magic o f that $ _POST [] array is revealed.
Take ano ther lo o k at the fo rm tag in co ntact.html:
<form method="POST" action="contact.php">

If yo u remember, fo rms themselves can be submitted using several different metho ds - two o f the mo st impo rtant
metho ds are GET and POST . If yo u've ever pro grammed a web applicatio n in a different language - say Perl o r C -
yo u might also remember using co mplicated CGI libraries to extract fo rm data fro m either the que ry st ring in the case
o f the GET metho d, o r fro m the e nviro nm e nt variable s in the case o f the POST metho d.

Ho wever, because PHP was created with the web in mind, this pro cess has been greatly simplified, using special
variables called supe rglo bals.

Let's lo o k at co ntact.php again:


<?php

echo "<h3>Thank you!</h3>";


echo "Here is a copy of your request:<br/><br/>";

echo "Name: ".$_POST['name']."<br/>";


echo "Email: ".$_POST['email']."<br/>";
echo "Type of Request: ".$_POST['whoami']."<br/>";
echo "Subject: ".$_POST['subject']."<br/>";
echo "Message: ".$_POST['message']."<br/>";
echo "How you heard about us: ".$_POST['found']."<br/>";
echo "Update you about our products: ".$_POST['update1']."<br/>";
echo "Update you about partners' products: ".$_POST['update2']."<br/>";

?>

Did yo u no tice so mething familiar abo ut the key indices o f $ _POST [] -- nam e , e m ail, who am i, etc.? Yo u see, PHP
do es all the wo rk fo r yo u here - it pro cesses the fo rm input and places all the values into the supe rglo bal array
$ _POST [], an asso ciative array with the key indices co rrespo nding to the fo rm element names. This is do ne
auto matically, whenever a fo rm is submitted using the POST m e t ho d, and the array wo rks in any sco pe - that's why
it's called a supe rglo bal variable.

By co nventio n, we do n't no rmally use the undersco re at the beginning o f variable names (as in
Note $ _POST ). Ho wever, they are used in supe rglo bals to prevent any clashing with yo ur o wn variable
names.

What do yo u do if yo u use the GET m e t ho d in yo ur fo rm? Experiment with this and find o ut. If yo u need help, check
o ut php.net.

Extracting Superglobals into Variables


As if the supe rglo bal variables weren't easy eno ugh, PHP go es even further to make reading fo rm inputs easy fo r
yo u.
In PHP, change co ntact.php with the fo llo wing blue co de:

<?php

extract($_POST, EXTR_PREFIX_SAME, "post");

echo "<h3>Thank you!</h3>";


echo "Here is a copy of your request:<br/><br/>";

echo "Name: ".$name."<br/>";


echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";
echo "Update you about our products: ".$update1."<br/>";
echo "Update you about partners' products: ".$update2."<br/>";

?>

Save co nt act .php again, then go back to co nt act .ht m l and Preview. What did yo u get?

Preview co ntact.html and submit the fo rm like befo re:

Thank You!
Here is a copy of your request:

Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please help!
Message: I can't get the darn thing to work!
How you heard about us: website
Update you about our products: on
Update you about partners' products:

Wo w - it wo rked even witho ut the $ _POST [] array! This is yet ano ther simplificatio n in the pro cess that can be do ne
thro ugh the built-in functio n e xt ract (). In this case, the fo rm elements passed thro ugh the $ _POST [] array have been
extracted into PHP variables, accessible by anything within the pro gram. We indicated to e xt ract () that we wanted the
PHP variable names to co rrespo nd to the fo rm element names by passing in the flag EXT R_PREFIX_SAME as a
parameter. Yo u can read mo re abo ut e xt ract () here: http://www.php.net/manual/en/functio n.extract.php.

In previo us versio ns o f PHP, a php co nfig directive called re gist e r glo bals auto matically created glo bal
Note variables fro m GET and POST fo rm elements. Ho wever, many dangers aro se in using register glo bals,
and as a result, PHP has remo ved them fro m PHP 5 and newer versio ns.

Supe rglo bals are brilliant inno vatio ns in web pro gramming - all built into PHP to make yo ur wo rld an easier place to
live. No t to mentio n our wo rld - did yo u no tice just ho w short this lesso n is? Exactly.

Nesting Variable Names


Just o ne mo re co o l feature befo re we mo ve o n...
In PHP, change co ntact.php with the fo llo wing, in blue:
<?php

extract($_POST, EXTR_PREFIX_SAME, "post");

echo "<h3>Thank you!</h3>";


echo "Here is a copy of your request:<br/><br/>";

echo "Name: ".$name."<br/>";


echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

?>

Preview co ntact.html and submit the fo rm like befo re:

Thank You!
Here is a copy of your request:

Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please help!
Message: I can't get the darn thing to work!
How you heard about us: website
update1: on
update2:

Did yo u see what happened there? We were able to dynamically co nstruct the name o f o ur "update#" fo rm elements
thro ugh a f o r lo o p, and then access the value o f that element thro ugh the variables we created with e xt ract (). This
was do ne by nesting variable names.

Take ano ther lo o k:


for ($i = 1; $i <= 2; $i++) {
$element_name = "update".$i;
echo $element_name.": "; << evaluates to "update1" or "update2"
echo $$element_name; << evaluates to $update1 or $update2, whose values are "on" or
"off"
echo "<br/>";
}

Nesting variable names is just like all the nesting we did in previo us lesso ns - first $ e le m e nt _nam e is evaluated,
and then that value is used to evaluate the nested $ ($ e le m e nt _nam e ). Name nesting can be do ne with ALL
variables, ho wever, it's especially useful when yo u create dynamic fo rm names and then need to read them with the
variables passed in thro ugh supe rglo bals and e xt ract (). It's definitely wo rth learning this handy trick.
We're just getting warmed up with fo rms. Do n't fo rget to Save yo ur wo rk and hand in yo ur assignm e nt s fro m yo ur syllabus.
See yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Utilizing Internet Tools
In the last lesso n, we created a co ntact fo rm fo r custo mers to co mmunicate with the custo mer suppo rt department o f a
co rpo ratio n. But it's no t quite ready fo r prime time yet. So far, we have no way o f kno wing what kind o f co mputer o r bro wser the
custo mer is using, no way to catch inco mplete fo rm entries, and no way to , well, send the message o ut.

It's time to fix this! Fire up Co deRunner and o pen the two files we were wo rking o n befo re: co nt act .ht m l and co nt act .php.

Environment and Server Variables


Preview co ntact.html and submit the fo rm like befo re:

Thank You!
Here is a copy of your request:

Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please help!
Message: I can't get the darn thing to work!
How you heard about us: website
update1: on
update2:

Have yo u ever received a custo mer suppo rt request like this? We have. It's mo re co mmo n than yo u may think, and it
can leave yo u scratching yo ur head—this custo mer can't get the darn website to wo rk, yet leaves the details o f the
pro blem to yo ur mind-reading skills.

Let's lo o k into o ur crystal ball...


In PHP, change co ntact.php as sho wn in blue:
<?php

extract($_POST, EXTR_PREFIX_SAME, "post");

echo "<h3>Thank you!</h3>";


echo "Here is a copy of your request:<br/><br/>";

echo "Name: ".$name."<br/>";


echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_X_FORWA
RDED_FOR'];

?>

Switch to co ntact.html, Preview, and submit the fo rm like befo re:

Thank You!
Here is a copy of your request:

Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please help!
Message: I can't get the darn thing to work!
How you heard about us: website
update1: on
update2:
You are currently working on Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418
(KHTML, like Gecko) Safari/417.9.2
The IP address of the computer you're working on is 63.171.219.74

When it co mes to custo mer suppo rt, just as impo rtant as the custo mer's request is kno wing where the custo mer is
co ming fro m—perhaps geo graphically, but mo re impo rtantly in the sense o f what o perating system (Windo ws, Mac)
and bro wser (Safari, Internet Explo rer, Firefo x) they're using.

Luckily, the fo lks who wo rked o n o ur very first web bro wsers way back in the day, already tho ught o f this. They created
so mething called CGI (Common Gateway Interface) Enviro nm e nt Variable s, which tell us a lo t abo ut bo th the
clie nt —that's the custo mer's co mputer—as well as the se rve r -- that's the co mputer where yo ur PHP script resides
(in o ur case, it's sitting in Champaign, Illino is).
Take ano ther lo o k at this co de:
echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];
echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_X_FORWA
RDED_FOR'];

Yo u guessed it—$ _SERVER[] is ano ther supe rglo bal array in PHP. That undersco re(_) at the beginning tends to
give it away. The info rmatio n that $ _SERVER[] ho lds? Enviro nm e nt variable s like HT T P_USER_AGENT and
HT T P_X_FORWARDED_FOR. But what do they mean?

No w take ano ther lo o k at the o utput:


You are currently working on Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/4
18 (KHTML, like Gecko)
Safari/417.9.2
The IP address of the computer you're working on is 63.171.219.74

Not so luckily, the fo lks who created the enviro nment variables didn't make them easy to decipher. Here's a little
translatio n fo r the two we're using:

HT T P_USER_AGENT gives yo u info rmatio n abo ut the co mputer and web so ftware yo ur custo mer is
using. Since yo u're testing yo ur o wn fo rm, it sho uld be telling yo u what co mputer and web so ftware you're
using. The fo rmat is so mething like this: o pe rat ing syst e m /ve rsio n (m o re inf o ) we b library/ve rsio n
(m o re inf o ) we b bro wse r/ve rsio n (m o re inf o ).

In o ur case, we go t the info rmatio n Mo zilla/5 .0 (Macint o sh; U; PPC Mac OS X; e n) Apple We bKit /4 18 (KHT ML,
like Ge cko ) Saf ari/4 17 .9 .2. Very cryptically, this tells us that we are o n a Macinto sh co mputer with a Mac OS X
o perating system, using the Safari web bro wser. Obvio usly, your result will mo st likely be different fro m this—yo u
might be o n a Windo ws XP co mputer, fo r instance, using Internet Explo rer (MSIE). Here is a list o f mo re bro wsers than
yo u'll ever care to kno w, and their HTTP_USER_AGENT translatio ns. Can yo u find yo urs?

HT T P_X_FORWARDED_FOR gives yo u the IP addre ss o f either yo ur custo mer's co mputer, o r if yo ur


custo mer is using an Internet Service Pro vider like AOL, the IP address o f o ne o f its servers. What's an IP
(Int e rne t Pro t o co l) addre ss? Every co mputer o n the internet has o ne -- a unique identifier, cho sen
within the Internet Pro to co l Standard. It's useful to kno w, because it can indicate the custo mer's co untry o f
o rigin, thro ugh any Who is to o l. Mo re impo rtantly, if it has been determined that a particular custo mer is a
fraud, there are ways to blo ck the IP address fro m ever getting to yo ur site—so mething yo u will learn in a
later co urse.

There are lo ts o f useful e nviro nm e nt variable s. Here is a very useful list to reference.

Using HT T P Headers
Ano ther impo rtant issue in custo mer suppo rt—and really any interface that requires fo rm input—is ensuring that all
fields are pro perly filled in. Ho w can yo u help a custo mer if he do esn't include his email address o r co ntact info ? But o f
co urse he'll include it, right? Yo u'd be surprised.
In PHP, change co ntact.php with the fo llo wing blue co de:

<?php

#We used the superglobal $_POST here


if (!($_POST['name'] && $_POST['email'] && $_POST['whoami']
&& $_POST['subject'] && $_POST['message'])) {
echo "Please make sure you've filled in all required information.";
exit();
}

extract($_POST, EXTR_PREFIX_SAME, "post");

echo "<h3>Thank you!</h3>";


echo "Here is a copy of your request:<br/><br/>";

echo "Name: ".$name."<br/>";


echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_X_FORWA
RDED_FOR'];

?>

No tice the new built-in PHP functio n we used here: e xit (). This essentially sto ps the pro gram in its
Note tracks. Ho w's that fo r lack o f co mmitment?

Switch to co ntact.html, Preview, and submit the fo rm like befo re—o nly this time, try leaving so mething blank:

Please make sure you've filled in all required information.

So essentially when so meo ne leaves so mething blank, we're letting them kno w abo ut it. But no w the custo mer has to
go back to the fo rm and find o ut what's wro ng. What if we co uld take them back to the fo rm auto matically? Let's give it a
sho t:
In PHP, change co ntact.php with the fo llo wing, in blue:
<?php

#We used the superglobal $_POST here


if (!($_POST['name'] && $_POST['email'] && $_POST['whoami']
&& $_POST['subject'] && $_POST['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";

$url = "http://".$_SERVER['HTTP_HOST']."/contact.html";
header("Location: ".$url);
exit();
}

extract($_POST, EXTR_PREFIX_SAME, "post");

echo "<h3>Thank you!</h3>";


echo "Here is a copy of your request:<br/><br/>";

echo "Name: ".$name."<br/>";


echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_X_FORWA
RDED_FOR'];

?>

Switch to co ntact.html, Preview yo ur fo rm, and submit it, leaving so mething blank. Yo u sho uld get this:
Contact ACME Corporation

Name:
Email:

Type of Request: Please choose...


Subject:
Message:

How did you hear about us?

Word of Mouth
Online Search
Printed publication/article
Online link/article
Other

Please email me updates about your products.


Please email me updates about products from third-party partners.

SUBM IT

Who a! What just happened? If yo u left so mething blank o n yo ur fo rm and submitted it, yo u just go t the same fo rm back,
blank again.

Let's take ano ther lo o k at this co de:


$url = "http://".$_SERVER['HTTP_HOST']."/contact.html";
header("Location: ".$url);
exit();

Yo u may already kno w that all HTML-based web pages use the Hype rT e xt T ransf e r Pro t o co l (HT T P) to render
pro perly in yo ur web bro wser—that's why yo u always see ht t p:// at the beginning o f every web address. But what yo u
may NOT kno w is that befo re any HTML is rendered o n yo ur web bro wser, a series o f invisible he ade rs are passed
so that yo ur bro wser kno ws exactly what to do with the co de. Mo st o f these headers are pretty o bscure, but a few are
extremely useful. Click here fo r a reference.

Of co urse, since PHP embeds HTML within its co de, it can also manipulate HT T P he ade rs thro ugh the built-in
functio n he ade r(). In this case, we were able to set the header " Lo cat io n: " with the URL o f the co ntact fo rm
co nt act .ht m l we created. As a result o f sending that header, the bro wser redirected the user back to the fo rm.

Any headers that are sent using he ade r() must co me BEFORE any PHP o r HTML o utput. Otherwise, the
Note bro wser will get co nfused, and next thing yo u kno w, yo u're debugging.

Yo u'll also no tice we used ano ther e nviro nm e nt variable , called HT T P_HOST . This variable returns the do m ain
nam e o f the web address where yo ur co nt act .php script resides.
In o ur case, o ur do main name, o r HTTP_HOST, is jo sh.o nza.ne t . It is a live web site, o n the internet fo r everyo ne to
see: http://jo sh.o nza.net/. Pretty lame web site, huh? Keep this in mind when yo u create yo ur website using yo ur o wn
do main name—yo u co uld have a lame web site like us, o r yo u co uld have a pro fessio nal o nline po rtfo lio to sho w to
all yo ur friends, co lleagues, and po tential emplo yers when yo u apply fo r yo ur first LAMP-based pro gramming jo b.

Manipulating Query Strings


But we digress. And in the meantime, simply redirecting o ur po o r custo mer to a blank fo rm is a ho rrible way to treat
so meo ne who 's already frustrated with the website. There has to be a mo re user-friendly way to ask the custo mer to
fix a fo rm field befo re we submit it.

The pro blem is, since co nt act .ht m l is a static HTML page, we can't dynamically add anything to it—that's why it's
blank. And simply giving the erro r message "Please fix this" to the custo mer, like we did befo re, isn't user-friendly
either. What we need is a way to sho w the custo mer, nicely, exactly what he needs to fix o n the fo rm, witho ut lo sing any
o f the answers he's already filled in.

We can do this by converting the HTML fo rm into a PHP script o f its o wn. What yo u need to do is Save co nt act .ht m l
in PHP synt ax, but sure t o call it " co nt act _f o rm .php" . Or if yo u'd rather, just co py and paste the HTML co de
into a new PHP file.
Be sure yo u're in PHP, and add the fo llo wing blue co de to co ntact_fo rm.php:

<body>
<h3>Contact ACME Corporation</h3>
<form method="GET" action="contact.php">
<table>
<tr>
<td align="right">
Name:
</td>
<td align="left">
<input type="text" size="25" name="name" value="<? echo $_GET['name']; ?>" />
</td>
</tr>
<tr>
<td align="right">
Email:
</td><td align="left">
<input type="text" size="25" name="email" value="<? echo $_GET['email']; ?>" />
</td>
</tr>
<tr>
<td align="right">
Type of Request:
</td>
<td align="left">
<select name="whoami">
<option value="" />Please choose...
<option value="newcustomer"<?
if ($_GET['whoami'] == "newcustomer") {
echo " selected";
}
?> />I am interested in becoming a customer.
<option value="customer"<?
if ($_GET['whoami'] == "customer") {
echo " selected";
}
?> />I am a customer with a general question.
<option value="support"<?
if ($_GET['whoami'] == "support") {
echo " selected";
}
?> />I need technical help using the website.
<option value="billing"<?
if ($_GET['whoami'] == "billing") {
echo " selected";
}
?> />I have a billing question.
</select>
</td>
</tr>
<tr>
<td align="right">
Subject:
</td>
<td align="left">
<input type="text" size="50" max="50" name="subject" value="<? echo $_GET['subject']; ?
>" />
</td>
</tr>
<tr>
<td align="right" valign="top">
Message:
</td>
<td align="left">
<textarea name="message" cols="50" rows="8">
<? echo $_GET['message']; ?>
</textarea>
</td>
</tr>
<tr>
<td colspan="2" align="left">
How did you hear about us?
<ul>
<input type="radio" name="found" value="wordofmouth" />Word of Mouth<br/>
<input type="radio" name="found" value="search" />Online Search<br/>
<input type="radio" name="found" value="article" />Printed publication/article<br/>
<input type="radio" name="found" value="website" />Online link/article<br/>
<input type="radio" name="found" value="other" />Other
</ul>
</td>
</tr>
<tr>
<td colspan="2">
<input type="checkbox" name="update1" checked="checked" />Please email me updates about
your products.<br/>
<input type="checkbox" name="update2" />Please email me updates about products from thi
rd-party partners.
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="SUBMIT" />
</td></tr>
</table>
</form>
</body>

No w, Preview co ntact_fo rm.php:


Contact ACME Corporation

Name:
Email:

Type of Request: Please choose...


Subject:
Message:

How did you hear about us?

Word of Mouth
Online Search
Printed publication/article
Online link/article
Other

Please email me updates about your products.


Please email me updates about products from third-party partners.

SUBM IT

Yo u'll no tice here that we've switched the m e t ho d attribute in the HTML fo rm tag fro m POST to GET , and we've
intro duced so me PHP echo statements using the $ _GET [] supe rglo bal. But so far, no changes have taken place—
we still get the same blank fo rm with co nt act _f o rm .php as we did with co nt act .ht m l.

The ht m lspe cialchars() functio n can be used when o btaining the values fo r the input tags. Fo r example:

<input type="text" size="25" name="email" value="<? echo


htmlspecialchars($_GET['email'],ENT_QUOTES, 'UTF-8 '); ?>" /> </td>

Note This functio n co nverts so me predefined characters to HTML entities and will help to pro tect yo ur co de
against cro ss site scripting. A detailed discussio n o f web applicatio n security in beyo nd the sco pe o f this
co urse, but please check o ut the fo llo wing links fo r additio nal info rmatio n:

link
link.

Be sure to Save co nt act _f o rm .php, since the Lo cat io n: header will redirect yo u back to the saved versio n o f
co nt act _f o rm .php, NOT the Preview versio n.
Switch to co ntact.php, and make the fo llo wing changes in blue:
<?php

#We used the superglobal $_GET here


if (!($_GET['name'] && $_GET['email'] && $_GET['whoami']
&& $_GET['subject'] && $_GET['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";

$query_string = $_SERVER['QUERY_STRING'];
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php?".$query_string;

header("Location: ".$url);
exit();

extract($_GET, EXTR_PREFIX_SAME, "get");

echo "<h3>Thank you!</h3>";


echo "Here is a copy of your request:<br/><br/>";

echo "Name: ".$name."<br/>";


echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_X_FORWA
RDED_FOR'];

?>

Remember to save co ntact.php, then switch back to co ntact_fo rm.php and Preview.

When yo u submit the fo rm, be sure that yo u leave o ne field blank to see what happens:
Contact ACME Corporation

Name: Trish
Email: trish@myemail.com

Type of Request: I need technical help using the website.


Subject: Woops, I left the message field blank!
Message:

How did you hear about us?

Word of Mouth
Online Search
Printed publication/article
Online link/article
Other

Please email me updates about your products.


Please email me updates about products from third-party partners.

SUBM IT

No w here's so me real pro gress. When yo u submit the fo rm with a field o r two blank, the fo rm still co mes back—but
this time, all the fields at the to p have been filled in. This is much better, because no w the user do esn't have to redo
everything.

Let's take ano ther lo o k at the co de we used in co ntact.php:

#We used the superglobal $_GET here


if (!($_GET['name'] && $_GET['email'] && $_GET['whoami']
&& $_GET['subject'] && $_GET['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";

$query_string = $_SERVER['QUERY_STRING']
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php?".$query_string;
header("Location: ".$url);
exit();

extract($_GET, EXTR_PREFIX_SAME, "get");

We switched o ur fo rm to have m e t ho d=GET so that o ur data will co me thro ugh to o ur script fro m the que ry st ring.
The que ry st ring co nsists o f all the enco ded data yo u see after the questio n mark (?) in yo ur URL when yo u submit
the fo rm:

And, since we have the handy e nviro nm e nt variable QUERY_ST RING, we can simply use the $ _SERVER[]
superglo bal to grab it and send it back to co nt act _f o rm .php.

And if yo u lo o k again at co ntact_fo rm.php:


<input type="text" size="25" name="name" value="<? echo $_GET['name']; ?>" />

Yo u'll see that we were able to harness the que ry st ring yet again—thro ugh the superglo bal $ _GET []—to fill in the
input tags with the custo mer's o riginal data.

Customizing specific error messages


No w it's time to use o ur newly-fo rmed script co nt act _f o rm .php to tell the custo mer exactly what needs to
be do ne. To do this, ho wever, we first need to manipulate the que ry st ring a bit:

In PHP, switch to co ntact.php, and make the fo llo wing changes, in blue:

<?php

#We used the superglobal $_GET here


if (!($_GET['name'] && $_GET['email'] && $_GET['whoami']
&& $_GET['subject'] && $_GET['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";

$query_string = $_SERVER['QUERY_STRING'];
#add a flag called "error" to tell contact_form.php that something needs fixe
d
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php?".$query_string."&e
rror=1";
header("Location: ".$url);
exit();

extract($_GET, EXTR_PREFIX_SAME, "get");

echo "<h3>Thank you!</h3>";


echo "Here is a copy of your request:<br/><br/>";

echo "Name: ".$name."<br/>";


echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_
X_FORWARDED_FOR'];

?>
Make sure yo u Save co ntact.php, and switch to co nt act _f o rm .php:
In PHP, add the fo llo wing to co ntact_fo rm.php, in blue:
<?php

if ($_GET['error'] == "1") {
$error_code = 1; //this means that there's been an error and we need to noti
fy the customer
} else {
$error_code = 0;
}

?>

<body>
<h3>Contact ACME Corporation</h3>
<?
if ($error_code) {
echo "<div style='color:red'>Please help us with the following:</div>";
}
?>
<form method="GET" action="contact.php">
<table>
<tr>
<td align="right">
Name:
</td>
<td align="left">
<input type="text" size="25" name="name" value="<? echo $_GET['name']; ?>" />
<?
if ($error_code && !($_GET['name'])) {
echo "<b>Please include your name.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Email:
</td><td align="left">
<input type="text" size="25" name="email" value="<? echo $_GET['email']; ?>" />
<?
if ($error_code && !($_GET['email'])) {
echo "<b>Please include your email address.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Type of Request:
</td>
<td align="left">
<select name="whoami">
<option value="" />Please choose...
<option value="newcustomer"<?
if ($_GET['whoami'] == "newcustomer") {
echo " selected";
}
?> />I am interested in becoming a customer.
<option value="customer"<?
if ($_GET['whoami'] == "customer") {
echo " selected";
}
?> />I am a customer with a general question.
<option value="support"<?
if ($_GET['whoami'] == "support") {
echo " selected";
}
?> />I need technical help using the website.
<option value="billing"<?
if ($_GET['whoami'] == "billing") {
echo " selected";
}
?> />I have a billing question.
</select>
<?
if ($error_code && !($_GET['whoami'])) {
echo "<b>Please choose a request type.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Subject:
</td>
<td align="left">
<input type="text" size="50" max="50" name="subject" value="<? echo $_GET['subje
ct']; ?>" />
<?
if ($error_code && !($_GET['subject'])) {
echo "<b>Please add a subject for your request.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right" valign="top">
Message:
</td>
<td align="left">
<textarea name="message" cols="50" rows="8">
<? echo $_GET['message']; ?>
</textarea>
<?
if ($error_code && !($_GET['message'])) {
echo "<b>Please fill in a message for us.</b>";
}
?>
</td>
</tr>
<tr>
<td colspan="2" align="left">
How did you hear about us?
<ul>
<input type="radio" name="found" value="wordofmouth" />Word of Mouth<br/>
<input type="radio" name="found" value="search" />Online Search<br/>
<input type="radio" name="found" value="article" />Printed publication/article<b
r/>
<input type="radio" name="found" value="website" />Online link/article<br/>
<input type="radio" name="found" value="other" />Other
</ul>
</td>
</tr>
<tr>
<td colspan="2">
<input type="checkbox" name="update1" checked="checked" />Please email me update
s about your products.<br/>
<input type="checkbox" name="update2" />Please email me updates about products f
rom third-party partners.
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="SUBMIT" />
</td></tr>
</table>
</form>
</body>

Again, be sure to Save co ntact_fo rm.php, and then Preview, leaving o ne field blank. What did yo u get?

We get so mething like this:

Contact ACME Corporation


Please help us with the following:
Name: Please include your name.
Email: trish@myemail.com
Type of
Request: I need technical help using the website.
Subject: Woops, I left the message field blank!
Message:

Please f ill in a message f o


us.
How did you hear about us?

Word of Mouth
Online Search
Printed publication/article
Online link/article
Other

Please email me updates about your products.


Please email me updates about products from third-party partners.
MUCH better. No w the custo mer kno ws exactly what's wro ng, he can fix it, and submit the suppo rt request
easily.

Sending Emails
Finally, we can do what we wanted to do all alo ng: send the suppo rt request via email. Never o ne to let us do wn, PHP
has just the functio n fo r us: m ail(). Let's try it:
In PHP, switch to co ntact.php, and make the fo llo wing changes, in blue:

<?php

#We used the superglobal $_GET here


if (!($_GET['name'] && $_GET['email'] && $_GET['whoami']
&& $_GET['subject'] && $_GET['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";

$query_string = $_SERVER['QUERY_STRING'];
#add a flag called "error" to tell contact_form.php that something needs fixed
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php?".$query_string."&error=1"
;
header("Location: ".$url);
exit(); //stop the rest of the program from happening

extract($_GET, EXTR_PREFIX_SAME, "get");

#construct email message


$email_message = "Name: ".$name."
Email: ".$email."
Type of Request: ".$whoami."
Subject: ".$subject."
Message: ".$message."
How you heard about us: ".$found."
User Agent: ".$_SERVER['HTTP_USER_AGENT']."
IP Address: ".$_SERVER['REMOTE_ADDR'];

#construct the email headers


$to = "support@example.com"; //for testing purposes, this should be YOUR email address
.
//We will send the emails from our own server
$from = "anything@yourlogin.oreillystudent.com";

$email_subject = $_GET['subject'];

#now mail
mail($to, $email_subject, $email_message, "From: ".$from);

echo "<h3>Thank you!</h3>";


echo "Here is a copy of your request:<br/><br/>";

echo "Name: ".$name."<br/>";


echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_X_FORWA
RDED_FOR'];

?>
Save co nt act .php, switch to co ntact_fo rm.php, Preview, and submit the fo rm.

If yo u filled in all the required fields, yo u sho uld get so mething like befo re:

Thank You!
Here is a copy of your request:

Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please help!
Message: I can't get the darn thing to work!
How you heard about us: website
update1: on
update2:
You are currently working on Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418
(KHTML, like Gecko) Safari/417.9.2
The IP address of the computer you're working on is 63.171.219.74

Ho wever, this time, if yo u included yo ur o wn email in the $ t o variable, yo u sho uld have a brand new custo mer suppo rt
message in yo ur email inbo x.

Do n't fo rget to Save yo ur wo rk and hand in the assignm e nt s fro m yo ur syllabus. See yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Date and Time
Yo u'll find that Date and Time play a huge part in pro gramming - they are useful fo r timestamps, lo gs, and are needed in just
abo ut every database entry yo u'll create. And altho ugh they're so mewhat tricky to harness, PHP has do ne well in simplifying the
pro cess.

Open the two files we were wo rking o n befo re: co nt act _f o rm .php and co nt act .php.

Date and T ime Standards


Switch to co ntact.php, and make the fo llo wing changes, in green:
<?php

#We used the superglobal $_GET here instead of the register globals, for safety
if (!($_GET['name'] && $_GET['email'] && $_GET['whoami']
&& $_GET['subject'] && $_GET['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";

$query_string = $_SERVER['QUERY_STRING'];
#add a flag called "error" to tell contact_form.php that something needs fixed
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php?".$query_string."&error=1"
;
header("Location: ".$url);
exit(); //stop the rest of the program from happening

extract($_GET, EXTR_PREFIX_SAME, "get");

#construct email message


$email_message = "Name: ".$name."
Email: ".$email."
Type of Request: ".$whoami."
Subject: ".$subject."
Message: ".$message."
How you heard about us: ".$found."
User Agent: ".$_SERVER['HTTP_USER_AGENT']."
IP Address: ".$_SERVER['HTTP_X_FORWARDED_FOR'];

#construct the email headers


$to = "support@example.com"; //for testing purposes, this should be YOUR email address
.
//We will send the emails from our own server
$from = "anything@yourlogin.oreillystudent.com";

$email_subject = "CONTACT #".time().": ".$_GET['subject'];

#now mail
mail($to, $email_subject, $email_message, "From: ".$from);

echo "<h3>Thank you!</h3>";


echo "Here is a copy of your request:<br/><br/>";
echo "CONTACT #".time().":<br/>";
echo "Name: ".$name."<br/>";
echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_X_FORWA
RDED_FOR'];

?>
No tice we're breaking o ne o f o ur o wn cardinal rules here - do ubling up o n co de that co uld be taken care
Note o f with o ne functio n. Feel free to punish us within yo ur o wn co de.

Save co nt act .php, switch to co ntact_fo rm.php, Preview, and submit the fo rm.

If yo u filled in all the required fields, yo u sho uld get so mething like this:

Thank You!
Here is a copy of your request:

CONTACT # 1148955473:
Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please help!
Message: I can't get the darn thing to work!
How you heard about us: website
update1: on
update2:
You are currently working on Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418
(KHTML, like Gecko) Safari/417.9.2
The IP address of the computer you're working on is 63.171.219.74

Altho ugh we're using it as a t im e st am p here, the number we go t actually measures ho w many seco nds have passed
since Unix Epo ch -- that's a fancy name fo r January 1st, 19 70 , at midnight (0 0 :0 0 :0 0 ) GMT. Why is that time the Unix
Epo ch? No go o d reaso n really, except that so me early co mputer scientists agreed o n it a lo ng time ago as a dat e
and t im e st andard.

So unds nerdy, but it's really a go o d thing - it enables us to harness date and time, no t o nly in PHP, but also in mySQL
and lo ts o f o ther techno lo gy languages. Fo r instance, yo u'll be using PHP functio ns to pro cess SQL timestamps in
later co urses.

Date and T ime Functions


Obvio usly, dat e and t im e st andards weren't created fo r us to use merely as a unique identificatio n number -
altho ugh that's handy. What else can they do fo r us? Enter the built-in PHP functio ns.
Switch to co ntact.php, and make the fo llo wing changes, in green:

<?php

#We used the superglobal $_GET here instead of the register globals, for safety
if (!($_GET['name'] && $_GET['email'] && $_GET['whoami']
&& $_GET['subject'] && $_GET['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";

$query_string = $_SERVER['QUERY_STRING'];
#add a flag called "error" to tell contact_form.php that something needs fixed
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php?".$query_string."&error=1"
;
header("Location: ".$url);
exit(); //stop the rest of the program from happening

extract($_GET, EXTR_PREFIX_SAME, "get");

#construct email message


$email_message = "Message Date: ".date("F d, Y h:i a")."
Name: ".$name."
Email: ".$email."
Type of Request: ".$whoami."
Subject: ".$subject."
Message: ".$message."
How you heard about us: ".$found."
User Agent: ".$_SERVER['HTTP_USER_AGENT']."
IP Address: ".$_SERVER['HTTP_X_FORWARDED_FOR'];

#construct the email headers


$to = "support@example.com"; //for testing purposes, this should be YOUR email address
.
//We will send the emails from our own server
$from = "anything@yourlogin.oreillystudent.com";

$email_subject = "CONTACT #".time().": ".$_GET['subject'];

#now mail
mail($to, $email_subject, $email_message, "From: ".$from);

echo "<h3>Thank you!</h3>";


echo "Here is a copy of your request:<br/><br/>";
echo "CONTACT #".time().":<br/>";
echo "Message Date: ".date("F d, Y h:i a")."<br/>";
echo "Name: ".$name."<br/>";
echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_X_FORWA
RDED_FOR'];
?>

Again, if yo u Save co nt act .php, then Preview co ntact_fo rm.php, yo u might get so mething like this:

Thank You!
Here is a copy of your request:

CONTACT # 1148955473:
Message Date: May 29, 2006 10:25 pm
Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please help!
Message: I can't get the darn thing to work!
How you heard about us: website
update1: on
update2:
You are currently working on Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418
(KHTML, like Gecko) Safari/417.9.2
The IP address of the computer you're working on is 63.171.219.74

This time, instead o f a cryptic timestamp, the date o f the message has been nicely fo rmatted fo r us thro ugh the dat e ()
functio n.

Let's take ano ther lo o k:


echo "Message Date: ".date("F d, Y h:i a")."<br/>";

The param e t e r fo r the dat e () functio n is a special co ded f o rm at that PHP replaces with the pro per time/date data.
Fo r instance, " F" is replaced with the name o f the mo nth - in o ur case, May, and " a" is replaced with am o r pm ,
depending o n the time - in o ur case, pm . Here is the php.net reference fo r time/date fo rmats.

f o rm at Exam ple
De script io n
charact e r re t urne d value s
Day --- ---
d Day o f the mo nth, 2 digits with leading zero s 01 to 31
D A textual representatio n o f a day, three letters Mon thro ugh Sun
j Day o f the mo nth witho ut leading zero s 1 to 31
l
Sunday thro ugh
(lo wercase A full textual representatio n o f the day o f the week
Saturday
'L')
1 (fo r Mo nday)
N ISO-8 6 0 1 numeric representatio n o f the day o f the week (added in PHP 5.1.0 ) thro ugh 7 (fo r
Sunday)
st, nd, rd o r th.
S English o rdinal suffix fo r the day o f the mo nth, 2 characters
Wo rks well with j
0 (fo r Sunday)
w Numeric representatio n o f the day o f the week thro ugh 6 (fo r
Saturday)
z The day o f the year (starting fro m 0 ) 0 thro ugh 365
Week --- ---
Example: 42 (the
W ISO-8 6 0 1 week number o f year, weeks starting o n Mo nday (added in PHP 4.1.0 ) 42nd week in the
year)
Month --- ---
January thro ugh
F A full textual representatio n o f a mo nth, such as January o r March
December
m Numeric representatio n o f a mo nth, with leading zero s 01 thro ugh 12
M A sho rt textual representatio n o f a mo nth, three letters Jan thro ugh Dec
n Numeric representatio n o f a mo nth, witho ut leading zero s 1 thro ugh 12
t Number o f days in the given mo nth 28 thro ugh 31
Year --- ---
1 if it is a leap year,
L Whether it's a leap year
0 o therwise.
ISO-8 6 0 1 year number. This has the same value as Y, except that if the ISO week
Examples: 1999 o r
o number (W) belo ngs to the previo us o r next year, that year is used instead.
2003
(added in PHP 5.1.0 )
Examples: 1999 o r
Y A full numeric representatio n o f a year, 4 digits
2003
y A two digit representatio n o f a year Examples: 99 o r 03
Time --- ---
a Lo wercase Ante meridiem and Po st meridiem am o r pm
A Uppercase Ante meridiem and Po st meridiem AM o r PM
B Swatch Internet time 000 thro ugh 999
g 12-ho ur fo rmat o f an ho ur witho ut leading zero s 1 thro ugh 12
G 24-ho ur fo rmat o f an ho ur witho ut leading zero s 0 thro ugh 23
h 12-ho ur fo rmat o f an ho ur with leading zero s 01 thro ugh 12
H 24-ho ur fo rmat o f an ho ur with leading zero s 00 thro ugh 23
i Minutes with leading zero s 00 to 59
s Seco nds, with leading zero s 00 thro ugh 59
Timezone --- ---
Examples: UTC,
e Timezo ne identifier (added in PHP 5.1.0 ) GMT,
Atlantic/Azores
1 if Daylight
I (capital i) Whether o r no t the date is in daylights savings time Savings Time, 0
o therwise.
O Difference to Greenwich time (GMT) in ho urs Example: +0200
Difference to Greenwich time (GMT) with co lo n between ho urs and minutes
P Example: +02:00
(added in PHP 5.1.3)
Examples: EST,
T Timezo ne setting o f this machine
MDT ...
Timezo ne o ffset in seco nds. The o ffset fo r timezo nes west o f UTC is always -43200 thro ugh
Z
negative, and fo r tho se east o f UTC is always po sitive. 43200
Full
--- ---
Date/Time
20 0 4-0 2-
c ISO 8 6 0 1 date (added in PHP 5)
12T15:19 :21+0 0 :0 0
Example: Thu, 21
r RFC 28 22 fo rmatted date Dec 2000 16:01:07
+0200
U Seco nds since the Unix Epo ch (January 1 19 70 0 0 :0 0 :0 0 GMT)

Constructing Dates and T imes


No w, suppo se Acme, Inc. had a custo mer service po licy claiming "We'll get back to yo u in 48 ho urs." Yo u'll
want to use the date o f the message to give the custo mer suppo rt representative an idea o f the deadline she
has.
Make sure yo u have co ntact.php, and make the fo llo wing changes, in green:

<?php

#We used the superglobal $_GET here instead of the register globals, for safety
if (!($_GET['name'] && $_GET['email'] && $_GET['whoami']
&& $_GET['subject'] && $_GET['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";

$query_string = $_SERVER['QUERY_STRING'];
#add a flag called "error" to tell contact_form.php that something needs fixe
d
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php?".$query_string."&e
rror=1";
header("Location: ".$url);
exit(); //stop the rest of the program from happening

extract($_GET, EXTR_PREFIX_SAME, "get");

#construct email message

#we want a deadline 2 days after the message date.


$deadline_array = getdate();
$deadline_day = $deadline_array['mday'] + 2;
$deadline_str = $deadline_array['month']." ".$deadline_day." ".$deadline_array['
year'];

$email_message = "Message Date: ".date("F d, Y h:i a")."


Please reply by: ".$deadline_str."
Name: ".$name."
Email: ".$email."
Type of Request: ".$whoami."
Subject: ".$subject."
Message: ".$message."
How you heard about us: ".$found."
User Agent: ".$_SERVER['HTTP_USER_AGENT']."
IP Address: ".$_SERVER['HTTP_X_FORWARDED_FOR'];

#construct the email headers


$to = "support@example.com"; //for testing purposes, this should be YOUR email
address.
//We will send the emails from our own server
$from = "anything@yourlogin.oreillystudent.com";

$email_subject = "CONTACT #".time().": ".$_GET['subject'];

#now mail
mail($to, $email_subject, $email_message, "From: ".$from);

echo "<h3>Thank you!</h3>";


echo "We'll get back to you by ".$deadline_str.".<br/>";
echo "Here is a copy of your request:<br/><br/>";
echo "CONTACT #".time().":<br/>";
echo "Message Date: ".date("F d, Y h:i a")."<br/>";
echo "Name: ".$name."<br/>";
echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_
X_FORWARDED_FOR'];

?>

Save co ntact.php, switch to co ntact_fo rm.php and Preview:

Thank You!
We'll get back to you by May 31 2006.
Here is a copy of your request:

CONTACT # 1148955473:
Message Date: May 29, 2006 10:25 pm
Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please help!
Message: I can't get the darn thing to work!
How you heard about us: website
update1: on
update2:
You are currently working on Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418
(KHTML, like Gecko) Safari/417.9.2
The IP address of the computer you're working on is 63.171.219.74

Take ano ther lo o k:


#we want a deadline 2 days after the message date.
$deadline_array = getdate();
$deadline_day = $deadline_array['mday'] + 2;
$deadline_str = $deadline_array['month']." ".$deadline_day." ".$deadline_array['
year'];

Here, the functio n ge t dat e (), like t im e (), gets a stamp o f the current time. Ho wever, instead o f just an
integer, ge t dat e () extracts the data and o utputs an asso ciat ive array that lo o ks a bit like this:
Here's what a getdate() o utput array might lo o k like:
Array
(
[seconds] => 40
[minutes] => 58
[hours] => 21
[mday] => 29
[wday] => 1
[mon] => 5
[year] => 2006
[yday] => 160
[weekday] => Monday
[month] => May
[0] => 1055901520
)

This array makes it easy to co nstruct a new date relative to the current date - all we have to do is add 2 to the
'm day' array value, and suddenly we have a deadline fo r the custo mer suppo rt representative. Fast service
means happy custo mers.

But wait a minute - what if to day was, say, the 31st o f May? Just adding 2 to that will give yo u an invalid date.
We co uld do a series o f if statements to fix this, but that's a lo t o f unwieldy co de. Luckily, PHP has yet ano ther
handy functio n to help us.
In PHP, try adding the fo llo wing green co de to co ntact.php:

<?php

#We used the superglobal $_GET here instead of the register globals, for safety
if (!($_GET['name'] && $_GET['email'] && $_GET['whoami']
&& $_GET['subject'] && $_GET['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";

$query_string = $_SERVER['QUERY_STRING'];
#add a flag called "error" to tell contact_form.php that something needs fixe
d
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php?".$query_string."&e
rror=1";
header("Location: ".$url);
exit(); //stop the rest of the program from happening

extract($_GET, EXTR_PREFIX_SAME, "get");

#construct email message


#we want a deadline 2 days after the message date.
$deadline_array = getdate();
$deadline_day = $deadline_array['mday'] + 2;

$deadline_stamp = mktime($deadline_array['hours'],$deadline_array['minutes'],$de
adline_array['seconds'],
$deadline_array['mon'],$deadline_day,$deadline_array['year']);
$deadline_str = date("F d, Y", $deadline_stamp);

$email_message = "Message Date: ".date("F d, Y h:i a")."


Please reply by: ".$deadline_str."
Name: ".$name."
Email: ".$email."
Type of Request: ".$whoami."
Subject: ".$subject."
Message: ".$message."
How you heard about us: ".$found."
User Agent: ".$_SERVER['HTTP_USER_AGENT']."
IP Address: ".$_SERVER['HTTP_X_FORWARDED_FOR'];

#construct the email headers


$to = "support@example.com"; //for testing purposes, this should be YOUR email
address.
//We will send the emails from our own server
$from = "anything@yourlogin.oreillystudent.com";

$email_subject = "CONTACT #".time().": ".$_GET['subject'];

#now mail
mail($to, $email_subject, $email_message, "From: ".$from);

echo "<h3>Thank you!</h3>";


echo "We'll get back to you by ".$deadline_str.".<br/>";
echo "Here is a copy of your request:<br/><br/>";
echo "CONTACT #".time().":<br/>";
echo "Message Date: ".date("F d, Y h:i a")."<br/>";
echo "Name: ".$name."<br/>";
echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";
for ($i = 1; $i <= 2; $i++) {
$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_
X_FORWARDED_FOR'];

?>

Save co ntact.php, switch to co ntact_fo rm.php and Preview:

Thank You!
We'll get back to you by June 2 2006.
Here is a copy of your request:

CONTACT # 1148962509:
Message Date: May 31, 2006 12:20 pm
Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please help!
Message: I can't get the darn thing to work!
How you heard about us: website
update1: on
update2:
You are currently working on Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418
(KHTML, like Gecko) Safari/417.9.2
The IP address of the computer you're working on is 63.171.219.74

Take o ne mo re lo o k:
$deadline_stamp = mktime($deadline_array['hours'],$deadline_array['minutes'],$de
adline_array['seconds'],
$deadline_array['mon'],$deadline_day,$deadline_array['year']);
$deadline_str = date("F d, Y", $deadline_stamp);

The functio n m kt im e () fixes all tho se pesky date pro blems. It takes in the parameter data o f the date yo u
want to fo rmat, and creates the o riginal t im e st am p, which we then plug into dat e () to fo rmat pro perly.
Pro blem so lved!

Do n't fo rget to Save yo ur wo rk and hand in yo ur assignm e nt s fro m yo ur syllabus. See yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Using Files
So far, we've created a simple co rpo rate co ntact fo rm that acco unts fo r user erro r and friendly reminders, successful o utput, and
sending o f the pro per message. Pretty ro bust, but at the same time, yo u have to admit, it's pretty ugly. And it's no t the mo st
pro fessio nal-lo o king interface o n the web either.

In a perfect wo rld, we'd have lo ts o f time to keep tweaking the PHP script to make every page lo o k just so . But in mo st
situatio ns, yo u wo n't have the luxury o f extra time, and yo u pro bably wo n't even be allo wed to dictate ho w the page lo o ks. No t
when there's a graphic designer do wn the hall. Just the same, yo u do n't want the graphic designer do wn the hall messing with
yo ur PHP scripts either. Here's where f ile t e m plat e s co me in real handy.

Including and Requiring Files


Fire up Co deRunner and o pen up the two files we were wo rking o n befo re: co nt act _f o rm .php and co nt act .php.
After yo u do this, switch Co deRunner to HT ML synt ax. Fo r just a mo ment, we're go ing to pretend that we are the
graphic designers do wn the hall.

In HTML, type the fo llo wing, in blue:

<html>
<head>
<title>Acme, Inc.</title>
<link rel="stylesheet" href="http://students.oreillyschool.com/resource/php_lesson.css"
type="text/css" />
</head>
<body>
<div class="topbar">
ACME, INC.
</div>
<table>
<tr><td class="sidebar" valign="top">
links go here
</td><td class="content">
Content goes here

</td></tr></table>
<div class="bottombar">
</div>
</body>
</html>

Preview this:

ACME, INC.
links go here
Content goes here

What we have here is a basic "C-Clamp" design template fo r a co rpo rate web page: lo go o n to p, links o n the side,
so mething o n the bo tto m to wrap the co ntent nicely, and a CSS file to add a little style (here we've pro vided o ne fo r
yo u). This will make o ur co ntact fo rm lo o k slightly better than it did befo re.

But ho w do yo u mo st easily place o ur co ntent within this C-Clamp? Yo u co uld simply embed the HTML into the PHP
script itself, but this creates a big pro blem - if the graphic designer decides to make a change, yo u're stuck making that
same change in every PHP script yo u've written. And if yo u wo rk fo r a large co rpo ratio n, this co uld mean do zens, even
hundreds o f files.

It wo uld be great is if yo u co uld reuse the co de, like when yo u create PHP functio ns.

In HTML, remo ve the seco nd half o f o ur C-Clamp:

<html>
<head>
<title>Acme, Inc.</title>
<link rel="stylesheet" href="http://students.oreillyschool.com/resource/php_lesson.css"
type="text/css" />
</head>
<body>
<div class="topbar">
ACME, INC.
</div>
<table>
<tr><td class="sidebar" valign=top>
links go here
</td><td class="content">

No w, Save this file and name it t e m plat e _t o p.inc.

Note Why use .inc? Just fo r clarity - this isn't a co mplete HTML file, so no need to name it with a .html suffix.

In HTML, create a NEW file, co ntaining the seco nd half o f o ur C-Clamp:

</td></tr></table>
<div class="bottombar">
</div>
</body>
</html>

Save this file and name it t e m plat e _bo t t o m .inc.


Add the fo llo wing to co ntact_fo rm.php, in green:
<?php

require($_SERVER['DOCUMENT_ROOT']."/template_top.inc");

if ($_GET['error'] == "1") {
$error_code = 1; //this means that there's been an error and we need to notify the
customer
}

?>
<body>
<h3>Contact ACME Corporation</h3>
<?
if ($error_code) {
echo "<font color=red>Please help us with the following:</font>";
}
?>
<form method=GET action="contact.php">
<table>
<tr>
<td align="right">
Name:
</td>
<td align="left">
<input type="text" size="25" name="name" value="<? echo $_GET['name']; ?>">
<?
if ($error_code && !($_GET['name'])) {
echo "<b>Please include your name.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Email:
</td><td align="left">
<input type="text" size="25" name="email" value="<? echo $_GET['email']; ?>">
<?
if ($error_code && !($_GET['email'])) {
echo "<b>Please include your email address.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Type of Request:
</td>
<td align="left">
<select name="whoami">
<option value="">Please choose...
<option value="newcustomer"<?
if ($_GET['whoami'] == "newcustomer") {
echo " selected";
}
?>>I am interested in becoming a customer.
<option value="customer"<?
if ($_GET['whoami'] == "customer") {
echo " selected";
}
?>>I am a customer with a general question.
<option value="support"<?
if ($_GET['whoami'] == "support") {
echo " selected";
}
?>>I need technical help using the website.
<option value="billing"<?
if ($_GET['whoami'] == "billing") {
echo " selected";
}
?>>I have a billing question.
</select>
<?
if ($error_code && !($_GET['whoami'])) {
echo "<b>Please choose a request type.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Subject:
</td>
<td align="left">
<input type="text" size="50" max="50" name="subject" value="<? echo $_GET['subject']; ?
>">
<?
if ($error_code && !($_GET['subject'])) {
echo "<b>Please add a subject for your request.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right" valign="top">
Message:
</td>
<td align="left">
<textarea name="message" cols=50 rows=8>
<? echo $_GET['message']; ?>
</textarea>
<?
if ($error_code && !($_GET['message'])) {
echo "<b>Please fill in a message for us.</b>";
}
?>
</td>
</tr>
<tr>
<td colspan="2" align="left">
How did you hear about us?
<ul>
<input type="radio" name="found" value="wordofmouth">Word of Mouth<br>
<input type="radio" name="found" value="search">Online Search<br>
<input type="radio" name="found" value="article">Printed publication/article<br>
<input type="radio" name="found" value="website">Online link/article<br>
<input type="radio" name="found" value="other">Other
</ul>
</td>
</tr>
<tr>
<td colspan="2">
<input type="checkbox" name="update1" checked>Please email me updates about your produc
ts.<br>
<input type="checkbox" name="update2">Please email me updates about products from third
-party partners.
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="SUBMIT">
</td></tr>
</table>
</form>

<?
require($_SERVER['DOCUMENT_ROOT']."/template_bottom.inc");
?>

</body>

Be sure and Save co nt act _f o rm .php.

No w PREVEIW:

ACME, INC.
links go here
Contact ACME Corporation

Name:
Email:
Type of Request: Please choose...

Subject:
Message:

How did you hear about us?

Word of Mouth
Online Search
Printed publication/article
Online link/article
Other

Please email me updates about your products.


Please email me updates about products from third-party partners.

SUBM IT

Even with the extreme simplicity o f o ur C-Clamp template, this lo o ks much better than it did befo re.

Take ano ther lo o k at the co de:

require($_SERVER['DOCUMENT_ROOT']."/template_top.inc");
The PHP built-in functio n re quire () takes a filename as its param e t e r, and impo rts all the data fro m that filename into
that exact place within the PHP co de. It's as if yo u had written the co de right in.

We can do this with co nt act .php as well.


Switch to co ntact.php and add the fo llo wing green co de:

<?php

#Remember, if you place any output before a header() call, you'll get an error.
#We used the superglobal $_GET here instead of the register globals, for safety
if (!($_GET['name'] && $_GET['email'] && $_GET['whoami']
&& $_GET['subject'] && $_GET['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";

$query_string = $_SERVER['QUERY_STRING'];
#add a flag called "error" to tell contact_form.php that something needs fixed
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php?".$query_string."&error=1"
;
header("Location: ".$url);
exit(); //stop the rest of the program from happening

}
extract($_GET, EXTR_PREFIX_SAME, "get");
#construct email message
#we want a deadline 2 days after the message date.
$deadline_array = getdate();
$deadline_day = $deadline_array['mday'] + 2;

$deadline_stamp = mktime($deadline_array['hours'],$deadline_array['minutes'],$deadline_
array['seconds'],
$deadline_array['mon'],$deadline_day,$deadline_array['year']);
$deadline_str = date("F d, Y", $deadline_stamp);

$email_message = "Message Date: ".date("F d, Y h:i a")."<br>


Please reply by: ".$deadline_str."<br>
Name: ".$name."<br>
Email: ".$email."<br>
Type of Request: ".$whoami."<br>
Subject: ".$subject."<br>
Message: ".$message."<br>
How you heard about us: ".$found."<br>
User Agent: ".$_SERVER['HTTP_USER_AGENT']."<br>
IP Address: ".$_SERVER['HTTP_X_FORWARDED_FOR'];

#construct the email headers


$to = "support@example.com"; //for testing purposes, this should be YOUR email address
.
//We will send the emails from our own server
$from = "anything@yourlogin.oreillystudent.com";

$email_subject = "CONTACT #".time().": ".$_GET['subject'];

$headers = "From: " . $from . "\r\n";


$headers .= 'MIME-Version: 1.0' . "\n"; //these headers will allow our HTML tags to be
displayed in the email
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

#now mail
mail($to, $email_subject, $email_message, $headers);

include($_SERVER['DOCUMENT_ROOT']."/template_top.inc");

echo "<h3>Thank you!</h3>";


echo "We'll get back to you by ".$deadline_str.".<br>";
echo "Here is a copy of your request:<br><br>";
echo "CONTACT #".time().":<br>";
echo "Message Date: ".date("F d, Y h:i a")."<br>";
echo "Name: ".$name."<br>";
echo "Email: ".$email."<br>";
echo "Type of Request: ".$whoami."<br>";
echo "Subject: ".$subject."<br>";
echo "Message: ".$message."<br>";
echo "How you heard about us: ".$found."<br>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br>The IP address of the computer you're working on is ".$_SERVER['HTTP_X_FORWAR
DED_FOR'];

include($_SERVER['DOCUMENT_ROOT']."/template_bottom.inc");

?>

Save co nt act .php. No w when yo u view co nt act _f o rm .php and submit the fo rm, yo u sho uld see so mething like
this:

ACME, INC.
links go here
Thank you!
We'll get back to you by June 07, 2006.
Here is a copy of your request:

CONTACT # 1149489921:
Message Date: June 05, 2006 01:45 pm
Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please help!
Message: I can/'t get the darn thing to work!
How you heard about us: other
update1: on
update2:
You are currently working on Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en)
AppleWebKit/418 (KHTML, like Gecko) Safari/417.9.2
The IP address of the computer you're working on is 63.171.219.74

This time, instead o f re quire () we used include (). What's the difference? If fo r so me reaso n the URL
Note do esn't exist, re quire () will give yo u a PHP erro r, whereas include () will just skip that URL.
Reading and Writing Files
No w that we've go t the web interface lo o king better, let's wo rk o n the email. In this case, there's no clear-cut beginning
and ending template, rather, the data is peppered thro ugho ut the email. So if we want to use a template with this, we'll
have to find a way to insert the data into the template, instead o f the o ther way aro und.

First, let's see ho w we want the template to lo o k. Switch to HT ML, and create a t e xt -o nly f ile that lo o ks so mething
like belo w.

Make sure yo u're in HTML, and type the fo llo wing into a new file:

You have just received a customer email. Please respond to this email by #DEADLINE#.
Details are below:

<table>
<tr><td width="100" align="right">Message Type: </td><td>#WHOAMI#</td></tr>
<tr><td width="100" align="right">Message Date: </td><td>#DATE#</td></tr>
<tr><td width="100" align="right">Name: </td><td>#NAME#</td></tr>
<tr><td width="100" align="right">Email: </td><td>#EMAIL#</td></tr>
<tr><td width="100" align="right">IP Address: </td><td>#IP#</td></tr>
<tr><td width="100" align="right">Platform: </td><td>#AGENT#</td></tr>
</table>

<b>Subject: #SUBJECT#
<br>
#MESSAGE#</b>
<br><br>
This customer found us through #FOUND#.<br>
#CONTACT#

Save this text file, and call it e m ail_t e m plat e .t xt . No w let's go back to co nt act .php.
Switch to co ntact.php and make the fo llo wing changes, in green:

<?php

function mail_message($data_array, $template_file, $deadline_str) {

#get template contents, and replace variables with data


$email_message = file_get_contents($template_file);
$email_message = str_replace("#DEADLINE#", $deadline_str, $email_message);
$email_message = str_replace("#WHOAMI#", $data_array['whoami'], $email_message);
$email_message = str_replace("#DATE#", date("F d, Y h:i a"), $email_message);
$email_message = str_replace("#NAME#", $data_array['name'], $email_message);
$email_message = str_replace("#EMAIL#", $data_array['email'], $email_message);
$email_message = str_replace("#IP#", $_SERVER['HTTP_X_FORWARDED_FOR'], $email_messag
e);
$email_message = str_replace("#AGENT#", $_SERVER['HTTP_USER_AGENT'], $email_message)
;
$email_message = str_replace("#SUBJECT#", $data_array['subject'], $email_message);
$email_message = str_replace("#MESSAGE#", $data_array['message'], $email_message);
$email_message = str_replace("#FOUND#", $data_array['found'], $email_message);

#include whether or not to contact the customer with offers in the future
$contact = "";
if (isset($data_array['update1'])) {
$contact = $contact." Please email updates about your products.<br/>";
}
if (isset($data_array['update2'])) {
$contact = $contact." Please email updates about products from third-party partne
rs.<br/>";
}
$email_message = str_replace("#CONTACT#", $contact, $email_message);

#construct the email headers


$to = "support@example.com"; //for testing purposes, this should be YOUR email addr
ess.
$from = $data_array['email'];
$email_subject = "CONTACT #".time().": ".$data_array['subject'];

$headers = "From: " . $from . "\r\n";


$headers .= 'MIME-Version: 1.0' . "\n"; //these headers will allow our HTML tags to
be displayed in the email
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

#now mail
mail($to, $email_subject, $email_message, $headers);

#Remember, if you place any output before a header() call, you'll get an error.
#We used the superglobal $_GET here instead of the register globals, for safety
if (!($_GET['name'] && $_GET['email'] && $_GET['whoami']
&& $_GET['subject'] && $_GET['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";

$query_string = $_SERVER['QUERY_STRING'];
#add a flag called "error" to tell contact_form.php that something needs fixed
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php?".$query_string."&error=1"
;
header("Location: ".$url);
exit(); //stop the rest of the program from happening
}

extract($_GET, EXTR_PREFIX_SAME, "get");

#we want a deadline 2 days after the message date.


$deadline_array = getdate();
$deadline_day = $deadline_array['mday'] + 2;

$deadline_stamp = mktime($deadline_array['hours'],$deadline_array['minutes'],$deadli
ne_array['seconds'],
$deadline_array['mon'],$deadline_day,$deadline_array['year']);
$deadline_str = date("F d, Y", $deadline_stamp);

//DOCUMENT_ROOT is the file path leading up to the template name.


mail_message($_GET, $_SERVER['DOCUMENT_ROOT']."/email_template.txt", $deadline_str);

include($_SERVER['DOCUMENT_ROOT']."/template_top.inc");

echo "<h3>Thank you!</h3>";


echo "We'll get back to you by ".$deadline_str.".<br/>";
echo "Here is a copy of your request:<br/><br/>";
echo "CONTACT #".time().":<br/>";
echo "Message Date: ".date("F d, Y h:i a")."<br/>";
echo "Name: ".$name."<br/>";
echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_X_FORWA
RDED_FOR'];

include($_SERVER['DOCUMENT_ROOT']."/template_bottom.inc");

?>

Save co nt act .php, then view and submit the fo rm in co nt act _f o rm .php. If yo u used yo ur o wn email address as the
$ t o variable, yo u sho uld have received an email in yo ur INBOX like befo re. Ho wever, this time it sho uld lo o k a little
better.

Yo u sho uld have received an email like this:


Date: Thu, 8 Jun 2006 17:03:11 -0500
From: trish@myemail.com
To: support@acmeinc.com
Subject: CONTACT #1149804191: Please help!

You have just received a customer email. Please respond to this email by June 10, 2006.
Details are below:

Message Type: support


Message Date: June 08, 2006 05:03 pm
Name: Trish
Email: trish@myemail.com
IP Address: 12.149.132.162
Platform: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418

Subject : Please help!

I can't get t he darn t hing t o work!

This customer found us through wordofmouth.


Please email updates about your products.

Take ano ther lo o k at the co de:


function mail_message($data_array, $template_file, $deadline_str) {

#get template contents, and replace variables with data


$email_message = file_get_contents($template_file);
$email_message = str_replace("#DEADLINE#", $deadline_str, $email_message);
$email_message = str_replace("#WHOAMI#", $data_array['whoami'], $email_message);

.
.
.
}
.
.
.
mail_message($_GET, $_SERVER['DOCUMENT_ROOT']."/email_template.txt", $deadline_str);

Here, we created a functio n called m ail_m e ssage (), which takes three parameters -- $ dat a_array, $ t e m plat e _f ile ,
and $ de adline _st r. $ dat a_array co ntains all the fo rm data, because we pass the $ _GET superglo bal array into it.
$ t e m plat e _f ile is the full path to the template file we want to use - in o ur case, we passed in the path to
"e m ail_t e m plat e .t xt " that we created earlier. And $ de adline _st r is the fo rmatted string o f the date by which we
want the message answered.

We used the built-in PHP functio n f ile _ge t _co nt e nt s() to impo rt o ur email template file into a string,
$ e m ail_m e ssage . Then, o ne by o ne, we replace each o f o ur template variables with the co rrespo nding fo rm data,
using the built-in functio n st r_re place (). Go to php.net to read mo re abo ut file_get_co ntents() o r str_replace().

By making the suppo rt email easier to read -- and o btaining as much user info rmatio n as po ssible -- yo u've impro ved
efficiency in Acme's custo mer suppo rt pro cess. Go ahead, demand a raise. Yo u deserve it.

Allowing Users to Download Files


To make things a little mo re interesting, it turns o ut that Acme wants every custo mer who sends in a suppo rt email to
be allo wed to do wnlo ad its info rmatio nal bro chure, a PDF do cument.

No w, technically yo u co uld just include a link to the PDF do cument itself, if the do cument is in a web-accessible
directo ry. Ho wever, mo st o f the time co rpo ratio ns do n't want their do wnlo adable files to be in a public area fo r anyo ne
and everyo ne to do wnlo ad. This is especially true when electro nic do cuments are fo r purchase, like marketing repo rts
o r co pyrighted materials.

In yo ur case, we've placed the bro chure, called acm e _bro chure .pdf , in a hidden directo ry called .php_f ile s/ within
yo ur acco unt. Yo u can't view this file thro ugh the web, but yo u need to allo w web users o f yo ur cho o sing to do wnlo ad
it. What do yo u do ?

In PHP, create a new file, called do wnlo ad.php:

<?php

$filepath = $_SERVER['DOCUMENT_ROOT']."/.php_files/acme_brochure.pdf";
if (file_exists($filepath)) {
header("Content-Type: application/force-download");
header("Content-Disposition:filename=\"brochure.pdf\"");
$fd = fopen($filepath,'rb');
fpassthru($fd);
fclose($fd);
}

?>

Save do wnlo ad.php.


No w, switch back to co ntact.php and make the fo llo wing changes, in green and blue:
<?php

function mail_message($data_array, $template_file, $deadline_str) {

#get template contents, and replace variables with data


$email_message = file_get_contents($template_file);
$email_message = str_replace("#DEADLINE#", $deadline_str, $email_message);
$email_message = str_replace("#WHOAMI#", $data_array['whoami'], $email_message);
$email_message = str_replace("#DATE#", date("F d, Y h:i a"), $email_message);
$email_message = str_replace("#NAME#", $data_array['name'], $email_message);
$email_message = str_replace("#EMAIL#", $data_array['email'], $email_message);
$email_message = str_replace("#IP#", $_SERVER['HTTP_X_FORWARDED_FOR'], $email_messag
e);
$email_message = str_replace("#AGENT#", $_SERVER['HTTP_USER_AGENT'], $email_message)
;
$email_message = str_replace("#SUBJECT#", $data_array['subject'], $email_message);
$email_message = str_replace("#MESSAGE#", $data_array['message'], $email_message);
$email_message = str_replace("#FOUND#", $data_array['found'], $email_message);

#include whether or not to contact the customer with offers in the future
$contact = "";
if (isset($data_array['update1'])) {
$contact = $contact." Please email updates about your products.<br/>";
}
if (isset($data_array['update2'])) {
$contact = $contact." Please email updates about products from third-party partne
rs.<br/>";
}
$email_message = str_replace("#CONTACT#", $contact, $email_message);

#construct the email headers


$to = "support@example.com"; //for testing purposes, this should be YOUR email addr
ess.
$from = $data_array['email'];
$email_subject = "CONTACT #".time().": ".$data_array['subject'];

$headers = "From: " . $from . "\r\n";


$headers .= 'MIME-Version: 1.0' . "\n"; //these headers will allow our HTML tags to
be displayed in the email
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

#now mail
mail($to, $email_subject, $email_message, $headers);

#Remember, if you place any output before a header() call, you'll get an error.
#We used the superglobal $_GET here instead of the register globals, for safety
if (!($_GET['name'] && $_GET['email'] && $_GET['whoami']
&& $_GET['subject'] && $_GET['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";

$query_string = $_SERVER['QUERY_STRING'];
#add a flag called "error" to tell contact_form.php that something needs fixed
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php?".$query_string."&error=1"
;
header("Location: ".$url);
exit(); //stop the rest of the program from happening

extract($_GET, EXTR_PREFIX_SAME, "get");


#we want a deadline 2 days after the message date.
$deadline_array = getdate();
$deadline_day = $deadline_array['mday'] + 2;

$deadline_stamp = mktime($deadline_array['hours'],$deadline_array['minutes'],$deadli
ne_array['seconds'],
$deadline_array['mon'],$deadline_day,$deadline_array['year']);
$deadline_str = date("F d, Y", $deadline_stamp);

//DOCUMENT_ROOT is the file path leading up to the template name.


mail_message($_GET, $_SERVER['DOCUMENT_ROOT']."/email_template.txt", $deadline_str);

include($_SERVER['DOCUMENT_ROOT']."/template_top.inc");

echo "<h3>Thank you!</h3>";


echo "We'll get back to you by ".$deadline_str.".<br/>";
echo "Here is a copy of your request:<br/><br/>";
echo "CONTACT #".time().":<br/>";
echo "Message Date: ".date("F d, Y h:i a")."<br/>";
echo "Name: ".$name."<br/>";
echo "Email: ".$email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_X_FORWA
RDED_FOR'];

?>
<br/><br/><a href="download.php"><b>Download our PDF brochure!</b></a>
<?

include($_SERVER['DOCUMENT_ROOT']."/template_bottom.inc");

?>

Save co nt act .php, then view co nt act _f o rm .php and submit the fo rm:

It sho uld lo o k so mething like this:


ACME, INC.
links go here
Thank you!
We'll get back to you by June 10, 2006.
Here is a copy of your request:

CONTACT # 1149809625:
Message Date: June 08, 2006 06:33 pm
Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please Help!
Message: I can/'t get the darn thing to work!
How you heard about us: wordofmouth
update1: on
update2:
You are currently working on Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en)
AppleWebKit/418 (KHTML, like Gecko) Safari/417.9.2
The IP address of the computer you're working on is 63.171.219.74

Download our PDF brochure!

No w click the link. Did the PDF file do wnlo ad to yo ur co mputer? Yo u may have seen so mething like this:

Ho w were we able to do that? Take ano ther lo o k at the co de in do wnlo ad.php:


OBSERVE:

$filepath = $_SERVER['DOCUMENT_ROOT']."/.php_files/acme_brochure.pdf";
if (file_exists($filepath)) {
header("Content-Type: application/force-download");
header("Content-Disposition:filename=\"brochure.pdf\"");
$fd = fopen($filepath,'rb');
fpassthru($fd);
fclose($fd);
}

First, the built-in functio n f ile _e xist s() do es exactly what it says - it returns TRUE o r FALSE based upo n the existence
o f the parameter $ f ile pat h, which we set to the path o f Acme's hidden PDF bro chure in o ur acco unt. Since it do es
exist, we use he ade r() to o utput two HT T P he ade rs. The header " Co nt e nt -T ype " is extremely impo rtant, as it tells
the web bro wser that we are preparing to do wnlo ad data that is NOT in an HTML o r text fo rmat, but in fact an
applicatio n. Find o ut what happens if yo u leave this header o ut. The header " Co nt e nt -Dispo sit io n" is o ptio nal, but
we used it to create a generic name fo r the do wnlo aded file.

In the case o f PDF files, yo u can also use the header " Co nt e nt -T ype : applicat io n/pdf " . What's the
Note difference? So me bro wsers allo w PDF files to be o pened within the bro wser itself, witho ut having to
do wnlo ad them to the co mputer's hard drive. Try it o ut and see what happens in yo ur o wn bro wser.

Then, the built-in functio n f o pe n() creates a f ile st re am po inting to o ur acme_bro chure.pdf file, and binds it to the
handle $ f d. The parameter 'rb' specifies that the file sho uld be o pened in re ad-o nly, binary m o de -- binary, again,
because it's no t a text file. f passt hru() then sends all the file data thro ugh to the o ut put buf f e r -- and because we
specified thro ugh he ade r() what the bro wser sho uld do with that o utput, this launches yo ur co mputer's do wnlo ad
manager. f clo se () simply clo ses the f ile st re am $ f d, to clean things up.

Do n't fo rget to Save yo ur wo rk and hand in yo ur assignm e nt s fro m yo ur syllabus. See yo u in the next lesso n!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Cookies and Sessions
Learning abo ut co o kie s and se ssio ns is essential fo r pro gramming PHP in the 21st century. Yo u see, web users just aren't as
patient as they used to be - they want websites that are incredibly easy fo r them to use and reuse, witho ut having to repeat
themselves o ver and o ver again. And their attentio n spans are sho rter as well, meaning co rpo rate websites in particular must
co mpete by targeting the user as specifically as po ssible.

"Know Thy User", as they say. But ho w?

Using Cookies

Mmmm, co o kies. Well, no , no t those kinds o f co o kies. Altho ugh we wo uld certainly revisit a web
site fo r free co o kies any day, unfo rtunately, do wnlo ading cho co late-chip go o dness just hasn't
been invented yet. Sigh...

Okay, so what are bro wse r co o kie s? Let's find o ut. Fire up Co deRunner in PHP, and open yo ur files
co nt act _f o rm .php and co nt act .php.
Add the fo llo wing to co ntact_fo rm.php, in green and blue:
<?php

require($_SERVER['DOCUMENT_ROOT']."/template_top.inc");

if ($_GET['error'] == "1") {
$error_code = 1; //this means that there's been an error and we need to notify the
customer
}

?>

<h3>Contact ACME Corporation</h3>


<?
if ($error_code) {
echo "<div style='color:red'>Please help us with the following:</div>";
}
?>
<form method="GET" action="contact.php">
<table>
<tr>
<td align="right">
Name:
</td>
<td align="left">
<?
if ($_COOKIE['name']) {
echo $_COOKIE['name'];
}
else {
?>
<input type="text" size="25" name="name" value="<? echo $_GET['name']; ?>" />
<input type="checkbox" name="remember" /> Remember me on this computer
<?
}
if ($error_code && !($_GET['name'] || $_COOKIE['name'])) {
echo "<b>Please include your name.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Email:
</td><td align="left">
<?
if ($_COOKIE['email']) {
echo $_COOKIE['email'];
}
else {
?>
<input type="text" size="25" name="email" value="<? echo $_GET['email']; ?>" />
<?
}
if ($error_code && !($_GET['email'] || $_COOKIE['email'])) {
echo "<b>Please include your email address.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Type of Request:
</td>
<td align="left">
<select name="whoami">
<option value="" />Please choose...
<option value="newcustomer"<?
if ($_GET['whoami'] == "newcustomer") {
echo " selected";
}
?> />I am interested in becoming a customer.
<option value="customer"<?
if ($_GET['whoami'] == "customer") {
echo " selected";
}
?> />I am a customer with a general question.
<option value="support"<?
if ($_GET['whoami'] == "support") {
echo " selected";
}
?> />I need technical help using the website.
<option value="billing"<?
if ($_GET['whoami'] == "billing") {
echo " selected";
}
?> />I have a billing question.
</select>
<?
if ($error_code && !($_GET['whoami'])) {
echo "<b>Please choose a request type.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Subject:
</td>
<td align="left">
<input type="text" size="50" max="50" name="subject" value="<? echo $_GET['subject']; ?
>" />
<?
if ($error_code && !($_GET['subject'])) {
echo "<b>Please add a subject for your request.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right" valign="top">
Message:
</td>
<td align="left">
<textarea name="message" cols="50" rows="8">
<? echo $_GET['message']; ?>
</textarea>
<?
if ($error_code && !($_GET['message'])) {
echo "<b>Please fill in a message for us.</b>";
}
?>
</td>
</tr>
<tr>
<td colspan="2" align="left">
How did you hear about us?
<ul>
<input type="radio" name="found" value="wordofmouth" />Word of Mouth<br/>
<input type="radio" name="found" value="search" />Online Search<br/>
<input type="radio" name="found" value="article" />Printed publication/article<br/>
<input type="radio" name="found" value="website" />Online link/article<br/>
<input type="radio" name="found" value="other" />Other
</ul>
</td>
</tr>
<tr>
<td colspan="2">
<input type="checkbox" name="update1" checked="checked" />Please email me updates about
your products.<br/>
<input type="checkbox" name="update2" />Please email me updates about products from thi
rd-party partners.
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="SUBMIT" />
</td></tr>
</table>
</form>

<?
require($_SERVER['DOCUMENT_ROOT']."/template_bottom.inc");
?>

Be sure and Save co nt act _f o rm .php, then Preview.

Yo u sho uld see so mething like this:


ACME, INC.
links go here
Contact ACME Corporation

Remember me on this
Name:
computer
Email:
Type of
Please choose...
Request:
Subject:
Message:

How did you hear about us?

Word of Mouth
Online Search
Printed publication/article
Online link/article
Other

Please email me updates about your products.


Please email me updates about products from third-party partners.
No w, switch back to co ntact.php and make the fo llo wing changes, in green:
<?php

function mail_message($data_array, $template_file, $deadline_str, $myname, $myemail) {

#get template contents, and replace variables with data


$email_message = file_get_contents($template_file);
$email_message = str_replace("#DEADLINE#", $deadline_str, $email_message);
$email_message = str_replace("#WHOAMI#", $data_array['whoami'], $email_message);
$email_message = str_replace("#DATE#", date("F d, Y h:i a"), $email_message);
$email_message = str_replace("#NAME#", $myname, $email_message);
$email_message = str_replace("#EMAIL#", $myemail, $email_message);
$email_message = str_replace("#IP#", $_SERVER['HTTP_X_FORWARDED_FOR'], $email_messag
e);
$email_message = str_replace("#AGENT#", $_SERVER['HTTP_USER_AGENT'], $email_message)
;
$email_message = str_replace("#SUBJECT#", $data_array['subject'], $email_message);
$email_message = str_replace("#MESSAGE#", $data_array['message'], $email_message);
$email_message = str_replace("#FOUND#", $data_array['found'], $email_message);

#include whether or not to contact the customer with offers in the future
$contact = "";
if (isset($data_array['update1'])) {
$contact = $contact." Please email updates about your products.<br/>";
}
if (isset($data_array['update2'])) {
$contact = $contact." Please email updates about products from third-party partne
rs.<br/>";
}
$email_message = str_replace("#CONTACT#", $contact, $email_message);

#construct the email headers


$to = " ReplaceWithYourOwnEmailAddress@oreillyschool.com"; //for testing purposes,
this should be YOUR email address.
$from = $data_array['email'];
$email_subject = "CONTACT #".time().": ".$data_array['subject'];

$headers = "From: " . $from . "\r\n";


$headers .= 'MIME-Version: 1.0' . "\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n"; #now mail
mail($to, $email_subject, $email_message, $headers);

$customer_name = $_COOKIE['name'];
if (!($customer_name)) {
$customer_name = $_GET['name'];
}
$customer_email = $_COOKIE['email'];
if (!($customer_email)) {
$customer_email = $_GET['email'];
}

#Remember, if you place any output before a header() call, you'll get an error.
#We used the superglobal $_GET here
if (!($customer_name && $customer_email && $_GET['whoami']
&& $_GET['subject'] && $_GET['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";

$query_string = $_SERVER['QUERY_STRING'];
#add a flag called "error" to tell contact_form.php that something needs fixed
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php?".$query_string."&error=1"
;
header("Location: ".$url);
exit(); //stop the rest of the program from happening

#we want a deadline 2 days after the message date.


$deadline_array = getdate();
$deadline_day = $deadline_array['mday'] + 2;

$deadline_stamp = mktime($deadline_array['hours'],$deadline_array['minutes'],$deadli
ne_array['seconds'],
$deadline_array['mon'],$deadline_day,$deadline_array['year']);
$deadline_str = date("F d, Y", $deadline_stamp);

if (isset($_GET['remember'])) {
#the customer wants us to remember him/her for next time
### set errcode cookie
/*
cookie expires in one year
365 days in a year
24 hours in a day
60 minutes in an hour
60 seconds in a minute
*/
$mytime = time() + (365 * 24 * 60 * 60);
setcookie("name",$customer_name,$mytime);
setcookie("email",$customer_email,$mytime);
}

//DOCUMENT_ROOT is the file path leading up to the template name.


mail_message($_GET, $_SERVER['DOCUMENT_ROOT']."/email_template.txt", $deadline_str, $cu
stomer_name, $customer_email);

include($_SERVER['DOCUMENT_ROOT']."/template_top.inc");

extract($_GET, EXTR_PREFIX_SAME, "get");

echo "<h3>Thank you!</h3>";


echo "We'll get back to you by ".$deadline_str.".<br/>";
echo "Here is a copy of your request:<br/><br/>";
echo "CONTACT #".time().":<br/>";
echo "Message Date: ".date("F d, Y h:i a")."<br/>";
echo "Name: ".$customer_name."<br/>";
echo "Email: ".$customer_email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_X_FORWA
RDED_FOR'];

?>
<br/><br/><a href="download.php"><b>Download our PDF brochure!</b></a>
<?
include($_SERVER['DOCUMENT_ROOT']."/template_bottom.inc");

?>

Save co nt act .php, switch to co nt act _f o rm .php, and Preview. This time, ho wever, when yo u submit the fo rm, be
sure to check the bo x that says "Remember me o n this co mputer."

ACME, INC.
links go here
Thank you!
We'll get back to you by June 11, 2006.
Here is a copy of your request:

CONTACT # 1149880113:
Message Date: June 09, 2006 02:08 pm
Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please help!
Message: I can/'t get the darn thing to work!
How you heard about us: wordofmouth
update1: on
update2:
You are currently working on Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O;
en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7
The IP address of the computer you're working on is 63.171.219.74

Download our PDF brochure!

Lo o ks pretty much the same as befo re. What's changed? To find o ut, no w go back to co nt act _f o rm .php and
RELOAD the page:
ACME, INC.
links go here
Contact ACME Corporation

Name: Trish
Email: trish@myemail.com
Type of Request: Please choose...
Subject:
Message:

How did you hear about us?

Word of Mouth
Online Search
Printed publication/article
Online link/article
Other

Please email me updates about your products.


Please email me updates about products from third-party partners.

SUBM IT

And there we are! The fo rm is indeed remembering us, and even if yo u exit yo ur bro wser entirely and co me back, yo ur
name and email wo uld still be there. But ho w were we able to do it? Using co o kie s.

Take ano ther lo o k at the co de in co ntact.php:


if (isset($_GET['remember'])) {
#the customer wants us to remember him/her for next time
### set errcode cookie
/*
cookie expires in one year
365 days in a year
24 hours in a day
60 minutes in an hour
60 seconds in a minute
*/
$mytime = time() + (365 * 24 * 60 * 60);
setcookie("name",$customer_name,$mytime);
setcookie("email",$customer_email,$mytime);
}
Here, we're using the built-in PHP functio n se t co o kie () with three parameters: " nam e " and " e m ail" are the names
we're giving the respective co o kies, and $ cust o m e r_nam e and $ cust o m e r_e m ail are the values that we go t fro m
the $ _GET superglo bal. $ m yt im e is the t im e st am p at which we want the co o kies to expire - since it's measured in
seco nds, we simply to o k t im e () and added eno ugh seco nds to make 1 year.

Bro wse r co o kie s are simply variables that are sto red within the user's bro wser o n his/her co mputer. If yo u lo o k in
yo ur o wn bro wser preferences, yo u can actually view all the co o kies that are set:

No w take ano ther lo o k at the co de in co ntact_fo rm.php


if ($_COOKIE['name']) {
echo $_COOKIE['name'];
}

Just like $ _GET and $ _POST sto re values set by the user, and $ _SERVER and $ _ENV sto re values set by the
enviro nment, $ _COOKIE is a supe rglo bal array -- but this time the values being sto red are set by yo u, the
pro grammer.

Befo re co o kies, o nce a user left a website, that site had no way reco gnizing that user when she came back. Basically,
the user had to start fro m scratch every time. No sho pping carts, perso nalized ho me pages, o r pre-filled fo rms. So as
yo u can see, intro ducing co o kies o pened up a wo rld o f po wer and co nvenience that have made them invaluable to
web pro gramming.

Knowing the User T hrough Sessions


Of co urse, there are a co uple o f do wnfalls to using co o kies. One is that different bro wsers have different restrictio ns o n
the number and size o f co o kies - so me allo w unlimited numbers but small sizes, o thers allo w large co o kies but o nly
up to 10 .

But the main pro blem with co o kies is privacy. Anyo ne who uses the same bro wser that yo u used - unless yo u deleted
yo ur co o kies befo re yo u left - can no w view yo ur name and email in the bro wser co o kie list. Think if that had been even
mo re sensitive info rmatio n, like usernames o r financial info rmatio n. Yikes! Let's try fixing this.
Add the fo llo wing to co ntact_fo rm.php, in green:
<?php

#start the session before any output


session_start();

require($_SERVER['DOCUMENT_ROOT']."/template_top.inc");

if ($_GET['error'] == "1") {
$error_code = 1; //this means that there's been an error and we need to notify the
customer
}

?>

<h3>Contact ACME Corporation</h3>


<?
if ($error_code) {
echo "<div style='color:red'>Please help us with the following:</div>";
}
?>
<form method="GET" action="contact.php">
<table>
<tr>
<td align="right">
Name:
</td>
<td align="left">
<?
if ($_SESSION['name']) {
echo $_SESSION['name'];
}
else {
?>
<input type="text" size="25" name="name" value="<? echo $_GET['name']; ?>" />
<input type="checkbox" name="remember" /> Remember me on this computer
<?
}
if ($error_code && !($_GET['name'] || $_SESSION['name'])) {
echo "<b>Please include your name.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Email:
</td><td align="left">
<?
if ($_SESSION['email']) {
echo $_SESSION['email'];
}
else {
?>
<input type="text" size="25" name="email" value="<? echo $_GET['email']; ?>" />
<?
}
if ($error_code && !($_GET['email'] || $_SESSION['email'])) {
echo "<b>Please include your email address.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Type of Request:
</td>
<td align="left">
<select name="whoami">
<option value="" />Please choose...
<option value="newcustomer"<?
if ($_GET['whoami'] == "newcustomer") {
echo " selected";
}
?> />I am interested in becoming a customer.
<option value="customer"<?
if ($_GET['whoami'] == "customer") {
echo " selected";
}
?> />I am a customer with a general question.
<option value="support"<?
if ($_GET['whoami'] == "support") {
echo " selected";
}
?> />I need technical help using the website.
<option value="billing"<?
if ($_GET['whoami'] == "billing") {
echo " selected";
}
?> />I have a billing question.
</select>
<?
if ($error_code && !($_GET['whoami'])) {
echo "<b>Please choose a request type.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Subject:
</td>
<td align="left">
<input type="text" size="50" max="50" name="subject" value="<? echo $_GET['subject']; ?
>" />
<?
if ($error_code && !($_GET['subject'])) {
echo "<b>Please add a subject for your request.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right" valign="top">
Message:
</td>
<td align="left">
<textarea name="message" cols="50" rows="8">
<? echo $_GET['message']; ?>
</textarea>
<?
if ($error_code && !($_GET['message'])) {
echo "<b>Please fill in a message for us.</b>";
}
?>
</td>
</tr>
<tr>
<td colspan="2" align="left">
How did you hear about us?
<ul>
<input type="radio" name="found" value="wordofmouth" />Word of Mouth<br/>
<input type="radio" name="found" value="search" />Online Search<br/>
<input type="radio" name="found" value="article" />Printed publication/article<br/>
<input type="radio" name="found" value="website" />Online link/article<br/>
<input type="radio" name="found" value="other" />Other
</ul>
</td>
</tr>
<tr>
<td colspan="2">
<input type="checkbox" name="update1" checked="checked" />Please email me updates about
your products.<br/>
<input type="checkbox" name="update2" />Please email me updates about products from thi
rd-party partners.
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="SUBMIT" />
</td></tr>
</table>
</form>

<?
require($_SERVER['DOCUMENT_ROOT']."/template_bottom.inc");
?>

Be sure to Save co nt act _f o rm .php.


No w switch to co ntact.php and make the fo llo wing changes, in green:
<?php

function mail_message($data_array, $template_file, $deadline_str, $myname, $myemail) {

#get template contents, and replace variables with data


$email_message = file_get_contents($template_file);
$email_message = str_replace("#DEADLINE#", $deadline_str, $email_message);
$email_message = str_replace("#WHOAMI#", $data_array['whoami'], $email_message);
$email_message = str_replace("#DATE#", date("F d, Y h:i a"), $email_message);
$email_message = str_replace("#NAME#", $myname, $email_message);
$email_message = str_replace("#EMAIL#", $myemail, $email_message);
$email_message = str_replace("#IP#", $_SERVER['HTTP_X_FORWARDED_FOR'], $email_messag
e);
$email_message = str_replace("#AGENT#", $_SERVER['HTTP_USER_AGENT'], $email_message)
;
$email_message = str_replace("#SUBJECT#", $data_array['subject'], $email_message);
$email_message = str_replace("#MESSAGE#", $data_array['message'], $email_message);
$email_message = str_replace("#FOUND#", $data_array['found'], $email_message);

#include whether or not to contact the customer with offers in the future
$contact = "";
if (isset($data_array['update1'])) {
$contact = $contact." Please email updates about your products.<br/>";
}
if (isset($data_array['update2'])) {
$contact = $contact." Please email updates about products from third-party partne
rs.<br/>";
}
$email_message = str_replace("#CONTACT#", $contact, $email_message);

#construct the email headers


$to = " ReplaceWithYourOwnEmailAddress@oreillyschool.com"; //for testing purposes,
this should be YOUR email address.
$from = $data_array['email'];
$email_subject = "CONTACT #".time().": ".$data_array['subject'];

$headers = "From: " . $from . "\r\n";


$headers .= 'MIME-Version: 1.0' . "\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n"; #now mail
mail($to, $email_subject, $email_message, $headers);

#start the session


session_start();

$customer_name = $_SESSION['name'];
if (!($customer_name)) {
$customer_name = $_GET['name'];
}

$customer_email = $_SESSION['email'];
if (!($customer_email)) {
$customer_email = $_GET['email'];
}

#Remember, if you place any output before a header() call, you'll get an error.
#We used the superglobal $_GET here
if (!($customer_name && $customer_email && $_GET['whoami']
&& $_GET['subject'] && $_GET['message'])) {

#with the header() function, no output can come before it.


#echo "Please make sure you've filled in all required information.";
$query_string = $_SERVER['QUERY_STRING'];
#add a flag called "error" to tell contact_form.php that something needs fixed
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php?".$query_string."&error=1"
;
header("Location: ".$url);
exit(); //stop the rest of the program from happening

#we want a deadline 2 days after the message date.


$deadline_array = getdate();
$deadline_day = $deadline_array['mday'] + 2;

$deadline_stamp = mktime($deadline_array['hours'],$deadline_array['minutes'],$deadli
ne_array['seconds'],
$deadline_array['mon'],$deadline_day,$deadline_array['year']);
$deadline_str = date("F d, Y", $deadline_stamp);

if (isset($_GET['remember'])) {
#the customer wants us to remember him/her for next time
$_SESSION['name'] = $customer_name;
$_SESSION['email'] = $customer_email;
}

//DOCUMENT_ROOT is the file path leading up to the template name.


mail_message($_GET, $_SERVER['DOCUMENT_ROOT']."/email_template.txt", $deadline_str, $cu
stomer_name, $customer_email);

include($_SERVER['DOCUMENT_ROOT']."/template_top.inc");

extract($_GET, EXTR_PREFIX_SAME, "get");

echo "<h3>Thank you!</h3>";


echo "We'll get back to you by ".$deadline_str.".<br/>";
echo "Here is a copy of your request:<br/><br/>";
echo "CONTACT #".time().":<br/>";
echo "Message Date: ".date("F d, Y h:i a")."<br/>";
echo "Name: ".$customer_name."<br/>";
echo "Email: ".$customer_email."<br/>";
echo "Type of Request: ".$whoami."<br/>";
echo "Subject: ".$subject."<br/>";
echo "Message: ".$message."<br/>";
echo "How you heard about us: ".$found."<br/>";

for ($i = 1; $i <= 2; $i++) {


$element_name = "update".$i;
echo $element_name.": ";
echo $$element_name;
echo "<br/>";
}

echo "You are currently working on ".$_SERVER['HTTP_USER_AGENT'];


echo "<br/>The IP address of the computer you're working on is ".$_SERVER['HTTP_X_FORWA
RDED_FOR'];

?>
<br/><br/><a href="download.php"><b>Download our PDF brochure!</b></a>
<?

include($_SERVER['DOCUMENT_ROOT']."/template_bottom.inc");

?>

Save co nt act .php, then switch to co ntact_fo rm.php and Preview. Yo u'll no tice that yo u have to re-enter yo ur name
and email address again, but no t fo r lo ng. Be sure to click the "Remember me o n this co mputer" checkbo x when yo u
submit the fo rm. What did yo u get?

It sho uld lo o k so mething like this:

ACME, INC.
links go here
Thank you!
We'll get back to you by June 11, 2006.
Here is a copy of your request:

CONTACT # 1149880113:
Message Date: June 09, 2006 02:08 pm
Name: Trish
Email: trish@myemail.com
Type of Request: support
Subject: Please help!
Message: I can\'t get the darn thing to work!
How you heard about us: wordofmouth
update1: on
update2:
You are currently working on Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O;
en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7
The IP address of the computer you're working on is 63.171.219.74

Download our PDF brochure!

Again, it lo o ks exactly the same as always. But, if yo u go back to co nt act _f o rm .php and RELOAD, yo u'll get:

So mething like this:


ACME, INC.
links go here
Contact ACME Corporation

Name: Trish
Email: trish@myemail.com
Type of Request: Please choose...
Subject:
Message:

How did you hear about us?

Word of Mouth
Online Search
Printed publication/article
Online link/article
Other

Please email me updates about your products.


Please email me updates about products from third-party partners.
Yes, it's exactly the same o utput as when yo u used co o kie s -- yo ur name and email address are no w magically
saved within the bro wser.

So what's the difference? If yo u check o ut yo ur bro wser's preferences and view the co o kies sto red there, yo u wo n't
see yo ur name and email address in there anymo re. Instead, yo u'll see so mething like this:
Take ano ther lo o k at the co de in co ntact.php:
#start the session
session_start();

$customer_name = $_SESSION['name'];
if (!($customer_name)) {
$customer_name = $_GET['name'];
}

$customer_email = $_SESSION['email'];
if (!($customer_email)) {
$customer_email = $_GET['email'];
}
.
.
.
if (isset($_GET['remember'])) {
#the customer wants us to remember him/her for next time
$_SESSION['name'] = $customer_name;
$_SESSION['email'] = $customer_email;
}

Any time yo u want to use se ssio ns in yo ur PHP script, yo u must start the sessio n first - using the PHP functio n
se ssio n_st art (). This way, the bro wser kno ws to pull up the $ _SESSION supe rglo bal using the SESSION ID that
was set in yo ur bro wser co o kies. Once it's been pulled up, yo u can no t o nly access the values using $ _SESSION,
yo u can set the values to o .

Note It's impo rtant to stress that se ssio n_st art () must be called be f o re any o utput - much like he ade r().

Deleting Sessions
In case so meo ne else visits o ur site using the same bro wser, we sho uld give the user a way to end the
sessio n witho ut waiting fo r it to expire.
Add the fo llo wing to co ntact_fo rm.php, in green and blue:

<?php

if (isset($_GET['delete_session'])) {
session_start(); //must always use this command to access the session and its
variables
session_destroy(); //force the session to end

//Add in a page reload so that the session_destroy() will take effect


if($_SESSION && $_SESSION['name']){
$url = "http://".$_SERVER['HTTP_HOST']."/contact_form.php";
header("Location: ".$url);
}
}
else {
#start the session before any output
session_start();
}

require($_SERVER['DOCUMENT_ROOT']."/template_top.inc");

if ($_GET['error'] == "1") {
$error_code = 1; //this means that there's been an error and we need to noti
fy the customer
}

?>

<h3>Contact ACME Corporation</h3>


<?
if ($error_code) {
echo "<div style='color:red'>Please help us with the following:</div>";
}
?>
<form method="GET" action="contact.php">
<table>
<tr>
<td align="right">
Name:
</td>
<td align="left">
<?
if ($_SESSION['name']) {
echo $_SESSION['name'];
?>
<a href="contact_form.php?delete_session=1">Not <? echo $_SESSION['name']; ?>?<
/a>
<?
}
else {
?>
<input type="text" size="25" name="name" value="<? echo $_GET['name']; ?>" />
<input type="checkbox" name="remember" /> Remember me on this computer
<?
}
if ($error_code && !($_GET['name'] || $_SESSION['name'])) {
echo "<b>Please include your name.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Email:
</td><td align="left">
<?
if ($_SESSION['email']) {
echo $_SESSION['email'];
}
else {
?>
<input type="text" size="25" name="email" value="<? echo $_GET['email']; ?>" />
<?
}
if ($error_code && !($_GET['email'] || $_SESSION['email'])) {
echo "<b>Please include your email address.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Type of Request:
</td>
<td align="left">
<select name="whoami">
<option value="" />Please choose...
<option value="newcustomer"<?
if ($_GET['whoami'] == "newcustomer") {
echo " selected";
}
?> />I am interested in becoming a customer.
<option value="customer"<?
if ($_GET['whoami'] == "customer") {
echo " selected";
}
?> />I am a customer with a general question.
<option value="support"<?
if ($_GET['whoami'] == "support") {
echo " selected";
}
?> />I need technical help using the website.
<option value="billing"<?
if ($_GET['whoami'] == "billing") {
echo " selected";
}
?> />I have a billing question.
</select>
<?
if ($error_code && !($_GET['whoami'])) {
echo "<b>Please choose a request type.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right">
Subject:
</td>
<td align="left">
<input type="text" size="50" max="50" name="subject" value="<? echo $_GET['subje
ct']; ?>" />
<?
if ($error_code && !($_GET['subject'])) {
echo "<b>Please add a subject for your request.</b>";
}
?>
</td>
</tr>
<tr>
<td align="right" valign="top">
Message:
</td>
<td align="left">
<textarea name="message" cols="50" rows="8">
<? echo $_GET['message']; ?>
</textarea>
<?
if ($error_code && !($_GET['message'])) {
echo "<b>Please fill in a message for us.</b>";
}
?>
</td>
</tr>
<tr>
<td colspan="2" align="left">
How did you hear about us?
<ul>
<input type="radio" name="found" value="wordofmouth" />Word of Mouth<br/>
<input type="radio" name="found" value="search" />Online Search<br/>
<input type="radio" name="found" value="article" />Printed publication/article<b
r/>
<input type="radio" name="found" value="website" />Online link/article<br/>
<input type="radio" name="found" value="other" />Other
</ul>
</td>
</tr>
<tr>
<td colspan="2">
<input type="checkbox" name="update1" checked="checked" />Please email me update
s about your products.<br/>
<input type="checkbox" name="update2" />Please email me updates about products f
rom third-party partners.
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="SUBMIT" />
</td></tr>
</table>
</form>

<?
require($_SERVER['DOCUMENT_ROOT']."/template_bottom.inc");
?>

Be sure to Save co nt act _f o rm .php, then Preview.

It sho uld lo o k so mething like this:


ACME, INC.
links go here
Contact ACME Corporation

Name: Trish Not Trish?


Email: trish@myemail.com
Type of Request: Please choose...
Subject:
Message:

How did you hear about us?

Word of Mouth
Online Search
Printed publication/article
Online link/article
Other

Please email me updates about your products.


Please email me updates about products from third-party partners.
Try clicking the link to see what happens:
ACME, INC.
links go here
Contact ACME Corporation

Remember me on this
Name:
computer
Email:
Type of
Please choose...
Request:
Subject:
Message:

How did you hear about us?

Word of Mouth
Online Search
Printed publication/article
Online link/article
Other

Please email me updates about your products.

Ending the sessio n was pretty straightfo rward, because sessio n_destro y() will destro y all the sessio n data
fo r a user. If we wanted to delete just o ne sessio n variable, we wo uld use
unse t ($ _SESSION['so m e _var']).

Co ngratulatio ns! Yo u've no w learned the PHP skills needed to make a vast range o f ro bust, co mmercial applicatio ns fo r the
web. Are yo u ready fo r tho se skills to be tested? Make sure yo u have Saved yo ur wo rk and handed in the assignm e nt s fo r this
lesso n. Then, it's time fo r yo ur f inal pro je ct .

Go o d luck! We kno w yo u can do it.

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.
Final Project

Final Project
The o verall go al o f this pro ject is to create a sho pping cart, with pro ducts, prices, registratio n, and a checko ut area. Yo u
can make this sho pping cart any way yo u wish.

Fo r the sake o f evaluatio n, try to include as many elements discussed in this co urse as yo u can. Fo r instance, yo u
sho uld use arrays fo r pro ducts, functio ns fo r vario us pro gram tasks, template files, fo rm validatio n, and
co o kies/sessio ns fo r cart persistence. Yo u are enco uraged to o bserve go o d pro gramming practices, with co mments,
co de reusability and readability.

Yo u can hand in up to five files, but yo u do n't have to create that many if yo u do n't want to .

Be creative and have fun! Yo u want to present yo urself in a pro fessio nal yet friendly way, so feel free to express
yo urself!

Copyright © 1998-2014 O'Reilly Media, Inc.

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.

Anda mungkin juga menyukai