I just wanted to say Hello.
—into the web page presented to the
user A.
As of this writing, the current version of
HTML is 5, which should remain the norm
for some time to come (it was officially
standardized in 2014). HTML5 is a solid
and practical version of the language, well
suited for today’s web.
Before getting into the syntax of PHP, let’s
create one simple but valid HTML document
that can act as a template for many of this
book’s examples.
2
Chapter 1
A How one web browser renders the
HTML code.
Basic CSS
HTML elements define a page’s content, but formatting the look and behavior of such content is
left to CSS (Cascading Style Sheets). As with HTML, this book does not teach CSS in any detail, but
because some of the book’s code uses CSS, you should be familiar with its basic syntax.
You can add CSS to a web page in a couple of ways. The first, and easiest, method is to use HTML
style tags:
The CSS rules are defined between the opening and closing style tags.
You can also use the link HTML tag to incorporate CSS rules defined in an external file:
That file would contain only the rules, without the style tags.
CSS rules are applied to combinations of general page elements, CSS classes, and specific items:
img { border: 0px; }
.error { color: red; }
#about { background-color: #ccc; }
The first rule applies to every image tag. The second applies to any element that has a class
of error:
Error!
The third rule applies only to the specific element that has an id value of about:
About...
(Not all elements need to have an id attribute, but no two elements should have the same id value.)
For the most part, this book uses CSS only to do simple things, such as changing the color or background color of an element or some text.
For more on CSS, search the web or see a dedicated book on the subject.
Getting Started with PHP
3
To create an HTML page:
1. Open your text editor or integrated
development environment (IDE).
You can use pretty much any application to create HTML and PHP pages.
Popular choices include
> Adobe’s Dreamweaver
(www.adobe.com)
B PhpStorm and most
other web development
applications can create the
basics of an HTML document
for you.
> Aptana Studio (www.aptana.com)
> PhpStorm (www.jetbrains.com)
> Sublime Text (www.sublimetext.com)
> Atom (https://atom.io)
The first three are IDEs, making them
more complicated to use but also more
powerful. The last two are text editors.
All these programs run on most common
operating systems.
2. Choose File > New to create a new,
blank document.
Some text editors allow you to start by
creating a new document of a certain
type—for example, a new HTML file B.
If your application has this option, use it!
3. Start with the HTML header lines
(Script 1.1):
A valid HTML5 document begins with
these lines. They tell the web browser
what type of document to expect. For
this template, and in this entire book,
HTML5 pages will be created. One of
the niceties of HTML5 is its minimal
doctype and syntax.
4
Chapter 1
Script 1.1 This simple document contains the
basics of an HTML5 page.
1
2
3
4
5
6
7
8
9
10
11
12
Welcome to this Page!
This is a basic HTML page!
Even with some decoration,
it's still not very exciting.
Understanding Encoding
Encoding is a huge subject, but what
you most need to understand is this:
The encoding you use in a file dictates
what characters can be represented
(and therefore, what written languages
you can use). To select an encoding, you
must first confirm that your text editor
or IDE can save documents using that
encoding. Some applications let you
set the encoding in the preferences or
options area; others set the encoding
when you save the file.
To indicate the encoding to the browser,
there’s a corresponding meta tag:
The charset=utf-8 part says that
UTF-8 (short for 8-bit Unicode Transformation Format) encoding is being used.
Unicode is a way of reliably representing
every symbol in every alphabet. Version
8.0.0 of Unicode—the current version as
of this writing—supports over 120,000
characters! The most commonly used
Unicode encoding is UTF-8.
If you want to create a multilingual web
page, UTF-8 is the way to go, and it’ll be
used in this book’s examples. You don’t
have to, of course. But whatever encoding you do use, make sure the encoding
indicated by the HTML page matches the
actual encoding used by the text editor
or IDE. If you don’t, you’ll likely see odd
characters when viewing the page in a
web browser.
4. Create the head section of the page:
Welcome to this Page!
➝
The head of an HTML page should
include the charset meta tag. The
“Understanding Encoding” sidebar discusses what this means in more detail.
The head also contains the page’s
title, which appears at the top of the
browser window or tab, as well as in
the browser’s bookmarks and history.
You can also place JavaScript and CSS
references in the head.
5. Create the body section:
This is a basic HTML page!
➝
Even with some
➝ decoration, it's still not
➝ very exciting.
The page’s content—what is shown in
the browser—goes between opening
and closing body tags.
6. Complete the page with a closing
HTML tag:
continues on next page
Getting Started with PHP
5
7. Choose File > Save As. In the dialog
box that appears, choose Text Only
(or ASCII) for the format, if you’re given
the option.
HTML and PHP documents are just
plain text files (unlike, for example, a
Microsoft Word document, which is
stored in a proprietary, binary format).
You may also need to indicate the
encoding (utf-8) when you save the
file (again, see the “Understanding
Encoding” sidebar).
8. Navigate to the location where you
wish to save the script.
You can place this script anywhere
you’d like on your computer, although
using one dedicated folder for every
script in this book, perhaps with subfolders for each chapter, makes sense.
9. Save the file as welcome.html.
HTML5 pages use the standard
.html extension.
10. Test the page by viewing it in your
browser C.
Unlike with PHP scripts (as you’ll soon
discover), you can test HTML pages by
opening them directly in a browser.
Search the web or use the book’s support forum (www.LarryUllman.com/forums/) to
find a good HTML and PHP editor or IDE.
For more information on HTML, check out
Elizabeth Castro and Bruce Hyslop’s excellent
book HTML and CSS, Eighth Edition: Visual
QuickStart Guide (Peachpit Press, 2014).
6
Chapter 1
C The HTML page, as interpreted by the browser.
Basic PHP Syntax
Now that you’ve seen how HTML will be
handled in this book, it’s time to begin
PHP scripting. To create a PHP page, you’ll
start exactly as you would if you were
creating an HTML document from scratch.
Understanding the reason for this is vitally
important: Web browsers are client applications that understand HTML; PHP is a
server-side technology that cannot run in
the client. To bridge this gap, PHP is used
on the server to generate HTML that’s run
in a browser (refer to the section “How
PHP Works” in this book’s “Introduction” for
a visual representation of this relationship).
There are three main differences between
a standard HTML page and a PHP script.
First, PHP scripts should be saved with the
.php file extension (for example, index.php).
Second, you place PHP code within tags, normally within the context of
some HTML:
...
This is HTML.
More HTML
...
The PHP tags indicate the parts of the
page to be run through the PHP processor
on the server. This leads to the third major
difference: PHP scripts must be run on a
PHP-enabled web server (whereas HTML
pages can be viewed on any computer,
directly in a browser). This means that
PHP scripts must always be run through
a URL (for example, http://example.com/
page.php). If you’re viewing a PHP script in
a web browser and the address does not
begin with http, the PHP script will not work.
Getting Started with PHP
7
To make this first PHP script do something
without too much programming fuss, you’ll
use the phpinfo() function. This function,
when called, sends a table of information to
the web browser. That table lists the specifics of the PHP installation on that particular
server. It’s a great way to test your PHP
installation and has a high “bang for your
buck” quality.
However, the phpinfo() function not only
outputs a table of information, it also creates
a complete HTML page for you. So this first
PHP script does not require the standard
HTML code, although subsequent scripts in
this chapter will.
To create a new PHP script
on your computer:
1. Create a new PHP document in
your text editor or IDE, to be named
phpinfo.php (Script 1.2).
For this specific case, you’ll start with a
blank file. But if your text editor or IDE
has PHP file templates for you, you can
certainly start with one of those.
2. Begin the page with
3. Add the following on the next line:
phpinfo();
The syntax will be explained in detail
later, but in short, this is just a call to an
existing PHP function named phpinfo.
You must use the opening and closing
parentheses, with nothing between
them, and the semicolon.
4. Type ?> on its own line, as the last line.
The closing PHP tag tells the server that
the PHP section of the script is over.
Again, because the phpinfo() function
generates a complete HTML page for
you, no HTML tags are needed.
5. Save the script as phpinfo.php.
Not to overstate the point, but remember that PHP scripts must use a valid
file extension. Most likely you’ll have
no problems if you save your files as
filename.php.
You also need to be certain that the
application or operating system is not
adding a hidden extension to the file.
Notepad on Windows, for example,
attempts to add .txt to uncommon
file extensions, which renders the PHP
script unusable. (Generally speaking,
do not use Notepad.)
Just as a file’s extension on your computer
tells the operating system in what application
to open the file, a web page’s extension tells
the server how to process the file: file.php
goes through the PHP module, file.aspx is
processed as ASP.NET, and file.html is a
static HTML document (normally). The extension associations are determined by the web
server’s settings.
If you’re developing PHP scripts for a
hosted website, check with your hosting company to learn which file extensions you can
use for PHP documents. In this book you’ll see
.php, the most common extension.
You’ll occasionally see PHP’s short tags—
simply and ?>—used in other people’s
scripts, although I recommend sticking with
the formal tags: . Support for the
short tags must be enabled on a server, and
using them makes your code less portable.
You’ll find it handy to have a copy of the
phpinfo.php file around. As you’ll soon see,
this script reports upon PHP’s capabilities,
settings, and other features of your server.
In fact, this book frequently suggests you
return to this script for those purposes.
PHP scripts can also be executed without a web browser, using a command-line
interface and a standalone PHP executable.
But that topic is well outside the scope of this
book (and it’s a much less common use of PHP
regardless).
Getting Started with PHP
9
Using SFTP
Unlike HTML, which can be tested directly
in a browser, PHP scripts need to be run
from a PHP-enabled server in order to
see the results. Specifically, PHP is run
through a web server application, such
as Apache (http://httpd.apache.org), Nginx
(www.nginx.com), or Internet Information
Server (IIS; www.iis.net).
You can obtain a PHP-enabled server in
one of two ways:
n
n
Install the software on your own
computer.
Acquire web hosting.
PHP is open source software (meaning,
in part, that it’s free) and is generally easy
to install (with no adverse effect on your
computer). If you want to install PHP and
a web server on your computer, follow the
directions in Appendix A, “Installation and
Configuration.” Once you’ve done so, you
can skip ahead to the next section of the
chapter, where you’ll learn how to test your
first PHP script.
If you’re not running PHP on your own
computer, you’ll need to transfer your PHP
scripts to the PHP-enabled server using
SFTP (Secure File Transfer Protocol). The web
hosting company or server’s administrator
will provide you with SFTP access information, which you’ll enter into an SFTP client.
Many SFTP client applications are available;
this next sequence of steps uses the free
FileZilla (http://filezilla-project.org), which
runs on many operating systems.
To SFTP your script to the server:
1. Open your SFTP application.
2. In the application’s connection window,
enter the information provided by your
web host A.
SFTP access requires a host (for example, the domain name or an IP address),
username, and password.
3. Click Quickconnect (or your SFTP
client’s equivalent).
If you’ve provided the correct information, you should be able to connect. If
not, you’ll see error messages at the
top of the FileZilla window B.
A The connection section of FileZilla’s main window (as it appears on the Mac).
B The reported error says that the connection attempt was refused.
10
Chapter 1
4. Navigate to the proper directory for
your web pages (for example, www,
htdocs, or httpdocs).
The SFTP application won’t necessarily
drop you off in the appropriate directory.
You may need to do some navigation
to get to the web document root. The
web document root is the directory on
the server to which a URL directly points
(for example, www.larryullman.com,
as opposed to www.larryullman.com/
somedir/). If you’re unsure of what the
web document root is for your setup, see
the documentation provided by the hosting company (or ask them for support).
In FileZilla, the right column represents
the files and directories on the server;
the left column represents the files and
directories on your computer C. Just
double-click folders to open them.
5. Upload your script—phpinfo.php—to
the server.
To do this in FileZilla, drag the file from
the left column—your computer—to the
right column—the server.
Some text editors and IDEs have built-in
SFTP capability, allowing you to save your
scripts directly to the server. Other applications can run PHP scripts without leaving the
application at all.
You can also transfer files to your web
server using version control software, such as
Git (https://git-scm.com). Although this is an
excellent route, it’s well beyond the scope of
a beginner’s guide to PHP.
C I’ve successfully connected to the remote server and navigated into the html directory (aka the web
document root).
Getting Started with PHP
11
Testing Your Script
Testing a PHP script is a two-step process.
First, you must put the PHP script in the
appropriate directory for the web server.
Second, you run the PHP script in your web
browser by loading the correct URL.
If you’re using a separate web server,
like one provided by a hosting company,
you just need to use an SFTP application
to upload your PHP script to it (as in the
previous steps). If you have installed PHP
on your personal computer, then you can
test your PHP scripts by saving them in, or
moving them to, the web document root.
This is normally
n
~/Sites for Mac OS X users (where
~ stands for your home directory; this
is no longer created automatically on
newer versions of Mac OS X, but you
can make one)
n
C:\Inetpub\wwwroot for Windows
users running IIS
n
n
C:\xampp\htdocs for Windows
users running XAMPP
(www.apachefriends.org)
/Applications/MAMP/htdocs for Mac
users running MAMP (www.mamp.info)
If you’re not sure what the web document
root for your setup is, see the documentation for the web server application or
operating system (if the web server application is built in).
Once you’ve got the PHP script in the right
place, use your browser to execute it.
12
Chapter 1
To test your script in the browser:
1. Open your favorite web browser.
For the most part, PHP doesn’t behave
differently on different browsers
(because PHP runs on the server), so
use whichever browser you prefer.
In this book, you’ll see that I primarily
use Chrome, regardless of the operating system.
2. In the browser’s address bar, enter the
URL of the site where your script has
been saved.
In my case, I enter www.larryullman.com,
but your URL will certainly be different.
If you’re running PHP on your own
computer, the URL is http://localhost
(Windows); or http://localhost/
~username (Mac OS X), where you
should replace username with your
username. Some all-in-one packages,
such as MAMP and XAMPP, may also
use a port as part of the URL: http://
localhost:8888.
If you’re not sure what URL to use, see
the documentation for the web server
application you installed.
3. Add /phpinfo.php to the URL.
If you placed the script within a subdirectory of the web document root,
you would add that subdirectory
name to the URL as well (for example,
/ch01/phpinfo.php).
4. Press Return/Enter to load the URL.
The page should load in your browser
window A.
continues on next page
A If the script executed correctly, the browser result should look like this (woohoo!).
Getting Started with PHP
13
If you see the PHP code B or a blank
page, it could mean many things:
n
n
n
You are not loading the PHP script
through a URL (that is, the address
does not begin with http). Note that
you may need to click the address bar
to view the full URL, including the http,
because many of today’s browsers
hide this by default.
n
n
You are not using the proper extension.
You entered the incorrect URL.
The PHP script is not in the proper
directory.
The PHP script does not have the correct name or extension.
It’s very important to remember that you
can’t open a PHP file directly in a browser as
you would open HTML pages or files in other
applications. PHP scripts must be processed
by the web server, which means you must
access them via a URL (an address that starts
with http://).
Even if you aren’t a seasoned computer
professional, you should consider installing
PHP on your computer. Doing so isn’t too difficult, and PHP is free. Again, see Appendix A
for instructions.
14
code is not being executed.
PHP has not been enabled on
the server.
If you see a file not found or similar error C,
it could be because
n
B If you see the raw PHP code, then the PHP
Chapter 1
C This server response indicates a mismatch
between the URL attempted and the files that
actually exist on the server.
Sending Text to
the Browser
PHP wouldn’t be very useful if all you
could do was see that it works (although
that confirmation is critical). You’ll use PHP
most frequently to send information to the
browser in the form of plain text and HTML
tags. To do so, use print:
print "something";
Just type the word print, followed by what
you want to display: a simple message, the
value of a variable, the result of a calculation, and so forth. In that example, the
message is a string of text, so it must be
surrounded with quotation marks.
PHP is case-insensitive when it comes to
calling functions, such as phpinfo() and
print. Using print, Print, and PRINT
nets the same results. Later in the book,
you’ll see examples where case makes a
crucial difference.
To be clear, print doesn’t actually print
anything; it just outputs data. When a PHP
script is run through a browser, that PHP
output is received by the browser itself as
if it were content from a static HTML file.
Also note that the line is terminated by a
semicolon (;). Every statement in PHP code
must end with a semicolon, and forgetting
this requirement is a common cause of
errors. A statement in PHP is an executable
line of code, like
print "something";
or
phpinfo();
Conversely, comments, PHP tags, control
structures (for example, conditionals
and loops), and certain other constructs
discussed in this book don’t require
semicolons.
Getting Started with PHP
15
Finally, you should know about a minor
technicality: Whereas phpinfo() is a
function, print is actually a language
construct. Although it’s still standard to
refer to print as a function, because
print is a language construct, no parentheses are required when using it, as in
the phpinfo() example.
To print a simple message:
1. Begin a new HTML document in
your text editor or IDE, to be named
hello1.php (Script 1.3):
Hello, World!
The following was created by
➝ PHP:
Most of this code is the standard HTML.
The last line will be used to distinguish
between the hard-coded HTML and the
PHP-generated HTML.
2. On the next line, type
Hello, World!
The following was created by PHP:
4. Close the PHP section and complete
the HTML page:
A A simple Hello, world! example: your first
foray into PHP programming.
?>
5. Save the file as hello1.php, place it on
your PHP-enabled server, and test it in
your browser A.
If you’re running PHP on your own computer, remember that you can save the
file to the proper directory and access
the script via http://localhost/.
If you see an error or a blank page
instead of the results shown in the
figure, review the “Testing Your Script”
section, or skip ahead to the “Basic
Debugging Steps” section at the end of
this chapter.
You can use other functions to send text
to the browser, including echo and printf(),
but this book primarily uses print.
You can—and commonly will—use print
over multiple lines:
print "This is a longer
sentence of text.";
The closing quotation mark terminates the
message being printed, and the semicolon is
placed only at the end of that line.
Getting Started with PHP
17
Using the PHP Manual
The PHP manual—accessible online at
www.php.net/manual—lists every function
and feature of the language. The manual
discusses general concepts (installation,
syntax, variables) first and ends with the
functions by topic (MySQL, string functions,
and so on).
To quickly look up any function in the PHP
manual, go to www.php.net/functionname
in your web browser (for example,
www.php.net/print).
To understand how functions are described,
look at the start of the print function’s
page A.
The first line is the name of the function
itself, followed by the versions of PHP in
which it’s available. As the language grows,
new functions are added and, occasionally,
older functions are removed. Then there’s
a textual description of the function along
with the function’s basic usage. The usage
is the most important and confusing part.
In this example, the first value—int—says
that print returns an integer value (specifically, print returns 1, always). Within the
parentheses, string $arg states that the
function takes one required argument,
which should be in the form of a string.
You’ve already seen this in action.
18
Chapter 1
A The PHP manual’s page for the print language
construct.
As a comparison, check out the manual’s
listing for the nl2br() function B. This
function converts newlines found within
text (the equivalent of pressing Return/
Enter) into HTML break tags. This function,
which returns a string, takes a string as its
first argument and an optional Boolean
(TRUE/FALSE) as its second. The square
brackets indicate optional arguments,
which are always listed last. When a function takes multiple arguments, they are
separated by commas. Hence, this function
can be called like so:
nl2br("Some text");
nl2br("Some text", false);
B The PHP manual’s page for the nl2br()
function.
As the definition also indicates, the second
argument has a default value of true,
meaning it’ll create tags (which is
XHTML compliant) unless the function is
passed a second argument value of false.
In that case, the function will create
tags instead.
The most important thing to remember
about the PHP manual is that it exists! If
you’re ever confused by a function or how
it is properly used, check the PHP manual’s
reference page for it.
Getting Started with PHP
19
To look up a function definition:
1. Go to www.php.net/functionname in
your web browser.
If the PHP manual doesn’t have a
matching record for the function you
tried, check the spelling or look at the
recommended alternatives that the
manual presents C.
2. Compare the versions of PHP that the
function exists in with the version of
PHP you’re using.
Use the phpinfo() function, already
demonstrated, to know for certain what
version of PHP you are running. If a function was added in a later version of PHP,
you’ll need to either upgrade the version
you have or use a different approach.
3. Examine what type of data the function
returns.
C The manual will present alternative functions if
the entered URL doesn’t exactly match a reference.
Sometimes you may be having a problem with a function because it returns a
different type of value than you expect
it to.
4. Examine how many and what types
of arguments the function requires or
can take.
The most common mistake when using
functions is sending the wrong number
or type of arguments when the function
is called.
5. Read the user comments, when present,
to learn more.
Sometimes the user comments can be
quite helpful (other times not).
D Deprecated functions should be avoided in
your code.
If you see a message saying that a function has been deprecated D, that means the
function will be dropped from future versions
of PHP, and you should start using the newer,
better alternative (there is almost always a
better alternative identified).
20
Chapter 1
A Attempting to print double quotation marks will
create errors, because they conflict with the print
statement’s primary double quotation marks.
Script 1.4 Using print, you can send HTML
tags along with text to the browser, where the
formatting will be applied.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Hello, World!
The following was created by PHP:
Hello,
world!";
?>
Sending HTML to
the Browser
As those who first learned HTML quickly
discovered, viewing plain text in a web
browser leaves a lot to be desired. Indeed,
HTML was created to make plain text more
appealing and useful. Because HTML works
by adding tags to text, you can use PHP to
also send HTML tags to the browser, along
with other data:
print "Hello, world!";
There is one situation where you have to be
careful, though. HTML tags that require
double quotation marks, like link, will cause problems
when printed by PHP, because the print
function uses quotation marks as well A:
print "link";
One workaround is to escape the quotation marks within the HTML by preceding
them with a backslash (\):
print "link";
By escaping each quotation mark within
the print statement, you tell PHP to print
the mark itself instead of treating the quotation mark as either the beginning or the
end of the string to be printed.
To send HTML to the browser:
1. Open the hello1.php script (Script 1.3)
in your text editor or IDE, if it is not
already open.
2. Within the HTML head, declare a CSS
class (Script 1.4):
continues on next page
Getting Started with PHP
21
This CSS code declares a class named
bold, which will be used to add emphasis to text. This is obviously a fairly trivial
use of CSS, but by declaring this as a
class, it can easily be updated, perhaps
to change the color of the text or the
size, along with its weight.
B The new version of the Hello, world! page, with
a little more decoration and appeal.
3. Edit the Hello, world! message by
adding HTML tags, making it read as
follows:
print "
➝ Hello, world!";
To make the PHP-generated part of
the message stand out, CSS styling will
bold the greeting. For this to work, you
must escape the quotation marks within
the span tag so they don’t conflict with
the print statement’s quotation mark.
4. Save the script as hello2.php, place
it on your PHP-enabled server, and run
the page in your browser B.
Using White Space
When programming in PHP, white space is generally (but not universally) ignored. Any blank line
(just one or several in a row) in PHP code is irrelevant to the end result. Likewise, tabs and spaces
are normally inconsequential to PHP. And because PHP code is not visible in the browser (unless
there’s a problem with the server), white space in your PHP files has no impact on what the end
user sees.
The spacing of HTML code shows up in the HTML source of a web page but has only a minimal
effect on what’s viewed in the browser. For example, all of a page’s HTML source code could be
placed on one line without changing what the end user sees. If you had to hunt for a problem in
the HTML source, however, you would not like the long, single line of HTML.
You can affect the spacing of dynamically generated HTML code by printing it in PHP over multiple
lines, or by using the newline character (\n) within double quotation marks:
print "Line 1\nLine 2";
Again, use of the newline character affects the HTML source code of the web page, not what the
end user sees rendered in the browser.
To adjust the spacing in the rendered web page, you’ll use CSS, plus paragraph, div, and break
tags, among others.
22
Chapter 1
5. View the HTML page source to see the
code that was sent to the browser C.
How you do this depends on the
browser: Select View > Developer >
View Source in Chrome, View > Page
Source in Firefox, or View > Source in
Internet Explorer.
This is a step you’ll want to be in the
habit of taking, particularly when problems occur. Remember that PHP is
primarily used to generate HTML, sent
to and interpreted by the browser.
Often, confirming what was sent to the
browser (by viewing the source) will help
explain the problem you’re seeing in the
browser’s interpretation (or visible result).
Understanding the role of quotation
marks and how to escape problematic characters is crucial to programming with PHP. These
topics will be covered in more detail in the
next two chapters.
The HTML you send to the web browser
from PHP doesn’t need to be this simple. You
can create tables, JavaScript, and much, much
more.
Remember that any HTML outside the
PHP tags will automatically go to the browser.
Within the PHP tags, print statements are
used to send HTML to the web browser.
C The resulting HTML source code of hello2.php B.
Getting Started with PHP
23
Adding Comments
to Scripts
Comments are integral to programming,
not because they do anything but because
they help you remember why you did
something. The computer ignores these
comments when it processes the script.
Furthermore, PHP comments are never
sent to the browser, remaining your secret.
PHP supports three ways of adding
comments. You can create a single-line
comment by putting either // or # at the
beginning of the line you want ignored:
// This is a comment.
You can also use // or # to begin a comment at the end of a PHP line, like so:
print "Hello"; // Just a greeting.
Although it’s largely a stylistic issue, // is
much more commonly used in PHP than #.
You can create a multiline comment using
/* to begin the comment and */ to conclude it:
/* This is a
multi-line comment. */
Some programmers prefer this comment
style because it contains both open and
closing “tags,” providing demarcation for
where the comment begins and ends.
24
Chapter 1
Script 1.5 PHP and HTML comments are added
to the script to document it and to render a line of
PHP code inert.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Hello, World!
The following was created by PHP:
Hello,
world!";
?>
To add comments to a script:
1. Open the hello2.php created earlier
(Script 1.4) in your text editor or IDE.
2. After the initial PHP tag, add some
comments to your script (Script 1.5):
/*
* Filename: hello3.php
* Book reference: Script 1.5
* Created by: Larry Ullman
*/
This is just a sample of the kind of
comments you can write. You should
document what the script does, what
information it relies on, who created it,
when, and so forth. Stylistically, such
comments are often placed at the top
of a script (as the first thing within the
PHP section, that is), using formatting
like this. The extra asterisks aren’t
required; they just draw attention to
the comments.
3. On line 21, in front of the print statement, type //.
By preceding the print statement with
two slashes, you ensure that the function call is “commented out,” meaning it
will never be executed.
4. After the closing PHP tag (on line 23),
add an HTML comment:
This line of code will help you distinguish among the different comment
types and where they appear. This comment will appear only within the HTML
source code.
continues on next page
Getting Started with PHP
25
5. Save the script as hello3.php, place
it on your PHP-enabled server, and run
the page in your web browser A.
6. View the source of the page to see the
HTML comment B.
You can comment out just one line of
code or several using the /* and */ method.
With // or #, you can negate only one line at
a time.
A With the print statement commented out,
the page looks just as it would if the print call
weren’t there.
Different programmers prefer to comment code in different ways. The important
thing is to find a system that works for you
and stick to it.
Note that you cannot use HTML comment characters () within PHP to
comment out code. You could have PHP print
those tags to the browser, but in that case
you’d create a comment that appeared in the
HTML source code on the client’s computer
(but not in the browser window). PHP comments
never make it as far as a user’s computer.
Despite my strong belief that you can’t
over-comment your scripts, the scripts in this
book aren’t as documented as they should
be, in order to save space. But the book will
document each script’s name and number, for
cross-reference purposes.
When you change a script’s code, be
certain to update its comments as well. It’s
quite confusing to see a comment that suggests
a script or a line of code does something other
than what it actually does.
26
Chapter 1
B HTML comments don’t appear in the web
browser but are in the HTML source. PHP
comments remain in the PHP script on the server,
not visible inside the HTML source.
Basic Debugging Steps
Debugging is by no means a simple concept to grasp, and unfortunately, it’s one
that is only truly mastered by doing. The
next 50 pages could be dedicated to the
subject and you’d still merely pick up a
fraction of the debugging skills that you’ll
eventually acquire and need.
The reason I introduce debugging in this
harrowing way is that it’s important not to
enter into programming with delusions.
Sometimes code won’t work as expected,
you’ll inevitably create careless errors, and
some days you’ll want to pull your hair out,
even when using a comparatively userfriendly language such as PHP. In short,
prepare to be perplexed and frustrated
at times. I’ve been coding in PHP since
1999, and occasionally I still get stuck in
the programming muck. But debugging is
a very important skill to have, and one that
you will eventually pick up out of necessity
and experience. As you begin your PHP
programming adventure, I offer the following basic but concrete debugging tips.
Getting Started with PHP
27
To debug a PHP script:
n
n
Make sure display_errors is on.
This is a basic PHP configuration setting (discussed in Appendix A). You
can confirm this setting by executing
the phpinfo() function ( just use your
browser to search for display_errors
in the resulting page). For security
reasons, PHP may not be set to display
the errors that occur. If that’s the case,
you’ll end up seeing blank pages when
problems occur. To debug most problems, you’ll need to see the errors, so
turn this setting on while you’re learning. You’ll find instructions for doing so
in Appendix A and Chapter 3, “HTML
Forms and PHP.”
28
n
Chapter 1
Trust the error message.
Another very common beginner’s mistake is to not fully read or trust the error
that PHP reports. Although an error
message can often be cryptic and may
seem meaningless, it can’t be ignored.
At the very least, PHP is normally correct as to the line on which the problem
can be found. And if you need to relay
that error message to someone else
(like when you’re asking me for help),
do include the entire error message!
Know what version of PHP you’re
running.
Some problems arise from the version
of PHP in use. Before you ever use
any PHP-enabled server, run the
phpinfo.php file (Script 1.2) to confirm
the version of PHP in use.
Check the HTML source code.
Sometimes the problem is hidden in
the HTML source of the page. In fact,
sometimes the PHP error message can
be hidden there!
Make sure you’re always running PHP
scripts through a URL!
This is perhaps the most common
beginner’s mistake. PHP code must be
run through the web server application, which means it must be requested
through http://something. When you
see actual PHP code instead of the
result of that code’s execution, most
likely you’re not running the PHP script
through a URL.
n
n
n
Take a break!
So many of the programming problems
I’ve encountered over the years, and
the vast majority of the toughest ones,
have been solved by stepping away
from my computer for a while. It’s easy
to become frustrated and confused,
and in such situations, any further steps
you take are likely to make matters
only worse.
These are just some general debugging
techniques, specifically tailored to the beginning PHP programmer. They should suffice
for now, because the examples in this book
are relatively simple. More complex coding
requires more advanced debugging techniques, so my PHP and MySQL for Dynamic
Web Sites: Visual QuickPro Guide, Fourth
Edition (Peachpit Press, 2012) dedicates a
whole chapter to this subject.
Review and Pursue
Each chapter in this book ends with a
“Review and Pursue” section. In these
sections you’ll find:
n
n
Questions regarding the material just
covered
Prompts for ways to expand your
knowledge and experience on your own
If you have any problems with these
sections, in either answering the questions
or pursuing your own endeavors, turn
to the book’s supporting forum
(www.LarryUllman.com/forums/).
Review
n
n
n
n
n
n
n
What is HTML? What is the current
version of HTML?
What encoding is your text editor or IDE
set to use? Does that match the encoding specified in your generated HTML
pages? Why does the encoding matter?
What is CSS and what is it used for?
What file extension should PHP scripts
have for your particular server?
What is meant by “web root directory”?
What is the web root directory for
your server?
How do you test PHP scripts? What
happens when PHP scripts are not
run through a URL?
Name two ways comments can be
added to PHP code. Identify some
reasons to use comments.
Getting Started with PHP
29
Pursue
n
n
n
n
n
If you have access to more than one
server, confirm what version of PHP is
running on another server.
Create a static HTML page that displays
some information. Then replace some of
the static content with content created
by PHP.
Create a template to use for your own
work. The template should contain the
HTML shell, the opening and closing
PHP tags, and some basic comments.
Confirm, using the phpinfo() function,
that display_errors is enabled on
your server. If it’s not, change your
server’s configuration to enable it (see
Chapter 3 and Appendix A).
In subsequent chapters, occasionally
check the PHP manual’s page when a
new function is mentioned in the book.
30 Chapter 1
2
Variables
The previous chapter covered how to use
PHP to send simple text and HTML to a
web browser—in other words, something
for which you don’t need PHP at all! Don’t
worry, though; this book will teach you how
to use print in conjunction with other PHP
features to do great and useful things with
your website.
To make the leap from creating simple,
static pages to dynamic web applications
and interactive websites, you need variables. Understanding what variables are,
the types of variables that a language supports, and how to use them is critical.
This chapter introduces the fundamentals
of variables in PHP, and later chapters
cover the different types in greater detail.
If you’ve never dealt with variables before,
this chapter will be a good introduction. If
you’re familiar with the concept, then you
should be able to work through this chapter
with ease.
In This Chapter
What Are Variables?
32
Variable Syntax
36
Types of Variables
38
Variable Values
41
Understanding Quotation Marks
44
Review and Pursue
48
What Are Variables?
A variable is a container for data. Once
data has been stored in a variable (or,
stated more commonly, once a variable
has been assigned a value), that data can
be altered, printed to the browser, saved to
a database, emailed, and so forth.
Variables in PHP are, by their nature,
flexible: You can put data into a variable,
retrieve that data from it (without affecting
the value of the variable), put new data in
it, and continue this cycle as many times
as necessary. But variables in PHP are
largely temporary: Most only exist—that is,
they only have a value—for the duration
of the script’s execution on the server.
Once the execution of the script completes
(often when the final closing PHP tag is
encountered), those variables cease to
exist. Furthermore, after users click a link
or submit a form, they are taken to a new
page that may have an entirely separate
set of variables.
32 Chapter 2
Before getting too deep into the discussion of variables, let’s write a quick script
that reveals some of PHP’s predefined
variables. These are variables that PHP
automatically creates when a script runs.
Over the course of the book, you’ll be
introduced to many different predefined
variables. This particular example looks
at the predefined $_SERVER variable. It
contains lots of information about the computer on which PHP is running.
The print_r() function offers an easy way
to display any variable’s value:
print_r($variable_name);
Just provide the name of the variable
you’d like to inspect as a single argument
to the print_r() function. (You’ll learn
more about a variable’s syntax throughout
this chapter.)
Script 2.1 This script uses the print_r() function
to show the values stored in the $_SERVER
predefined variable.
1
2
3
4
5
6
7
8
9
10
11
Predefined Variables
To print PHP’s predefined variables:
1. Create a new PHP script in your
text editor or IDE, to be named
predefined.php (Script 2.1).
2. Create the initial HTML tags:
Predefined Variables
➝
This code repeats the HTML template
created in the preceding chapter. Within
the body of the page, the
tags
are being used to make the generated
PHP information more legible. Without
using the
tags, the print_r()
function’s output would be difficult to
read in a browser.
3. Add the PHP code:
The PHP code contains just one function call. The function should be provided with the name of a variable.
In this example, the variable is
$_SERVER, which is special in PHP.
$_SERVER stores all sorts of data about
the server: its name and operating
system, the name of the current user,
information about the web server application (Apache, Nginx, IIS, and so on),
and more. It also reflects the PHP script
being executed: its name, where it’s
stored on the server, and so forth.
continues on next page
Variables
33
Note that you must type $_SERVER
exactly as it is here, in all uppercase letters.
4. Complete the HTML page:
5. Save the file as predefined.php,
upload it to your server (or save it to the
appropriate directory on your computer), and test it in your browser A.
Once again, remember that you must
run all PHP scripts through a URL (that
is, http://something).
6. If possible, transfer the file to another
computer or server running PHP and
execute the script in your browser
again B.
Printing out the value of any variable
as you’ve done here is one of the greatest
debugging tools. Scripts often don’t work
as you expect them to because one or more
variables do not have the values you assume
they should, so confirming their actual values
is extremely helpful.
If you don’t use the HTML
tags, the result will be like the jumble of information in C.
A The $_SERVER variable, as printed out by this script, is a master list
of values pertaining to the server and the PHP script.
34
Chapter 2
B With the predefined.php page, different servers will generate different
results (compare with A).
C With large, complex variables such as $_SERVER, not using the HTML
preformatting tags with print_r() creates an incomprehensible mess
(compare to A B).
Variables
35
Variable Syntax
Now that you’ve had a quick dip in the variable pool, it’s time to swim a bit deeper. In
the preceding example, the script printed
out the value of PHP’s predefined $_SERVER
variable. You can also create your own
variables, once you understand the proper
syntax. To create appropriate variable
names, you must follow these rules:
n
n
n
n
n
n
All variable names must be preceded
by a dollar sign ($).
Following the dollar sign, the variable
name must begin with either a letter
(A–Z, a–z) or an underscore (_). A number cannot immediately follow the
dollar sign.
The rest of the variable name can contain any combination of letters, underscores, and numbers.
You may not use spaces within the
name of a variable. (Instead, the underscore is commonly used to separate
words.)
Each variable must have a unique
name.
Variable names are case-sensitive!
Consequently, $variable and
$Variable are two different constructs,
and it would be a bad idea to use two
variables with such similar names.
This last point is perhaps the most important:
Variable names in PHP are case-sensitive.
Using the wrong letter case is a very
common cause of bugs. (If you used, for
example, $_server or $_Server in the
previous script, you’d see either an error
message or nothing at all A.)
36 Chapter 2
A Misspelling a variable’s name, including its
case, will create undesired and unpredictable
results.
Script 2.2 Properly documenting the purposes of
variables, along with using meaningful names, is a
hallmark of a professional programmer.
To help minimize bugs, I recommend the
following policies:
n
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Variables and Comments
TABLE 2.1 Valid Variables in PHP
Name
n
n
n
Always use all lowercase variable names.
Make your variable names descriptive
(for example, $first_name is better
than $fn).
Use comments to indicate the purpose
of variables (Script 2.2), redundant as
that may seem.
Above all, be consistent with whatever
naming convention you choose!
Table 2.1 lists some sample valid variables;
Table 2.2 lists some invalid variables and
the rules they violate.
Unlike some other languages, PHP
doesn’t require you to declare or initialize a
variable prior to use, although PHP does issue
warnings when you do. In other words, you
can refer to variables without first defining
them. But it’s best not to do that; try to write
scripts so that every variable is defined or
validated before use.
There are two main variable naming
conventions, determined by how you delineate
words. These are the so-called camel-hump
or camel-case (named because of the way
capital letters break up the word—for example,
$FirstName) and underscore ($first_name)
styles. This book uses the latter convention.
$first_name
$person
$address1
$_SERVER
TABLE 2.2 Invalid Variables in PHP
Name
Reason
$first name
Has a space
$first.name
Has a period
first_name
Does not begin with $
$1address
A number cannot follow $
Variables
37
Types of Variables
This book covers three common PHP variable types: numbers, strings, and arrays.
This chapter introduces them quickly, and
later chapters discuss them in more detail:
n
Chapter 4, “Using Numbers”
n
Chapter 5, “Using Strings”
n
Chapter 7, “Using Arrays”
A fourth variable type, objects, is introduced in Appendix B, “Resources and Next
Steps,” but isn’t covered in this book. That
particular subject is just too advanced for
a beginner’s guide—in fact, basic coverage
of the subject in my PHP Advanced and
Object-Oriented Programing: Visual
QuickPro Guide, Third Edition (Peachpit
Press, 2013) requires over 150 pages!
Numbers
Technically speaking, PHP breaks numbers
into two types: integers and floating-point
(also known as double-precision floatingpoint or doubles). Due to the lax way PHP
handles variables, it largely won’t affect your
programming to group the two categories
of numbers into one all-inclusive membership, at least when you’re just starting out.
Still, let’s briefly discuss the differences
between the two, to be precise.
The first type of numbers—integers—is also
known as whole numbers. They can be positive or negative but include neither fractions
nor decimals. Numbers that use a decimal
point (even something like 1.0) are floatingpoint numbers, also known as floats. You
use floating-point numbers to refer to fractions, because the only way to express a
fraction in PHP is to convert it to its decimal
equivalent. Hence, 1¼ is written as 1.25.
Table 2.3 lists some sample valid numbers
and their formal type; Table 2.4 lists invalid
numbers and the rules they violate.
As you’ll soon see, you add quotation
marks around invalid numbers to turn them
into valid strings.
TABLE 2.3 Valid Numbers in PHP
TABLE 2.4 Invalid Numbers in PHP
Number
Type
Number
Reason
1
Integer
1/3
Contains a slash
1.0
Floating-point
1996a
Contains a letter
1972
Integer
08.02.06
19.72
Floating-point
Contains multiple
decimals
–1
Integer
–1.0
Floating-point
38
Chapter 2
Strings
A string is any number of characters
enclosed within a pair of either single (')
or double (") quotation marks. Strings can
contain any combination of characters
that exist: letters, numbers, symbols, and
spaces. Strings can also contain variables.
Here are examples of valid string values:
"Hello, world!"
"Hello, $first_name!"
"1/3"
'Hello, world! How are you today?'
"08.02.06"
"1996"
''
That last example is an empty string—a
string that contains no characters.
To create a string, just wrap 0 or more
characters within quotation marks. There
are cases, however, where you may run
into problems. For example:
"I said, "How are you?""
This string will be tricky. Chapter 1, “Getting
Started with PHP,” hinted at the same problem with respect to printing HTML code.
When PHP hits the second quotation mark
in the example, it assumes the string ends
there; the continuing text (How…) causes
an error. To use a quotation mark within a
string you escape the quotation mark by
putting a backslash (\) before it:
The backslash tells PHP to treat each
escaped quotation mark as part of the
value of the string, rather than using it as
the string’s opening or closing indicators.
You can similarly circumvent this problem
by using different quotation mark types:
'I said, "How are you?"'
"I said, 'How are you?'"
Notice that “1996” converts an integer
into a string, simply by placing the number
within quotes. Essentially, the string contains
the characters 1996, whereas the number (a
nonquoted value) would be equal to 1996. It’s
a fine distinction, and one that won’t matter
in your code, because PHP lets you perform
mathematical calculations with the string 1996
just as you can with the number.
Chapter 1 also demonstrated how to
create a new line by printing the \n character within double quotation marks. Although
escaping a quotation mark prints the quotation mark, escaping an n prints a new line,
escaping an r creates a carriage return, and
escaping a t creates a tab.
Understanding strings, variables, and the
single and double quotation marks is critical
to programming with PHP. For this reason, a
section at the end of this chapter is dedicated
to the subject.
"I said, \"How are you?\""
Variables
39
Arrays
Arrays are covered more thoroughly in
Chapter 7, but let’s look at them briefly
here. Whereas a string or a number contains a single value (both are said to be
scalar), an array can have more than one
value assigned to it. You can think of an
array as a list or table of values: You can
put multiple strings and/or numbers into
one array.
Arrays use keys to create and retrieve the
values they store. The resulting structure—
a list of key-value pairs—is similar to a
two-column spreadsheet. Unlike arrays in
other programming languages, the array
structure in PHP is so flexible that it can use
either numbers or strings for both the keys
and the values. The array doesn’t even need
to be consistent in this respect. (All of this
will make more sense in Chapter 7, when
you start working with specific examples.)
PHP supports two kinds of arrays, based
on the format of the keys. If the array uses
numbers for the keys (Table 2.5), it’s known
as an indexed array. If it uses strings for
the keys (Table 2.6), it’s an associative
array. In either case, the values in the array
can be of any variable type (string, number,
and so on).
The array’s key is also referred to as
its index. You’ll see these two terms used
interchangeably.
An array can, and frequently will, contain
other arrays, creating what is called a multidimensional array.
What PHP refers to as an associative
array is known as a hash in Perl and Ruby,
among other languages.
40
Chapter 2
TABLE 2.5 Indexed Array
Key
Value
0
Dev
1
Rachel
2
Denise
3
Arnold
TABLE 2.6 Associative Array
Key
Value
VT
Vermont
NH
New Hampshire
IA
Iowa
PA
Pennsylvania
Variable Values
A The result of printing the values
of two variables.
To assign a value to a variable, regardless
of the variable type, you use the equals
sign (=). Therefore, the equals sign is known
as the assignment operator, because it
assigns the value on the right to the variable
on the left. For example:
$number = 1;
$floating_number = 1.2;
$string = "Hello, world!";
B Using the print statement on a complex
variable type, such as an array, will not have the
results you desire.
Each of these lines represents a complete
statement (that is, an executable action),
so each concludes with a semicolon.
To print the value of a variable, use the
print function:
print $number;
print $string;
If you want to print a variable’s value within
a context, you can place the variable’s
name in the printed string, as long as you
use double quotation marks A:
print "Number is $number";
print "String is $string";
Using print in this way works for the scalar (single-valued) variable types—numbers
and strings. For complex variable types—
arrays and objects—you cannot just use
print B:
print "_SERVER is $_SERVER";
As you’ve already seen, print_r() can
handle these nonscalar types, and you’ll
learn other approaches later in the book.
Whether you’re dealing with scalar or nonscalar variables, don’t forget that printing
out their values is an excellent debugging
technique when you’re having problems
with a script.
Variables 41
Because variable types aren’t locked in
(PHP is referred to as a weakly typed language), they can be changed on the fly:
$variable = 1;
$variable = "Greetings";
If you were to print the value of $variable
now, the result would be Greetings. The
following section better demonstrates the
concept of assigning values to variables
and then accessing those values.
To assign values to and
access variables:
1. Create a new PHP script in your
text editor or IDE, to be named
variables.php (Script 2.3).
2. Create the initial HTML tags:
Variables
3. Begin the PHP code:
Variables
The address is: $street
$city $state $zip";
?>
Remember that each statement must
conclude with a semicolon and that the
variable names are case-sensitive.
5. Print out the values of the variables
within some context:
C Some variables are assigned values, and then
printed within a context.
D Parse errors are the most common type of PHP
error, as you’ll discover. They’re frequently caused
by missing semicolons or mismatched quotation
marks or parentheses.
print "
The address is:
➝ $street $city $state
➝ $zip
";
Here a single print statement references all the variables. The entire string
to be printed (consisting of text, HTML
tags, and variables) is enclosed within
double quotation marks. The HTML
tags make the text flow over multiple lines in the browser.
6. Complete the PHP section and the
HTML page:
?>
E The Undefined variable error indicates that
you used a variable with no value (it hasn’t been
defined). This can happen with misspellings and
capitalization inconsistencies.
7. Save the file as variables.php, upload
it to your server (or save it to the appropriate directory on your computer), and
test it in your browser C.
If you see a parse error D when you
run this script, you probably either omitted
a semicolon or have an imbalance in your
quotation marks. In such particular cases, the
mistake itself is likely on the previous line of
code (than reported in the error message) but
wasn’t caught by PHP until the next line.
If one of the variable’s values isn’t
printed out or you see an Undefined variable
error E, you most likely failed to spell a
variable name the same way twice.
If you see a blank page, you most likely
have an error but PHP’s display_errors
configuration is set to off. See Chapter 3,
“HTML Forms and PHP,” for details.
Variables
43
Understanding
Quotation Marks
Now that you know the basics of variables
and how to create them, let’s do an exercise to make sure you completely understand how to properly use quotation marks.
PHP, like most programming languages,
allows you to use both double (") and
single (') quotation marks—but they give
vastly different results. It’s critical that you
comprehend the distinction, so the next
example will run tests using both types just
to emphasize the different behaviors.
The rule to remember is: Items within
single quotation marks are treated literally;
items within double quotation marks
are extrapolated. This means that within
double quotation marks, a variable’s name
is replaced with its value, as in Script 2.3,
but the same is not true for single quotation marks.
This rule applies anywhere in PHP you
might use quotation marks, including
uses of the print function and the assignment of values to string variables. An
example is the best way to demonstrate
this critical concept.
44
Chapter 2
Script 2.4 This script simply demonstrates how
the type of quotation mark you use with variables
affects the result.
1
2
3
4
5
6
7
8
9
10
Quotes
Double Quotes
name1 is $name1
name2 is $name2
";
print '
Single Quotes
name1 is $name1
name2 is $name2
';
?>
To use quotation marks:
1. Begin a new PHP script in your text
editor or IDE, to be named quotes.php
(Script 2.4).
2. Create the initial HTML tags:
Quotes
3. Begin the PHP code:
Double Quotes
name1 is $name1
name2 is $name2
";
print '
Single Quotes
name1 is $name1
name2 is $name2
';
Again, the quotation marks make all the
difference here. The first print statement, using double quotation marks,
prints out the values of the $name1 and
$name2 variables, whereas the second,
using single quotation marks, prints out
$name1 and $name2 literally.
The HTML in the print statements
makes them more legible in the
browser. Each statement is executed
over three lines of PHP code for additional readability, which is perfectly
acceptable.
46
Chapter 2
7. Complete the PHP section and the
HTML page:
?>
8. Save the file as quotes.php, upload it
to your server (or save it to the appropriate directory on your computer), and
test it in your browser A.
A The different quotation marks (single
versus double) dictate whether the
variable’s name or value is printed.
If you’re still confused about the distinction between the two types of quotation marks,
always stick with double quotation marks and
you’ll be safer.
Arguably, using single quotation marks
when you can is marginally preferable, because
PHP won’t need to search the strings looking
for variables, resulting in better performance.
But, at best, this is a minor optimization.
The shortcuts for creating newlines (\n),
carriage returns (\r), and tabs (\t) must be
used within double quotation marks to have
the desired effect. Within single quotes, each
of those is treated literally.
Remember that you don’t always need to
use quotation marks at all. When assigning a
numeric value or when only printing a variable,
you can omit them:
$num = 2;
print $num;
Variables 47
Review and Pursue
If you have any problems with the review
questions or the pursue prompts, turn
to the book’s supporting forum
(www.LarryUllman.com/forums/).
Review
n
n
n
n
n
n
n
n
What kind of variable is $_SERVER an
example of?
What character must all variables
begin with?
What characters can be used in a variable’s name (after the required initial
character)? What other characters can
be used in a variable’s name, after the
first character?
Are variable names case-sensitive or
case-insensitive?
What does it mean to say that a variable
is scalar? What are examples of scalar
variable types? What is an example of
a nonscalar variable type?
What is the assignment operator?
What great debugging technique—with
respect to variables—was introduced
in this chapter?
What is the difference between using
single and double quotation marks?
Pursue
n
n
Create another PHP script that defines
some variables and prints their values.
Try using variables of different scalar
types.
Create a PHP script that prints the value
of some variables within some HTML.
More sophisticated practice might
involve using PHP and variables to
create a link or image tag.
48 Chapter 2
3
HTML Forms
and PHP
The previous chapter provided a brief
introduction to the topic of variables.
Although you’ll commonly create your
own variables, you’ll also frequently use
variables in conjunction with HTML forms.
Forms are a fundamental unit of websites,
enabling such features as registration
and login systems, search capability, and
online shopping. Even the simplest site
will find logical reasons to incorporate
HTML forms. And with PHP, it’s stunningly
simple to receive and handle data generated by them.
With that in mind, this chapter will cover
the basics of creating HTML forms and
explain how the submitted form data is
available to a PHP script. This chapter will
also introduce several key concepts of real
PHP programming, including how to manage errors in your scripts.
In This Chapter
Creating a Simple Form
50
Choosing a Form Method
54
Receiving Form Data in PHP
58
Displaying Errors
63
Error Reporting
65
Manually Sending Data to a Page
68
Review and Pursue
73
Creating a
Simple Form
For the HTML form example in this chapter,
you’ll create a feedback page that takes
the user’s salutation (or title), name, email
address, response, and comments A. The
code that generates a form goes between
opening and closing form tags:
The form tags dictate where a form begins
and ends. Every element of the form must
be entered between these two tags. The
opening form tag should also contain an
action attribute. It indicates the page to
which the form data should be submitted.
This value is one of the most important
considerations when you’re creating a form.
In this book, the action attributes will
always point to PHP scripts:
";
?>
3. Save the file, place it in the same
directory as posting.html (on your
PHP-enabled server), and test again
in your browser C.
Newlines can also be inserted into
strings by placing the newline character—\n—
between double quotation marks.
C Now the same submitted data A is properly
displayed over multiple lines in the browser.
Other HTML tags, such as paragraph
tags, also affect spacing in the rendered web
page. You can turn newlines (or any character)
into paragraph tags using a replacing function,
but the code for doing so is far more involved
than just invoking nl2br().
Newlines present in strings sent to the
browser will have an effect, but only in the
HTML source of the page D.
D The HTML source, corresponding to B, shows
the effect that newlines have in the browser (i.e.,
they add spacing within the HTML source code).
Using Strings
103
HTML and PHP
As stated several times over by now, PHP
is a server-side technology that’s frequently used to send data to the browser.
This data can be in the form of plain text,
HTML code, or, more commonly, both.
In this chapter’s primary example, data is
entered in an HTML form and then printed
back to the browser using PHP. A potential
problem is that the user can enter HTML
characters in the form, which can affect
the resulting page’s formatting A B—or,
worse, cause security problems.
You can use a few PHP functions to
manipulate HTML tags within PHP string
variables:
n
n
n
htmlspecialchars() converts certain
HTML tags into their entity versions.
A If the user enters HTML code in the posting…
htmlentities() turns all HTML tags
into their entity versions.
strip_tags() removes all HTML and
PHP tags.
The first two functions turn an HTML tag
(for example, ) into an entity version like <span>. The entity version
appears in the output but isn’t rendered.
You might use either of these if you wanted
to display code without enacting it. The
third function, strip_tags(), removes
HTML and PHP tags entirely.
B …it’s rendered by the browser when reprinted.
104
Chapter 5
C Displaying HTML submitted by a user in a
browser can have terrible consequences, such as
the execution of JavaScript.
You ought to watch for special tags in
user-provided data for two reasons. First,
as already mentioned, submitted HTML
would likely affect the rendered page
(for example, mess up a table, tweak the
CSS, or just add formatting where there
shouldn’t be any). The second concern
is more important. Because JavaScript is
placed within HTML script tags, a malicious
user could submit JavaScript that would
be executed when it’s redisplayed on the
page C. This is how cross-site scripting
(XSS) attacks are performed.
To see the impact these functions have,
this next rewrite of handle_post.php will
use each of them and display the respective results.
Using Strings 105
To address HTML in PHP:
1. Open handle_post.php (Script 5.3)
in your text editor or IDE, if it is not
already open.
2. Before the print line, add the following
(Script 5.4):
$html_post = htmlentities
➝ ($_POST['posting']);
$strip_post = strip_tags
➝ ($_POST['posting']);
To clarify the difference between how
these two functions work, apply them
both to the posting text, creating two
new variables in the process. Refer
to $_POST['posting'] here and not
$posting because $posting already
reflects the application of the nl2br()
function, which means that break tags
may have been introduced that were
not explicitly entered by the user.
3. Alter the print statement to read
as follows:
print "
Thank you, $name,
➝ for your posting:
Original: $posting
Entity: $html_post
Stripped: $strip_post
➝
";
To highlight the different results, print
out the three different versions of the
posting text. First is the original posting
as it was entered, after being run through
nl2br(). Next is the htmlentities()
version of the posting, which will show
the HTML tags without rendering them.
Finally, the strip_tags() version will
be printed; it doesn’t include any HTML
(or PHP) tags.
106
Chapter 5
Script 5.4 This version of the PHP script addresses
HTML tags in two different ways.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Forum Posting
Thank you, $name, for
your posting:
Original: $posting
Entity: $html_post
Stripped: $strip_post
";
?>
4. Save the file, place it in the same
directory as posting.html (on your
PHP-enabled server), and test it again
in your browser D E.
If you view the HTML source code of
the resulting PHP page F, you’ll also
see the effect that applying these functions has.
For security purposes, it’s almost
always a good idea to use htmlentities(),
htmlspecialchars(), or strip_tags() to
any user-provided data that’s being printed
to the browser. The only reason I don’t do so
in this book is to minimize clutter.
Today’s browsers can identify and block
execution of potentially malicious JavaScript,
although you should not rely on that behavior.
D The HTML characters entered as part of a
posting will now be addressed by PHP.
The html_entity_decode() function
does just the opposite of htmlentities(),
turning HTML entities into their respective
HTML code.
Another useful function for outputting
strings in the browser is wordwrap(). This
function wraps a string to a certain number
of characters.
E The resulting PHP page shows the original post
as it would look if printed without modification,
the effect of htmlentities(), and the effect of
strip_tags().
To turn newlines into breaks while
still removing any HTML or PHP tags, apply
nl2br() after strip_tags():
$posting = nl2br(strip_tags
➝ ($_POST['posting']));
In that line, the strip_tags() function will
be called first, and its result will be sent to
the nl2br() function.
F The HTML source for the content displayed in E.
Using Strings
107
Encoding and
Decoding Strings
At the end of Chapter 3, the section
“Manually Sending Data to a Page” demonstrated how to use the thinking behind the
GET form method to send data to a page.
In that example, instead of using an actual
form, data was appended to the URL, making it available to the receiving script. I was
careful to say that only single words could
be passed this way, without spaces or
punctuation. But what if you want to pass
several words as one variable value or use
special characters?
To safely pass any value to a PHP script
through the URL, apply the urlencode()
function. As its name implies, this function
takes a string and encodes it (changes its
format) so that it can properly be passed
as part of a URL. Among other things, the
function replaces spaces with plus signs
(+) and translates special characters (for
example, the apostrophe) into less problematic versions. You can use the function
like so:
$string = urlencode($string);
To demonstrate one application of
urlencode(), let’s update the handle_
post.php page so that it also creates a
link that passes the user’s name and email
address to a third page.
108
Chapter 5
Script 5.5 This script encodes two variables
before adding them to a link. Then the values can
be successfully passed to another page.
1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Forum Posting
Thank you, $name, for your
posting:
$posting
";
// Make a link to another page:
$name = urlencode($name);
$email = urlencode($_POST['email']);
print "
";
To use urlencode():
1. Open handle_post.php (Script 5.4)
in your text editor or IDE, if it is not
already open.
2. Delete the htmlentities() and
strip_tags() lines added in the previous set of steps (Script 5.5).
3. Revert to the older version of the
print invocation:
print "
Thank you, $name,
➝ for your posting:
$posting
";
4. After the print statement, add the
following:
$name = urlencode($name);
$email = urlencode($_POST
➝ ['email']);
This script will pass these two variables
to a second page. In order for it to do
so, they must both be encoded.
Because the script has not previously
referred to or used the $email variable, the second line both retrieves the
email value from the $_POST array and
encodes it in one step. This is the same
as having these two separate lines:
$email = $_POST['email'];
$email = urlencode($email);
continues on next page
?>
Using Strings 109
5. Add another print statement that
creates the link:
print "
";
The primary purpose of this print
statement is to create an HTML link
in the web page, the source code of
which would be something like
here
To accomplish this, begin by hard-coding
most of the HTML and then include the
appropriate variable names. Because
the HTML code requires that the URL
for the link be in double quotation marks
—and the print statement already
uses double quotation marks—you
must escape them (by preceding them
with backslashes) in order for them to
be printed.
6. Save the file, place it in the proper
directory of your PHP-enabled server,
and test it again in your browser A B.
Note that clicking the link will result in
a server error, because the thanks.php
script hasn’t yet been written.
110
Chapter 5
A Another use of the form.
B The handling script now displays a link to
another page.
7. View the HTML source code of the
handling page to see the resulting link
in the HTML code C.
Values sent directly from a form are automatically URL-encoded prior to being sent and
decoded upon arrival at the receiving script.
You only need the urlencode() function to
manually encode data (as in the example).
The urldecode() function does just
the opposite of urlencode()—it takes an
encoded URL and turns it back into a standard
form. You’ll use it less frequently, though,
because PHP will automatically decode most
values it receives.
Since you can use concatenation with
functions, the new print statement could be
written as follows:
print 'Click here to continue.';
This method has two added benefits over the
original approach. First, it uses single quotation marks to start and stop the statement,
meaning you don’t need to escape the double
quotation marks. Second, the variables used
are more obvious—they aren’t buried in a lot of
other code.
C The HTML source code of the page B shows the dynamically generated link.
Using Strings
111
You do not need to encode numeric
PHP values in order to use them in a URL,
because they do not contain problematic
characters. That being said, it won’t hurt to
encode them either.
At the end of the chapter you’ll be
prompted to create thanks.php, which greets
the user by name and email address D.
D The third page in this process—to be created by you at the end of the chapter—prints a message based
on values it receives in the URL.
Encrypting and Decrypting Strings
Frequently, in order to protect data, programmers encrypt it—alter its state by transforming it to a
form that’s more difficult, if not impossible, to discern. Passwords are an example of a value you
might want to encrypt. Depending on the level of security you want to establish, usernames, email
addresses, and phone numbers are likely candidates for encryption too.
You can use the password_hash() function to encrypt data, but be aware that no decryption
option is available (it’s known as one-way encryption). So a password may be encrypted using
it and then stored, but the decrypted value of the password can never be determined. Using
this function in a web application, you might encrypt a user’s password upon registration; then,
when the user logged in, the password the user entered at that time would also be encrypted,
and the two protected versions of the password would be compared. The syntax for using
password_hash() is
$data = password_hash($data, PASSWORD_DEFAULT);
The second argument says to use the default encryption algorithm (the algorithm determining how
quickly and securely the encryption is performed).
If the data is being stored in a database, you can also use functions built into the database application (for example, MySQL, PostgreSQL, Oracle, or SQL Server) to perform encryption and decryption. Depending on the technology you’re using, it most likely provides both one- and two-way
encryption tools.
112
Chapter 5
Comparing Strings
To compare two strings, you can always
use the equality operator, which you’ll
learn about in the next chapter. Otherwise, you can use the strcmp() function.
It indicates how two strings compare
by returning a whole number: 0 if they
are the same, and a positive or negative
number if one is “greater” than the other.
PHP also has a case-insensitive companion, strcasecmp().
To see if a substring is contained within
another string (that is, to find a needle in
a haystack), you’ll use these functions:
.. strstr() returns the haystack from
the first occurrence of a needle to the
end.
.. strpos() searches through a haystack and returns the numeric location of a particular needle.
Both of these functions also have a caseinsensitive alternative: stristr() and
stripos(), respectively. Each of these
functions is normally used in a conditional
to test whether the substring was found.
Finding Substrings
PHP has a few functions you can use to
pull apart strings, search through them,
and perform comparisons. Although these
functions are normally used with conditionals, discussed in Chapter 6, “Control
Structures,” they are important enough that
they’ll be introduced here; later chapters
will use them more formally.
Earlier in this chapter, you learned how
to join strings using concatenation. Along
with making larger strings out of smaller
pieces, PHP easily lets you extract subsections from a string. The trick to using any
method to pull out a subsection of a string
is that you must know something about the
string itself in order to know how to break
it up.
The strtok() function creates a substring,
referred to as a token, from a larger string
by using a predetermined separator (such
as a comma or a space). For example, if
you have users enter their full name in one
field (presumably with their first and last
names separated by a space), you can pull
out their first name with this code:
$first = strtok($_POST['name'], ' ');
That line tells PHP to extract everything
from the beginning of $_POST['name']
until it finds a blank space.
If you have users enter their full name in
the format Surname, First, you can find
their surname by writing
$last = strtok($_POST['name'], ', ');
Using Strings
113
A second way to pull out sections of a
string is by referring to the indexed position
of the characters within the string. The
indexed position of a string is the numerical location of a character, counting from
the beginning. However, PHP—like most
programming languages—begins all indexes
with the number 0. For example, to index
the string Larry, you begin with the L at
position 0, followed by a at 1, r at 2, the
second r at 3, and y at 4. Even though the
string length of Larry is 5, its index goes
from 0 to 4. In short, indexes always go
from 0 to the length minus 1.
With this in mind, you can call on the
substr() function to create a substring
based on the index position of the substring’s characters:
$sub = substr($string, 0, 10);
The first argument is the master string from
which the substring will be derived. Second,
indicate where the substring begins, as its
indexed position (0 means that you want
to start with the first character). Third, from
that starting point, state how many characters the substring should contain (10). If
the master string does not have that many
characters in it, the resulting substring
will end with the end of the master string.
This argument is optional; if omitted, the
substring will also go until the end of the
master string.
You can also use negative numbers to
count backward from the end of the string:
$string = 'aardvark';
$sub = substr($string, -3, 3); // ark
114
Chapter 5
Script 5.6 This version of handle_post.php
counts the number of words in the posting and
trims the displayed posting down to just the first
50 characters.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Forum Posting
Thank you, $name, for
your posting:
$posting...
($words words)
";
?>
The second line says that three characters
should be returned starting at the third
character from the end. With that particular
example, you can again omit the third
argument and have the same result:
$sub = substr($string, -3); // ark
To see how many characters are in a string,
use strlen():
print strlen('Hello, world!'); // 13
The count will include spaces and punctuation. To see how many words are in a
string, use str_word_count(). This function, along with substr(), will be used in
this next revision of the handle_post.php
script.
To create substrings:
1. Open handle_post.php (Script 5.5)
in your text editor or IDE, if it is not
already open.
2. Before the print statement, add the
following (Script 5.6):
$words = str_word_count
➝ ($posting);
This version of the script will do two
new things with the user’s posting.
One will be to display the number of
words it contains. That information is
gathered here and assigned to the
$words variable.
continues on next page
Using Strings
115
3. On the next line (also before the print
statement), add
$posting = substr($posting, 0,
➝ 50);
The second new thing this script will do
is limit the displayed posting to its first
50 characters. You might use this, for
example, if one page shows the beginning of a post, then a link takes the user
to the full posting. To implement this
limit, the substr() function is called.
4. Update the print statement to read
print "
Thank you, $name,
➝ for your posting:
$posting...
($words words)
";
There are two changes here. First,
ellipses are added after the posting to
indicate that this is just part of the whole
posting. Then, within another paragraph, the number of words is printed.
A Postings longer than 50 characters…
5. Delete the two urlencode() lines and
the corresponding print line.
I’m referring specifically to the code
added in the previous incarnation of
the script, linking to thanks.php.
6. Save the file, place it in the proper
directory of your PHP-enabled server,
and test it again in your browser A B.
If you want to check whether a string
matches a certain format—for example, to
see if it’s a syntactically valid postal code—
you need to use regular expressions. Regular
expressions are an advanced concept in
which you define patterns and then see if a
value fits the mold. See the PHP manual or
my book PHP and MySQL for Dynamic Web
Sites (Fourth Edition): Visual QuickPro Guide
(Peachpit Press, 2012).
116
Chapter 5
B …will be cut short. The word count is also
displayed.
Adjusting String Case
A handful of PHP functions are used to
change the case of a string’s letters:
Replacing Parts
of a String
.. ucwords() capitalizes the first letter
of words in a string.
Instead of just finding substrings within a
string, as the previous section discusses,
you might find that you need to replace
substrings with new values. You can do
so using the str_ireplace() function:
.. strtoupper() makes an entire string
uppercase.
$string = str_ireplace($needle,
➝ $replacement, $haystack);
.. ucfirst() capitalizes the first letter
of the string.
.. strtolower() makes an entire string
lowercase.
Due to the variance in people’s names
around the globe, there’s no flawless
way to automatically format names with
PHP (or any programming language). In
fact, I would be hesitant to alter the case
of user-supplied data unless you have
good cause to do so.
This function replaces every occurrence
of $needle found in $haystack with
$replacement. For example:
$me = 'Larry E. Ullman';
$me = str_ireplace('E.', 'Edward',
➝ $me);
The $me variable now has a value of Larry
Edward Ullman.
That function performs a case-insensitive
search. To be more restrictive, you can
perform a case-sensitive search using
str_replace(). In this next script,
str_ireplace() will be used to eliminate
“bad words” in submitted text.
There’s one last string-related function
I want to discuss: trim(). This function
removes any white space—spaces, newlines, and tabs—from the beginning and
end of a string. It’s quite common for extra
spaces to be added to a string variable,
either because a user enters information
carelessly or due to sloppy HTML code.
For purposes of clarity, data integrity, and
web design, it’s worth your while to delete
those spaces from the strings before you
use them. Extra spaces sent to the browser
could make the page appear odd, and
those sent to a database or cookie could
have unfortunate consequences at a
later date (for example, if a password has
a superfluous space, it might not match
when it’s entered without the space).
Using Strings 117
The trim() function automatically strips
away any extra spaces from both the
beginning and the end of a string (but not
the middle). The format for using trim() is
as follows:
Script 5.7 This final version of the handling script
applies the trim() function and then replaces
uses of badword with a bunch of Xs.
$string = ' extra space before and
➝ after text ';
$string = trim($string);
// $string is now equal to 'extra
➝ space before and after text'
1
2
3
4
5
6
7
8
9
To use str_ireplace () and trim():
10
1. Open handle_post.php (Script 5.6)
in your text editor or IDE, if it is not
already open.
11
12
2. Apply trim() to the form data
(Script 5.7):
$first_name = trim($_POST
➝ ['first_name']);
$last_name = trim($_POST
➝ ['last_name']);
$posting = trim($_POST
➝ ['posting']);
Just in case the incoming data has
extraneous white space at its beginning
or end, the trim() function is applied.
3. Remove the use of substr():
$posting = substr($posting,
➝ 0, 50);
You’ll want to see the entire posting for
this example, so remove this invocation
of substr().
4. Before the print statement, add
$posting = str_ireplace
➝ ('badword', 'XXXXX', $posting);
This specific example flags the use of
a bad word in a posting by crossing it
out. Rather than an actual curse word,
the code uses badword. (You can use
whatever you want, of course.)
118
Chapter 5
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Forum Posting
Thank you, $name, for your
posting:
$posting
($words words)
";
?>
If you’d like to catch many bad words,
you can use multiple lines, like so:
$posting = str_ireplace
➝ ('badword1', 'XXXXX', $posting);
$posting = str_ireplace
➝ ('badword2', 'XXXXX', $posting);
$posting = str_ireplace
➝ ('badword3', 'XXXXX', $posting);
5. Update the print statement so that it
no longer uses the ellipses:
print "
Thank you, $name,
➝ for your posting:
$posting
($words words)
";
6. Save the file, place it in the proper
directory of your PHP-enabled server,
and test again in your browser A B.
A If users enter a word you’d prefer they not use…
The str_ireplace() function will
even catch bad words in context. For example,
if you entered I feel like using badwords, the
result would be I feel like using XXXXXs.
The str_ireplace() function can
also take an array of needle terms, an array
of replacement terms, and even an array as
the haystack. Because you may not know
what an array is yet, this technique isn’t
demonstrated here.
B …you can have PHP replace it.
If you need to trim excess spaces from
the beginning or the end of a string but not
both, PHP breaks the trim() function into
two more specific functions: rtrim() removes
spaces found at the end of a string variable
(on its right side), and ltrim() handles those
at the beginning (its left). They’re both used
just like trim():
$string = rtrim($string);
$string = ltrim($string);
Using Strings
119
Review and Pursue
If you have any problems with the
review questions or the pursue prompts,
turn to the book’s supporting forum
(www.LarryUllman.com/forums/).
Review
n
n
n
n
n
n
n
n
n
120
Pursue
n
n
How do you create a string?
What are the differences between using
single and double quotation marks?
What is the concatenation operator?
What is the concatenation assignment
operator?
What is the impact of having a newline
in a string printed to the browser? How
do you convert a newline character to
a break tag?
What problems can occur when HTML
is entered into form elements whose
values will later be printed back to the
browser? What steps can be taken to
sanctify submitted form data?
What function makes data safe to pass
in a URL?
How do you escape problematic characters within a string? What happens if
you do not escape them?
The characters in a string are indexed
beginning at what number?
What does the trim() function do?
Chapter 5
n
n
n
Look up the PHP manual page for one
of the new functions mentioned in this
chapter. Use the links on that page to
examine a couple of other string-related
functions that PHP has.
Check out the PHP manual page
specifically for the substr() function.
Read the other examples found on
that page to get a better sense of how
substr() can be used.
Write the thanks.php script that goes
along with Script 5.5. If you need help,
revisit the hello.php script from
Chapter 3 (Script 3.7).
Rewrite the print statement in the final
version of handle_post.php (Script 5.7)
so that it uses single quotation marks
and concatenation instead of double
quotation marks.
Create another HTML form for taking
string values. Then create the PHP
script that receives the form data,
addresses any HTML or PHP code,
manipulates the data in some way,
and prints out the results.
6
Control
Structures
Control structures—conditionals and
loops—are a staple of programming languages. PHP has two conditionals—if and
switch—both of which you’ll master in this
chapter. Conditionals allow you to establish a test and then perform actions based
on the results. This functionality provides
the ability to make websites even more
dynamic.
The discussion of if conditionals requires
introduction of two last categories of
operators: comparison and logical (you’ve
already seen the arithmetic and assignment operators in the previous chapters).
You’ll commonly use these operators in
your conditionals, along with the Boolean
concepts of TRUE and FALSE.
Finally, this chapter introduces loops,
which allow you to repeat an action for a
specified number of iterations. Loops can
save you programming time and help you
get the most functionality out of arrays, as
you’ll see in the next chapter.
In This Chapter
Creating the HTML Form
122
The if Conditional
125
Validation Functions
128
Using else
132
More Operators
135
Using elseif
144
The Switch Conditional
148
The for Loop
152
Review and Pursue
157
Creating the
HTML Form
As with the previous chapters, the examples in this chapter are based on an HTML
form that sends data to a PHP page. In this
case, the form is a simple registration page
that requests the following information A:
n
Email address
n
Password
n
Confirmation of the password
n
Year of birth (to verify age)
n
n
Favorite color (for customization
purposes)
Agreement to the site’s terms
(a common requirement)
The following steps walk through the creation of this form before getting into
the PHP code.
To create the HTML form:
1. Begin a new HTML document in
your text editor or IDE, to be named
register.html (Script 6.1):
Registration Form
Please complete this
➝ form to register:
2. Create the initial form tag:
A The HTML form used in this chapter.
Script 6.1 This pseudo-registration form is the
basis for the examples in this chapter.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Registration Form
Please complete this form to
register:
Email
Address:
Password:
<p>Confirm Password:
18
code continues on next page
122
Chapter 6
Script 6.1 continued
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<p>Year You Were Born:
<p>Favorite Color:
<p> I agree to
the terms (whatever they may be).
<input type="submit" name="submit"
value="Register">
B A password input type as it’s being filled out.
As with many of the previous examples,
this page uses the POST method. The
handling script, identified by the action
attribute, will be handle_reg.php,
found in the same directory as the
HTML form.
3. Create inputs for the email address and
passwords:
Email Address:
Password:
Confirm Password:
These lines should be self-evident by
now. Each line is wrapped in HTML
tags to improve the spacing in
the browser. Also, note that two password inputs are created—the second
is used to confirm the text entered in
the first. Password input types don’t
reveal what the user enters B, so the
standard is to require the user to enter
passwords twice (theoretically ensuring
that users know exactly what password
they provided).
4. Create an input for the user’s birth year:
Year You Were Born:
Rather than use a drop-down menu that
displays 50 or 100 years, have users
enter their birth year in a text box. By
presetting the placeholder attribute of
the input, you make the text box indicate
the proper format for the year A.
continues on next page
Control Structures
123
5. Create a drop-down menu for the user’s
favorite color:
Favorite Color:
The truth is that I’m adding this input so
that it can be used for a specific example later in the chapter, but it might be
used to customize the look of the site
after the user logs in. Naturally, you can
add as many colors as you want here.
6. Create a checkbox for the user to agree
to the site’s terms:
➝ I agree to the terms (whatever
➝ they may be).
Many sites have some sort of terms or
licensing that the user must indicate
acceptance of, normally by selecting a
checkbox. This particular form doesn’t
have a link to where the user can read
the terms, but it probably doesn’t matter
because no one reads them (and this is
just a hypothetical example anyway). In
any case, using this element, you’ll be
able to see how checkboxes are treated
by the handling PHP script.
124
Chapter 6
7. Add a submit button and close the form:
8. Complete the HTML page:
9. Save the file as register.html, place it
in the proper directory for your PHPenabled server, and load the page in
your browser.
It’s becoming more common to not require
a password confirmation, relying instead on
password reset functionality should users
make a mistake or forget what they entered.
I definitely prefer not having to confirm the
password (and I used a password management
application regardless), but you will see both
approaches online.
Most registration pages use either a nickname or an email address for the username.
If you use the email address as a username,
it’s easier for your users to remember their
registration information (a user may have only
a couple of email addresses but a gazillion
usernames for different sites around the web).
Furthermore, email addresses are, by their
nature, unique to an individual, whereas usernames are not.
The if Conditional
The basic programming conditional is the
standard if (what used to be called an
if-then conditional—the then is now
implied). The syntax for this kind of conditional is simple:
if (condition) {
statement(s);
}
The condition must go within parentheses;
then the statement(s) are placed within
braces (you’ll also see these referred to as
“curly braces” or “curly brackets”). The statements are commands to be executed—for
example, printing a string or adding two
numbers together. Each separate statement
must have its own semicolon indicating the
end of the line, but there’s no limit on the
number of statements that can be associated with a conditional.
The statements are normally indented from
the initial if line to indicate that they’re
the result of a conditional, but that format
isn’t syntactically required. You’ll also see
people use this syntax:
if (condition)
{
statement(s);
}
How you arrange your braces is a matter
of personal preference—and the source of
minor online skirmishes. Just pick a style
you like and stick to it.
Failure to use a semicolon after each statement, forgetting an opening or closing
parenthesis or brace, or using a semicolon
after either of the braces will cause errors
to occur. Be mindful of your syntax as you
code with conditionals!
PHP uses the Boolean concepts of TRUE
and FALSE when determining whether to
execute the statements. If the condition is
TRUE, the statements are executed; if it’s
FALSE, they are not executed A.
A How an if conditional affects the program flow
of a script.
Control Structures
125
Over the course of this chapter, a PHP script
will be developed until it fully validates the
register.html form data. To start, this
first version of the script will just create the
basic shell of the validation process, defining and using a variable with a Boolean
value that will track the success of the
validation process.
To create an if conditional:
1. Begin a new document in your text
editor or IDE, to be named
handle_reg.php (Script 6.2):
Registration
Registration Results
2. Begin the PHP section and address
error management, if necessary:
Registration
Registration Results
You have been
successfully registered (but not
really).';
}
?>
The variable is initialized with a Boolean
value of TRUE, meaning that the assumption is that the form was completed
properly. Booleans are case-insensitive
in PHP, so you could also write True
or TRUE.
4. Print a message if everything is all right:
if ($okay) {
print '
You have been
➝ successfully registered (but
➝ not really).
';
}
Over the course of this chapter, validation routines will be added to this script,
checking the submitted form data. If any
data fails a routine, then $okay will be
set to FALSE. In that case, this conditional will also be FALSE, so the message
won’t be printed. However, if the data
passes every validation routine, then
$okay will still be TRUE, in which case
this message will be printed.
5. Complete the PHP section and the
HTML page:
?>
6. Save the file as handle_reg.php, place
it in the proper directory for your PHPenabled server (in the same directory as
register.html), and test both in your
browser B and C.
Of course, the fact is that this particular
script will always print the success
message, because no code will set
$okay to FALSE. You can even run the
script directly and see the same result.
If the statement area of your conditional
is only one line long, you technically don’t
need the braces. In that case, you can write
the conditional using either of these formats:
if (condition) statement;
or
if (condition)
statement;
You may run across code in these formats.
However, I think it’s best to always use the
multiline format, with the braces (as demonstrated in the syntax introduction) to improve
consistency and minimize errors.
B Filling out the HTML form to any degree…
C …results in just this.
Control Structures
127
Validation Functions
PHP has dozens of functions commonly
used to validate form data. Of these functions, three of the most important ones are
used in this chapter’s examples.
First up is the empty() function, which
checks to see if a given variable has an
“empty” value. A variable is considered to
have an empty value if the variable has no
value, has a value of 0, or has a value of
FALSE. In any of these cases, the function
returns TRUE; otherwise, it returns FALSE:
$var1 = 0;
$var2 = 'something';
$var3 = ' '; // An empty string
empty($var); // TRUE, no defined
➝ value
empty($var1); // TRUE, empty value
empty($var2); // FALSE, non-empty
➝ value
empty($var3); // TRUE, empty value
This function is perfect for making sure
that text boxes in forms have been filled
out. For example, if you have a text input
named email and the user doesn’t enter
anything in it before submitting the form,
then the $_POST['email'] variable will
exist but will have an empty value.
Next is the isset() function, which is
almost the opposite of empty(), albeit with
a slight difference. The isset() function
returns TRUE if a variable has any value
(including 0, FALSE, or an empty string).
If the variable does not have a value,
isset() returns FALSE:
$var1 = 0;
$var2 = 'something';
$var3 = ' '; // An empty string
isset($var); // FALSE, no defined
➝ value
isset($var1); // TRUE
isset($var2); // TRUE
isset($var3); // TRUE
The isset() function is commonly used to
validate nontext form elements like checkboxes, radio buttons, and select menus.
It’s also regularly used to confirm that a
variable exists, regardless of its value.
Finally, the is_numeric() function returns
TRUE if the submitted variable has a valid
numerical value and FALSE otherwise.
Integers, decimals, and even strings (if
they’re a valid number) can all pass the
is_numeric() test:
$var1 = 2309;
$var2 = '80.23';
$var3 = 'Bears';
is_numeric($var1); // TRUE
is_numeric($var2); // TRUE
is_numeric($var3); // FALSE
An interesting thing to note is that using
is_numeric() on a variable that doesn’t
exist not only returns FALSE, but also
generates a warning. For this reason, you’ll
often see isset() used along with other
validation functions like is_numeric().
Let’s start applying these functions to the
PHP script to perform data validation.
128
Chapter 6
Script 6.3 Using if conditionals and the empty()
function, this PHP script checks if email address
and password values were provided.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Registration
Registration Results
Please
enter your email address.';
$okay = false;
}
// Validate the password:
if (empty($_POST['password'])) {
print '
Please
enter your password.
';
$okay = false;
}
// If there were no errors, print a
success message:
if ($okay) {
print '
You have been successfully
registered (but not really).
';
}
?>
To validate form data:
1. Open handle_reg.php (Script 6.2) in
your text editor or IDE, if it is not already
open.
2. Within the document’s head, define a
CSS class (Script 6.3):
This CSS class will be used to format
any printed registration errors.
3. Validate the email address:
if (empty($_POST['email'])) {
print '
➝ Please enter your email
➝ address.
';
$okay = false;
}
This if conditional uses the code
empty($_POST['email']) as its condition. If that variable is empty, meaning
it has no value, a value of 0, or a value
of an empty string, the conditional is
TRUE. In that case, the print statement
will be executed and the $okay variable
will be assigned a value of FALSE (indicating that everything is not okay).
If the variable isn’t empty, then the
conditional is FALSE, the print function
is never called, and $okay will retain its
original value.
continues on next page
Control Structures
129
4. Repeat the validation for the password:
if (empty($_POST['password'])) {
print '
Please
➝ enter your password.
';
$okay = false;
}
This is a repeat of the email validation,
but with the variable name and print
statement changed accordingly. The
other form inputs will be validated in time.
All the printed error messages are
placed within HTML paragraph tags that
have a class value of error. By doing
so, the CSS formatting will be applied
(i.e., the errors will be printed in red).
5. Save the file as handle_reg.php, place it
in the same directory as register.html
(on your PHP-enabled server), and test
both the form and the script in your
browser A and B.
A If you omit the email address or password
form input…
6. Resubmit the form in different states of
completeness to test the results more.
If you do provide both email address
and password values, the result will
be exactly like that in C in the section
“The if Conditional,” because the $okay
variable will still have a value of TRUE.
B …you’ll see messages like these.
130
Chapter 6
When you use functions within conditionals, as with empty() here, it’s easy to forget
a closing parenthesis and see a parse error.
Be extra careful with your syntax when you’re
coding any control structure.
One use of the isset() function is to
avoid referring to a variable unless it exists.
If PHP is set to report notices (see “Error
Reporting” in Chapter 3), then, for example,
using $var if it has not been defined will
cause an error. You can avoid this by coding
if (isset($var)) {
//
Do whatever with $var.
}
Even though almost all form data is sent
to a PHP script as strings, the is_numeric()
function can still be used for values coming
from a form because it can handle strings that
contain only numbers.
The isset() function can take any
number of variables as arguments:
if (isset($var1, $var2)) {
print
'Both variables exist.';
}
If all the named variables are set, the function
returns TRUE; if any variable is not set, the
function returns FALSE.
Once you’re more comfortable with PHP,
you’ll start using the filter() function for
validation, too. It’s a wonderful tool, but a bit
too complicated for beginners.
Control Structures
131
Using else
The next control structure to discuss is the
if-else conditional. This control structure
allows you to execute one or more statements when a condition is TRUE and
execute one or more other statements
when the condition is FALSE:
if (condition) {
statement(s);
} else {
other_statement(s);
}
The important thing to remember when
using this construct is that unless the
condition is explicitly met, the else statement will be executed. In other words, the
statements after the else constitute the
default action, whereas the statements
after the if condition are the exception to
the rule A.
Let’s rewrite the handle_reg.php page,
incorporating an if-else conditional to
validate the birth year. In the process, a
new variable will be created, representing
the user’s age.
To use else:
1. Open handle_reg.php (Script 6.3) in
your text editor or IDE, if it is not already
open.
2. After the password validation but
before the $okay conditional, begin a
new conditional (Script 6.4):
if (is_numeric($_POST['year'])) {
Because the year variable should be a
number, you can use the is_numeric()
function, rather than empty(), to check
its value. This is a basic start to this
particular form element’s validation;
later scripts will expand on this.
132
Chapter 6
A How an if-else conditional affects the
program flow of a script.
Script 6.4 By adding an if-else conditional, this
script validates the birth year and creates a new
variable in the process.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Registration
Registration Results
Please enter
your email address.';
$okay = false;
}
// Validate the password:
if (empty($_POST['password'])) {
print '
Please enter
your password.
';
$okay = false;
}
// Validate the birth year:
if (is_numeric($_POST['year'])) {
$age = 2016 - $_POST['year']; //
Calculate age this year.
} else {
print '
Please
enter the year you were born as
four digits.
';
$okay = false;
}
// If there were no errors, print a
success message:
if ($okay) {
print '
You have been successfully
registered (but not really).
';
print
"
You will turn $age this
year.
";
}
?>
3. Create a new variable:
$age = 2016 - $_POST['year'];
If the $_POST['year'] variable has a
numeric value (meaning that the conditional is TRUE), then the $age variable is
assigned the value of the current year
minus the provided year. For now, without knowledge of PHP’s date functions,
just hard-code the current year into the
equation.
4. Add an else clause:
} else {
print '
Please
➝ enter the year you were born
➝ as four digits.
';
$okay = false;
}
If the year does not have a numeric
value, an error message is printed and
the $okay variable is set to FALSE (as is
the case if any validation routine fails).
5. After the final print statement but
within the same $okay conditional, also
print out the value of $age:
print "
You will turn $age this
➝ year.
";
If the $okay variable still has a value of
TRUE, then the submitted data passed
every validation routine. This means
that the user’s age has been calculated
(in the sense of how old that user will
be at some point this year), and it can
be printed, too.
continues on next page
Control Structures
133
6. Save your script, place it in the same
directory as register.html (on your
PHP-enabled server), and test it in your
browser again B, C, and D.
Another good validation function is
checkdate(), which you can use to confirm
that a date exists (or existed in the past).
You’d use it like so:
if (checkdate($month, $day, $year))
➝ {...
B Test the form again, without providing a year
value, and…
C …you’ll see this.
D If the user provides a numeric value for their
birth year, the user’s age will now be calculated
and printed (assuming that an email address and
password was also provided).
134
Chapter 6
More Operators
TABLE 6.1 PHP’s Operators
Previous chapters discussed most of
PHP’s operators along with the variable
types that use them. These operators
include arithmetic for numbers: addition (+),
subtraction (-), multiplication (*), and
division (/), along with the increment (++)
and decrement (--) shortcuts for increasing
or decreasing the value of a number by 1.
Then there is the assignment operator (=),
which is used to set the value of a variable,
regardless of type. You’ve also learned
about concatenation (.), which appends
one string to another.
Operator
Usage
Type
+
Addition
Arithmetic
-
Subtraction
Arithmetic
*
Multiplication
Arithmetic
/
Division
Arithmetic
%
Modulus (remainder
of a division)
Arithmetic
++
Incrementation
Arithmetic
-
Decrementation
Arithmetic
*
Assigns a value
to a variable
Assignment
/
Equality
Comparison
%
Inequality
Comparison
<
Less than
Comparison
>
Greater than
Comparison
<=
Less than or
equal to
Comparison
>=
Greater than or
equal to
Comparison
<=>
Returns an
integer reflecting
comparison
Comparison
!
Negation
Logical
AND
And
Logical
When the assignment operator (the
equals sign) was introduced in Chapter 2,
“Variables,” you learned that its meaning
isn’t exactly what you’d conventionally
think it to be. The line
&&
And
Logical
$var = 5;
OR
Or
Logical
||
Or
Logical
XOR
Exclusive or
Logical
doesn’t state that $var is equal to 5 but
that it is assigned the value of 5. This is
an important distinction.
??
Null coalescing
Logical
.
Concatenation
String
When it comes to creating conditionals, the
comparison and logical operators are the
most important. Table 6.1 lists the operators
to be discussed, along with those you’ve
already seen.
Comparison
When you’re writing conditionals, you’ll
often want to see if a variable is equal to
a specific value—to match usernames or
passwords, perhaps, which you can’t do
with the equals sign alone (because that
operator is used for assigning a value, not
equating values). Instead, for comparisons,
use the equality operator (==):
$var = 5;
if ($var == 5) { ...
continues on next page
Control Structures
135
These two lines of code together first
establish the value of $var as 5 and then
make a TRUE conditional that checks if $var
is equal to 5. This example demonstrates the
significant difference that one more equals
sign makes in your PHP code and why you
must distinguish carefully between the
assignment and comparison operators.
The next comparison operator—not equal
to—is represented by an exclamation mark
coupled with an equals sign (!=). The
remaining comparison operators are identical to their mathematical counterparts: less
than (<), greater than (>), less than or equal
to (<=), and greater than or equal to (>=).
As a demonstration of comparison operators, you’ll check that the user’s birth year
is before 2016 and that the confirmed
password matches the original password.
To use comparison operators:
1. Open handle_reg.php (Script 6.4)
in your text editor or IDE, if it is not
already open.
2. After the password validation, check
that the two passwords match
(Script 6.5):
if ($_POST['password']
➝ != $_POST['confirm']) {
print '
➝ Your confirmed password
➝ does not match the original
➝ password.
';
$okay = false;
}
To compare these two string values,
use the inequality operator. Alternatively, you could use one of the string
comparison functions (see Chapter 5,
“Using Strings”), but != is just fine.
Script 6.5 This version of the form-handling
script uses comparison operators to validate the
password and year values.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Registration
Registration Results
Please enter
your email address.';
$okay = false;
}
// Validate the password:
if (empty($_POST['password'])) {
print '
Please enter
your password.
';
$okay = false;
}
// Check the two passwords for equality:
if ($_POST['password'] != $_
POST['confirm']) {
print '
Your
confirmed password does not match
the original password.
';
$okay = false;
}
code continues on next page
136 Chapter 6
Script 6.5 continued
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// Validate the birth year:
if (is_numeric($_POST['year'])) {
$age = 2016 - $_POST['year']; //
Calculate age this year.
} else {
print '
Please enter
the year you were born as four
digits.
';
$okay = false;
}
// Check that they were born before this
year:
if ($_POST['year'] >= 2016) {
print '
Either you
entered your birth year wrong or
you come from the future!
';
$okay = false;
}
3. After the year validation, report an
error if the year is greater than or equal
to 2016:
if ($_POST['year'] >= 2016) {
print '
Either
➝ you entered your birth year
➝ wrong or you come from the
➝ future!
';
$okay = false;
}
If the user entered the year of birth as
2016 or later, it’s presumably a mistake.
(If you’re reading this book after 2016,
change the year accordingly).
continues on next page
// If there were no errors, print a
success message:
if ($okay) {
print '
You have been successfully
registered (but not really).
';
print "
You will turn $age this
year.
";
}
?>
Control Structures
137
4. Save your script, place it in the same
directory as register.html (on your
PHP-enabled server), and test it in your
browser again A and B.
Before you compare two string values
that come from a form (like the password
and confirmed password), it’s a good idea to
apply the trim() function to both, to get rid
of any errant spaces. I didn’t do so here, so as
not to overcomplicate matters, but this habit
is recommended. It’s also prudent to apply
trim() to values used for logging in, such
as usernames or email addresses.
Another method of checking that a text
input type has been filled out (as opposed to
using the empty() function) is this:
if (strlen($var) > 0 ) {
//
$var is okay.
}
A Run the form once again…
New in PHP 7 is the “spaceship” operator: <=>. This operator returns: –1 if the left
operand is less than the right operand; 1 if the
left operand is greater than the right; and 0 if
the two are equal. The password confirmation
conditional could be written this way:
if ( ($_POST['password'] <=>
➝ $_POST['confirm']) == 0) {
Except that is unnecessarily complex!
Logical
Writing conditions in PHP comes down to
identifying TRUE or FALSE situations. You
can do this by using functions and comparative operators, as you’ve already seen.
Logical operators—the final operator type
discussed in this chapter—help you create
more elaborate or obvious constructs.
138
Chapter 6
B …with two new validation checks in place.
Nesting Conditionals
Besides using logical operators to create more complex conditionals, you
can use nesting for this purpose (the
process of placing one control structure
inside another). The key to doing so is
to place the interior conditional as the
statement(s) section of the exterior conditional. For example:
In PHP, one example of a TRUE condition
is simply a variable name that has a value
that isn’t zero, an empty string, or FALSE,
such as
$var = 5;
if ($var) { ...
You’ve already seen this with the $okay
variable being used in the handling PHP
script.
if (condition1) {
if
(condition2) {
statement(s)2;
}
else { // condition2 else
other_statement(s)2;
} // End of 2
} else { // condition1 else
other_statement(s)1;
} // End of 1
A condition is also TRUE if it makes logical
sense:
As you can see from this example, you
can cut down on the complexity of these
structures by using extensive indentations and comments. As long as every
conditional is syntactically correct, there
are no rules as to how many levels of
nesting you can have, whether you use
an else clause or even whether a subconditional is part of the if or the else
section of the main conditional.
if (5 <= 3) { ...
if (5 >= 3) { ...
A condition will be FALSE if it refers to a
variable and that variable has no value (or
a value of 0 or an empty string), or if you’ve
created an illogical construct. The following
condition is always FALSE:
In PHP, the exclamation mark (!) is the not
operator. You can use it to invert the TRUE/
FALSE status of a statement. For example:
$var = 'value';
if ($var) {... // TRUE
if (!$var) {... // FALSE
if (isset($var)) {... // TRUE
if (!isset($var)) {... // FALSE
if (!empty($var)) {... // TRUE
To go beyond simple one-part conditions,
PHP supports five more types of logical
operators: two versions of and (AND and &&),
two versions of or (OR and ||—a character
called the pipe, put together twice), and
or not (XOR). When you have two options
for one operator (as with and and or), they
differ only in precedence. For almost every
situation, you can use either version of and
or either version of or interchangeably.
Control Structures
139
Using parentheses and logical operators,
you can create even more complex if
conditionals. For an AND conditional, every
conjoined part must be TRUE in order for
the whole conditional to be TRUE. With OR,
at least one subsection must be TRUE to
render the whole condition TRUE. These
conditionals are TRUE:
if ( (5 <= 3) OR (5 >= 3) ) { ...
if ( (5 > 3) AND (5 < 10) ) { ...
These conditionals are FALSE:
if ( (5 != 5) AND (5 > 3) ) { ...
if ( (5 != 5) OR (5 < 3) ) { ...
As you construct your conditionals, remember two important things: First, in order for
the statements that are the result of a conditional to be executed, the entire conditional
must have a TRUE value; second, by using
parentheses, you can ignore rules of precedence and ensure that your operators are
addressed in the order of your choosing.
To demonstrate logical operators, let’s add
more conditionals to the handle_reg.php
page. You’ll also nest one of the year conditionals inside another conditional (see the
sidebar “Nesting Conditionals” for more).
To use logical operators:
1. Open handle_reg.php (Script 6.5) in
your text editor or IDE, if it is not already
open.
2. Delete the existing year validations
(Script 6.6).
You’ll entirely rewrite these conditionals
as one nested conditional, so it’s best to
get rid of the old versions entirely.
Script 6.6 Here the handling PHP script is
changed so that the year validation routine uses
both multiple and nested conditions. Also, the
terms of agreement checkbox is now validated.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Registration
Registration Results
Please enter
your email address.';
$okay = false;
}
// Validate the password:
if (empty($_POST['password'])) {
print '
Please enter
your password.
';
$okay = false;
}
// Check the two passwords for equality:
if ($_POST['password'] != $_
POST['confirm']) {
print '
Your
confirmed password does not match the
original password.
';
$okay = false;
}
code continues on next page
140
Chapter 6
Script 6.6 continued
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Validate the year:
if ( is_numeric($_POST['year']) AND
(strlen($_POST['year']) == 4) ) {
// Check that they were born before
2016.
if ($_POST['year'] < 2016) {
$age = 2016 - $_POST['year'];
// Calculate age this year.
} else {
print '
Either
you entered your birth year
wrong or you come from the
future!
';
$okay = false;
} // End of 2nd conditional.
} else { // Else for 1st conditional.
print
'
Please
enter the year you were born as
four digits.
';
$okay = false;
} // End of 1st conditional.
// Validate the terms:
if ( !isset($_POST['terms'])) {
print '
You must
accept the terms.
';
$okay = false;
}
// If there were no errors, print a
success message:
if ($okay) {
print '
You have been successfully
registered (but not really).
';
print "
You will turn $age this
year.
";
}
?>
3. Check that the year variable is a fourdigit number:
if ( is_numeric($_POST['year'])
➝ AND (strlen($_POST['year'])
➝ == 4) ) {
This conditional has two parts. The first
you’ve already seen—it tests for a valid
numeric value. The second part gets
the length of the year variable (using
the strlen() function) and checks if
the length value is equal to 4. Because
of the AND, this conditional is TRUE only
if both conditions are met.
4. Create a subconditional to check if the
year value is before 2016:
if ($_POST['year'] < 2016) {
$age = 2016 - $_POST['year'];
} else {
print '
➝ Either you entered your birth
➝ year wrong or you come from
➝ the future!
';
$okay = FALSE;
} // End of 2nd conditional
This if-else conditional acts as the
statements part of the main conditional, and is thus executed only if
that condition is TRUE. This if-else
checks whether the year variable is
less than 2016 (i.e., the user must have
been born before the current year). If
that condition is TRUE, the user’s age
is calculated as before. Otherwise, an
error message is printed and the $okay
variable is set to FALSE (indicating that
a problem occurred).
Note that this conditional is just the
opposite of the previous version:
verifying that a value is less than some
number instead of greater than or equal
to that number.
continues on next page
Control Structures
141
5. Complete the main year conditional:
} else { // Else for 1st
conditional.
print '
Please
➝ enter the year you were born
➝ as four digits.
';
$okay = FALSE;
} // End of 1st conditional.
This else section completes the conditional begun in Step 3. If at least one of
the conditions set forth there is FALSE,
this message is printed, and $okay is
set to FALSE.
6. Confirm that the terms checkbox wasn’t
ignored:
if (!isset($_POST['terms'])) {
print '
You
➝ must accept the terms.
';
$okay = FALSE;
}
C The PHP script now catches if the year isn’t
a four-digit number, as will be the case with this
form submission.
If the $_POST['terms'] variable is not
set, then the user failed to select that
box, and an error should be reported.
To be more exact, this conditional
could be
if ( !isset($_POST['terms']) AND
➝ ($_POST['terms'] != 'Yes') ) {
7. Those are the only changes to the script,
so you can now save it again, place it in
the same directory as register.html
(on your PHP-enabled server), and test
it in your browser again C and D.
142
Chapter 6
D Error messages are printed if fields are
incorrectly filled out or if the terms checkbox is
not selected.
8. If desired, change your year value to
be in the future, and submit the form
again E.
It’s very easy in long, complicated
conditionals to forget an opening or closing
parenthesis or brace, which will produce either
error messages or unexpected results. Find
a system (like spacing out your conditionals
and using comments) to help clarify your code.
Another good technique is to create the conditional’s entire structure first, and then go back
to add the details.
If you have problems getting your
if-else statements to execute, print out the
values of your variables to help debug the
problem. A conditional may not be TRUE or
FALSE because a variable doesn’t have the
value you think it does.
The Null Coalescing Operator
New in PHP 7 is the null coalescing
operator, which is a fancy name for a
useful shortcut. Often you’ll want to
check if a variable has a value and, if not,
assign a default value to it. Before PHP 7,
this would be done using code like
if (isset($_POST['var'])) {
$var = $_POST['var'];
} else {
$var
= 'default value';
}
Thanks to the null coalescing operator,
??, that code can be abbreviated to
$var = $_POST['var'] ?? 'default
➝ value';
The result is semantically the same, but
the latter requires one-fourth as many lines
of code.
E The year validation still checks that the date is before 2016.
Control Structures
143
Using elseif
Similar to the if-else conditional is
if-elseif (or if-elseif-else). This conditional acts like a running if statement and
can be expanded to whatever complexity
you require:
if (condition1) {
statement(s);
} elseif (condition2) {
other_statement(s);
}
Here’s another example A:
if (condition1) {
statement(s);
} elseif (condition2) {
other_statement(s);
} else {
other_other_statement(s);
}
Understand that this structure means,
for example, that other_statement(s) are
only executed if condition1 is FALSE but
condition2 is TRUE. If both conditions are
FALSE, the other_other_statement(s) are
executed.
If the else is present, you must always make
it the last part of a conditional because
it’s executed unless one of the conditions
to that point has been met (again, else
represents the default behavior). You can,
however, continue to use elseifs as many
times as you want as part of one if conditional. You may also forgo an else clause if
you don’t need a default result.
As an example of this, let’s create a conditional that prints a message based on the
selected color value.
144
Chapter 6
A How an if-elseif-else conditional affects the
program flow of a script.
Script 6.7 This multiline if-elseif-else
conditional validates that a submitted color has an
allowed value and is used to determine what type
of color the selection is.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Registration
Registration Results
Please enter
your email address.';
$okay = false;
}
// Validate the password:
if (empty($_POST['password'])) {
print '
Please enter
your password.
';
$okay = false;
}
To use elseif:
1. Open handle_reg.php (Script 6.6) in
your text editor or IDE, if it is not already
open.
2. Before the $okay conditional, begin a
new conditional (Script 6.7):
if ($_POST['color'] == 'red') {
$color_type = 'primary';
The color value comes from a select
menu with four possible options: red,
yellow, green, and blue. This conditional will determine whether the user
has selected a primary—red, yellow, or
blue—or secondary (all others) color.
The first condition checks if the value
of $_POST['color'] is equal to the
string red.
Be certain to use the equality operator
—two equals signs—and not the assignment operator—one—in the conditional.
3. Add an elseif clause for the second
color:
} elseif ($_POST['color'] ==
➝ 'yellow') {
$color_type
= 'primary';
The elseif continues the main conditional begun in Step 2. The condition
itself is a replication of the condition in
Step 2, using a new color comparison.
continues on next page
// Check the two passwords for equality:
if ($_POST['password'] != $_
POST['confirm']) {
print '
Your
confirmed password does not match the
original password.
';
$okay = false;
}
code continues on next page
Control Structures
145
4. Add elseif clauses for the other two
colors:
} elseif ($_POST['color'] ==
➝ 'green') {
$color_type = 'secondary';
} elseif ($_POST['color'] ==
➝ 'blue') {
$color_type = 'primary';
Once you understand the main concept, it’s just a matter of repeating the
elseifs for every possible color value.
5. Add an else clause:
} else {
print '
➝ Please select your favorite
➝ color.
';
$okay = FALSE;
}
If the user didn’t select a color, or if the
user manipulated the form to submit
a different color value (other than red,
yellow, green, or blue), none of the
conditions will be TRUE, meaning this
else clause will take effect. That clause
prints an error and assigns a value of
FALSE to $okay, indicating a problem.
It doesn’t matter in what order the colors
are checked, so long as the else clause
comes last.
Script 6.7 continued
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Check the two passwords for equality:
if ($_POST['password'] != $_
POST['confirm']) {
print '
Your
confirmed password does not match the
original password.
';
$okay = false;
}
// Validate the year:
if ( is_numeric($_POST['year']) AND
(strlen($_POST['year']) == 4) ) {
// Check that they were born before
2016.
if ($_POST['year'] < 2016) {
$age = 2016 - $_POST['year']; //
Calculate age this year.
} else {
print '
Either you
entered your birth year wrong or
you come from the future!
';
$okay = false;
} // End of 2nd conditional.
} else { // Else for 1st conditional.
print '
Please enter
the year you were born as four
digits.
';
$okay = false;
} // End of 1st conditional.
// Validate the terms:
if ( !isset($_POST['terms'])) {
print '
';
$okay = false;
}
// If there were no errors, print a
success message:
if ($okay) {
print '
You have been successfully
registered (but not really).
';
print "
You will turn $age this
year.
";
print
"
Your favorite color is a
$color_type color.
";
}
?>
6. Within the $okay conditional, print the
user’s favorite color type:
print "
Your favorite color is
➝ a $color_type color.
";
7. Save the script, place it in the same
directory as register.html (on your
PHP-enabled server), and test it in your
browser again, using different color
options B and C.
One thing most beginner developers
don’t realize is that it’s possible—in fact, quite
easy—for a hacker to submit data to your PHP
script without using your HTML form. It’s also
easy with modern browsers to manipulate
forms. For these reasons, it’s important that
you validate the existence of expected variables (i.e., that they are set), their type, and
their values.
PHP also allows you to write elseif as
two words, if you prefer:
if (condition1) {
statement(s);
} else if (condition2) {
statement(s)2;
}
B The script now prints a message
acknowledging the user’s color choice.
C Failure to select a color results in this
error message.
Control Structures
147
The Switch Conditional
Once you get to the point where you
have longer if-elseif-else conditionals,
you may find that you can save programming time and clarify your code by using
a switch conditional instead. The switch
conditional takes only one possible condition, normally just a variable:
switch ($var) {
case
value1:
statement(s)1;
break;
case
value2:
statement(s)2;
break;
default:
statement(s)3;
break;
}
You must understand how a switch conditional works in order to use it properly.
After the keyword switch, a variable is
identified within parentheses. PHP will
then look at each case in order, trying to
identify a matching value. Note that, as
with any other use of strings and numbers
in PHP, numeric values would not be quoted;
string values should be. After the case
value section, a colon (not a semicolon)
prefaces the associated statements, which
are normally indented beginning on the
following line.
Once PHP finds a case that matches the
value of the conditional variable, it executes
the subsequent statements. Here’s the
tricky part: Once PHP has found a matching case, it will continue going through the
switch until it either comes to the end of
the switch conditional (the closing brace)
or hits a break statement, at which point it
exits the switch construct. Thus, it’s imperative that you close every case—even the
148
Chapter 6
Script 6.8 Switch conditionals can simplify
complicated if-elseif conditionals.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Registration
Registration Results
Please enter
your email address.';
$okay = false;
}
// Validate the password:
if (empty($_POST['password'])) {
print '
Please enter
your password.
';
$okay = false;
}
// Check the two passwords for equality:
if ($_POST['password'] != $_
POST['confirm']) {
print '
Your
confirmed password does not match the
original password.
';
$okay = false;
}
code continues on next page
Script 6.8 continued
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// Validate the year:
if ( is_numeric($_POST['year']) AND
(strlen($_POST['year']) == 4) ) {
// Check that they were born before
2016.
if ($_POST['year'] < 2016) {
$age = 2016 - $_POST['year']; //
Calculate age this year.
} else {
print '
Either you
entered your birth year wrong or
you come from the future!
';
$okay = false;
} // End of 2nd conditional.
} else { // Else for 1st conditional.
print '
Please enter
the year you were born as four
digits.
';
$okay = false;
} // End of 1st conditional.
// Validate the terms:
if ( !isset($_POST['terms'])) {
print '
You must
accept the terms.
';
$okay = false;
}
// Validate the color:
switch ($_POST['color']) {
case 'red':
$color_type = 'primary';
break;
case 'yellow':
$color_type = 'primary';
break;
case 'green':
$color_type = 'secondary';
break;
case 'blue':
$color_type = 'primary';
break;
default:
default case, for consistency’s sake—
with a break (the sidebar “Break, Exit, Die,
and Continue” discusses this keyword in
more detail).
This previous switch conditional is like a
rewrite of
if ($var == value1) {
statement(s)1;
} elseif ($variable == value2) {
statement(s)2;
} else {
statement(s)3;
}
Because the switch conditional uses the
value of $var as its condition, it first checks
to see if $var is equal to value1, and if so,
it executes statement(s)1. If not, it checks
to see if $var is equal to value2, and if so,
it executes statement(s)2. If neither condition is met, the default action of the switch
conditional is to execute statement(s)3.
With this in mind, let’s rewrite the colors
conditional as a switch.
To use a switch conditional:
1. Open handle_reg.php (Script 6.7) in your
text editor or IDE, if it is not already open.
2. Delete the extended colors conditional
(Script 6.8).
3. Begin the switch:
switch ($_POST['color']) {
As mentioned earlier, a switch conditional takes only one condition: a
variable’s name. In this example, it’s
$_POST['color'].
continues on next page
code continues on next page
Control Structures
149
4. Create the first case:
case 'red':
$color_type = 'primary';
break;
The first case checks to see if
$_POST['color'] has a value of red.
If so, then the same statement is
executed as before. Next you include
a break statement to exit the switch.
5. Add a case for the second color:
Script 6.8 continued
78
79
80
81
82
83
84
85
case 'yellow':
$color_type = 'primary';
break;
86
6. Add cases for the remaining colors:
88
89
90
91
case 'green':
$color_type = 'secondary';
break;
case 'blue':
$color_type = 'primary';
break;
87
print
'
Please
select your favorite color.
p>';
$okay = false;
break;
} // End of switch.
// If there were no errors, print a
success message:
if ($okay) {
print '
You have been successfully
registered (but not really).
';
print "
You will turn $age this
year.
";
print "
Your favorite color is a
$color_type color.
";
}
?>
Break, Exit, Die, and Continue
PHP includes many language constructs—tools that aren’t functions but still do something in your
scripts. For example, print is a language construct. Another example is break, which is demonstrated in the switch. A break exits the current structure, be it a switch, an if-else conditional,
or a loop.
Similar to this is continue, which terminates the current iteration of a loop. Any remaining statements within the loop aren’t executed, but the loop’s condition is checked again to see if the loop
should be entered.
exit and die are more potent versions of break (and they’re synonymous). Instead of exiting
the current structure, these two language constructs terminate the execution of the PHP script.
Therefore, all PHP code after a use of exit or die is never executed. For that matter, any HTML
after these constructs is never sent to the browser. You’ll see die used most frequently as a
heavy-handed error handling tool. exit is often used in conjunction with the header() function.
You’ll see an example of this in Chapter 8, “Creating Web Applications.”
150
Chapter 6
7. Add a default case and complete the
switch:
default:
print '
➝ Please select your favorite
➝ color.
';
$okay = FALSE;
break;
} // End of switch.
A The handling script still works the same,
whether the user selects a color…
This default case is the equivalent
of the else clause used in the original
conditional.
8. Save your script, place it in the same
directory as register.html (on your
PHP-enabled server), and test it in your
browser again A and B.
B …or fails to.
A default case isn’t required in your
switch conditional, but if it’s used, it should
be the last case. You could set up a switch so
that if the value isn’t explicitly met by one of
the cases, nothing happens.
If you’re using a string in your switch
conditional as the case value, keep in mind
that it’s case sensitive, meaning that Value
won’t match value.
You can structure switch conditionals
such that more than one case has the same
result. However, that kind of programming,
which requires sound knowledge of PHP’s
behavior, is unnecessarily clever for the beginning programmer.
Control Structures
151
The for Loop
Loops are the final type of control structure
discussed in this chapter. As suggested
earlier, loops are used to execute a section
of code repeatedly. You may want to print
something a certain number of times, or you
may want to do something with each value
in an array (an array is a list of values). For
either of these cases, and many more, you
can use a loop. (The latter example is demonstrated in the next chapter.)
PHP supports three kinds of loops: for,
while, and foreach. The while loop is
similar to for, but it’s used most frequently
when retrieving values from a database or
reading from a text file (it’s introduced in
the sidebar “The while Loop” and covered
in more detail in the next chapter). The
foreach loop is related to using arrays and
is introduced in the next chapter.
The for loop is designed to perform one
or more statements for a determined
number of iterations (unlike while, which
runs until a condition is FALSE—similar,
but significantly different, concepts). You
normally use a dummy variable in the loop
for this purpose:
for (initial expression; condition;
➝ closing expression) {
statement(s);
}
The initial expression is executed once:
the first time the loop is called. Then the
condition is used to determine whether
to execute the statements. The closing
expression is executed each time the condition is found to be TRUE, but only after
the statements are executed A.
152
Chapter 6
A This flowchart represents how a for loop is
executed in PHP.
Script 6.9 This script uses a PHP for loop to
dynamically generate the day of the month dropdown menu.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Registration Form
<p> I agree to
the terms (whatever they may be).
<input type="submit" name="submit"
value="Register">
6. Create a for loop to print out 31 days as
select menu options:
for ($i = 1; $i <= 31; $i++) {
print "\n";
}
The loop begins by creating a dummy
variable named $i. On the first use of
the loop, this variable is set to 1. Then,
as long as $i is less than or equal to 31,
the contents of the loop are executed.
These contents are the print line,
which creates code like
B The new version of the HTML form, with some
dynamically generated content.
followed by a return (created with \n).
After this statement is executed, the $i
variable is incremented by 1. Then the
condition ($i <= 31) is checked again,
and the process is repeated.
7. Close the PHP section, and the select
element:
?>
8. Save the file as register.php.
You must save the file with the .php
extension now in order for the PHP
code to be executed.
C If you view the HTML source code for the form,
you’ll see the data generated by the for loop.
9. Place the file in the proper directory for
your PHP-enabled server, and test it in
your browser B.
As long as this script is in the same
directory as handle_reg.php, you can
even fill out and submit the form as you
would with the plain HTML version.
10. If desired, view the HTML source code
to see the PHP-generated options C.
Control Structures
155
It’s conventional to use simple variables
as the counters within for loops: $i, $j, $k,
and so on.
Just as you can write the if conditional
on one line if you have only one statement,
you can do the same with the while and for
loops. Again, though, this isn’t recommended.
Loops can be nested inside each other.
You can also place conditionals within loops,
loops within conditionals, and so forth.
Pay close attention to your loop’s condition so that the loop ends at some point.
Otherwise, you’ll create an infinite loop, and
the script will run and run and run.
The while Loop
The second of the three types of loops that exist in PHP—the while loop—is designed to continue
working as long as the condition you establish is TRUE. Like the for loop, it checks the value of
the condition before each iteration. Once the condition becomes FALSE, the while loop is exited:
while (condition) {
statement(s);
}
The main difference between for and while is that while doesn’t include a system for setting
initial conditions or for executing closing expressions.
You also have the option of using the do...while loop, which guarantees that the statements are
executed at least once (this isn’t necessarily true of the while loop):
do {
statement(s);
} while (condition);
Although there is a fair amount of overlap regarding when you can use the two major loop constructs (while and for), you’ll discover as you program that sometimes one is more logical than the
other. The while loop is frequently used in the retrieval of data from a database (see Chapter 12,
“Intro to Databases”).
156
Chapter 6
Review and Pursue
If you have any problems with the
review questions or the pursue prompts,
turn to the book’s supporting forum
(www.LarryUllman.com/forums/).
Review
n
n
n
n
What is the basic structure of an
if conditional in PHP? An if-else
conditional? An if-elseif? An
if-elseif-else?
What are the differences between the
empty() and isset() functions?
What is the assignment operator?
What is the equality operator?
Without knowing anything about $var,
will the following conditional be TRUE
or FALSE? Why?
if ($var = 'donut') {
n
What do these operators mean?
> &&
> ||
> !
n
n
What is the syntax of a switch
conditional? When is a switch most
commonly used?
What is the syntax of a for loop?
Control Structures
157
Pursue
n
n
n
n
n
158
Check out the PHP manual’s pages for
the various operators.
Rewrite handle_reg.php so that it uses
a variable for the current year, instead
of hard-coding that value.
For debugging purposes, add code to
the beginning of the handle_reg.php
script that prints out the values of the
received variables. Hint: There’s a short
and a long way to do this.
Rewrite one of the versions of
handle_reg.php so that it prints the
user’s favorite color selection in the
user’s favorite color. Hint: You’ll want
to use CSS and concatenation.
Update handle_reg.php so that it
validates the user’s birthday by looking
at the three individual form elements:
month, day, and year. Create a variable
that represents the user’s birthday in
the format XX/DD/YYYY (again, you’ll
use concatenation for this).
Chapter 6
7
Using Arrays
The next—and last—variable type you’ll
learn about in this book is the array. Arrays
are significantly different from numbers or
strings, and you can’t make the most of
programming in PHP without understanding them.
Because of their unique nature, this chapter
will cover arrays more deliberately and
slowly than the other variable types. The
chapter begins with an introduction to the
concept, along with the basics of creating
and using arrays. Then it covers multidimensional arrays and some of the array-related
functions. The chapter concludes with arraystring conversions and a demonstration on
how to create an array from an HTML form.
In This Chapter
What Is an Array?
160
Creating an Array
162
Adding Items to an Array
166
Accessing Array Elements
170
Creating Multidimensional Arrays
173
Sorting Arrays
178
Transforming Between Strings
and Arrays
182
Creating an Array from a Form
186
Review and Pursue
191
What Is an Array?
Arrays constitute a complicated but very
useful notion. Whereas numbers and
strings are scalar variables—meaning they
always have only a single value—an array
is a collection of multiple values assembled
into one overriding variable. An array can
consist of numbers and/or strings and/or
other arrays, which allows this one variable
to hold exponentially more information
than a simple string or number can. For
example, if you wanted to create a grocery
list using strings, your code would look
something like this:
$item1 = 'apples';
$item2 = 'bananas';
$item3 = 'oranges';
For each added item, you’d need to create
a new string. This approach is cumbersome,
and it makes it difficult to refer back to the
entire list or any specific value later in your
code. You can greatly simplify matters by
placing your entire list into one array (say,
$items), which contains everything you
need (Table 7.1).
As an array, your list can be added to, sorted,
searched, and so forth. With this context in
mind, let’s look into the syntax of arrays.
160
Chapter 7
TABLE 7.1 Grocery List Array
Item Number
Item
1
apples
2
bananas
3
oranges
Superglobals and You
Throughout this book, you’ve already
dealt with some arrays: $_SERVER,
$_GET, and $_POST. These are all special
arrays known as superglobals, along
with $_COOKIE, $_SESSION, and $_ENV.
As you know, the $_POST array receives
all the data sent to the page from a form
that uses the POST method. Its indexes
are the names of the form elements, and
its values are the values of those form
elements. Therefore, $_POST['name']
refers to the value typed in a form input
created by the code
Similarly, $_GET refers to data sent from a
form using the GET method or from data
otherwise passed in the URL. $_COOKIE
refers to data stored in a cookie, and
$_SESSION refers to data stored in a
session (you’ll encounter these two in
Chapter 9, “Cookies and Sessions”).
$_ENV is like $_SERVER, containing values
pertaining to the computer on which PHP
is running.
Syntactical rules for arrays
The other variable types you’ve dealt
with—numbers and strings—have a variable name and a corresponding value (for
example, $first_name could be equal to
Larry). Arrays also have a name, derived
using the same conventions:
n
n
n
They begin with a dollar sign.
They continue with a letter or
underscore.
They finish with any combination of letters, numbers, or the underscore.
But arrays differ in that they contain multiple elements. Think of each row in Table 7.1
as an element. An element consists of an
index or key—the two words can be used
interchangeably—and a value. In Table 7.1,
the Item Number is the key, and the Item is
the value.
An array’s index is used as a reference
point to the values. An array can use either
numbers or strings as its keys, or both,
depending on how you set it up.
Generally, when you use an array it looks
the same as any other variable, except
that you include a key in brackets ([],
sometimes referred to as square brackets)
to reference particular values. Whereas
$items refers to the array as a whole,
$items[1] points to a specific element in
the array (in this example, apples).
Using Arrays
161
Creating an Array
The formal method of creating an array is
to use the array() function. Its syntax is
$list = array('apples', 'bananas',
➝ 'oranges');
Arrays automatically begin their indexing
at 0, unless otherwise specified. In that
example—which doesn’t specify an index
for the elements—the first item, apples,
is automatically indexed at 0, the second
item at 1, and the third at 2.
If you desire, you can assign the index
when using array():
$list = array(1 => 'apples', 2 =>
➝ 'bananas', 3 => 'oranges');
Because PHP is very liberal when it comes
to blank space in your code, you can make
this structure easier to read by writing it
over multiple lines:
$list = array(
1 => 'apples',
2 => 'bananas',
3 => 'oranges'
);
(For better legibility, it’s common to
indent the array elements as shown here,
although this is not required.)
162
Chapter 7
As of PHP 5.4, you can also create arrays
using the short array syntax. Simply use
brackets instead of a call to array():
$list = ['apples', 'bananas',
➝ 'oranges'];
Naturally, you can set the indexes with this
syntax as well:
$list = [
1 => 'apples',
2 => 'bananas',
3 => 'oranges'
];
Finally, the index value you specify doesn’t
have to be a number—you can use strings
instead. As an example, you could create
an array that records the soup of the day
for each day of the week, as in the following script. This example will also demonstrate how you can, and cannot, print out
an array (which has already been demonstrated but is worth rehashing).
Script 7.1 The $soups array contains three
elements and uses strings for its keys.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
No Soup for You!
Mmm...soups
'Clam Chowder',
'Tuesday' => 'White Chicken
Chili',
'Wednesday' => 'Vegetarian'
];
// Try to print the array:
print "
$soups
";
// Print the contents of the array:
print_r($soups);
?>
To create an array:
1. Begin a new document in your text
editor or IDE, to be named soups1.php
(Script 7.1):
No Soup for You!
Mmm...soups
2. Begin the PHP section of the script, and
address error handling, if necessary:
'Clam Chowder',
'Tuesday' => 'White Chicken
➝ Chili',
'Wednesday' => 'Vegetarian'
];
This is the proper short array syntax
format for initializing—creating and
assigning a value to—an array in PHP,
using strings as the indices. Because
both the keys and values are strings, you
surround them with quotation marks. As
with all strings, you can use either single
or double quotation marks, as long as
you’re mindful of other quotation marks
that might be found within the string.
If you are not using at least PHP version
5.4, or if you prefer to be more explicit,
use the array() function instead.
continues on next page
Using Arrays
163
4. Attempt to print the array:
print "
$soups
";
As you’ve already seen, arrays are also
different from scalar variables in that
they can’t be printed using this syntax.
5. Use the print_r() function to print out
the array differently:
print_r($soups);
In Chapter 2, “Variables,” you learned
how to use print_r() to show the
contents and structure of any variable.
Use it here so you can see the difference between the way this function
and print work with arrays.
6. Close the PHP and the HTML sections:
?>
7. Save your document as soups1.php,
place it in the proper directory for your
PHP-enabled server, and test it in your
browser A.
Remember to run the PHP script
through a URL.
A Because an array is structured differently than other variable types, a request to print out
an array results in the word Array. On the other hand, the print_r() function prints the array’s
contents and structure.
164
Chapter 7
The practice of beginning any index at 0
is standard in PHP and most other programming languages. As unnatural as this counting
system may seem, it’s here to stay, so you
have two possible coping techniques. First,
manually start all your arrays indexed at position 1. Second, unlearn a lifetime of counting
from 1. You can decide which is easier, but
most programmers just get used to this odd
construct.
You must refer to an array’s elements via
the same index used to create the array. In the
$soups example, $soups[0] has no value
even though the array obviously has a first element (the first element normally being indexed
at 0 numerically).
With numeric indexes, you can set the
first index and the others will follow sequentially. For example:
The range() function can also be used
to create an array of items based on a range of
values. Here are two examples:
$ten = range(1, 10);
$alphabet = range('a', 'z');
The range() function includes a step parameter that lets you specify increments:
$evens = range (0, 100, 2);
If you use the var_dump() function
in your script in lieu of print_r(), it shows
not only the contents of the array but also its
structure in a more detailed format B.
An array whose keys are numbers is
known as an indexed array. If the keys are
strings, it’s referred to as an associative array.
Other languages refer to associative arrays
as hashes.
$list = [1 => 'apples', 'bananas',
➝ 'oranges'];
Now bananas is indexed at 2 and oranges at 3.
B The var_dump() function (used with Script 7.1 instead of the print_r()
function) shows how many elements are in an array and how long each string
value is.
Using Arrays
165
Adding Items
to an Array
In PHP, once an array exists, you can
add extra elements to the array with the
assignment operator (the equals sign), in a
way similar to how you assign a value to a
string or a number. When doing so, you can
specify the key of the added element or
not specify it, but in either case, you must
refer to the array with brackets.
Here’s a definition of the $list array:
$list = [
1 => 'apples',
2 => 'bananas',
3 => 'oranges'
];
To add two items to that, you’d write
$list[] = 'pears';
$list[] = 'tomatoes';
If you don’t specify the key, each element
is appended to the existing array, indexed
with the next sequential number. Now
pears is located at 4 and tomatoes at 5.
If you do specify the index, the value is
assigned at that location. Any existing
value already indexed at that point is overwritten, like so:
$list[3] = 'pears';
$list[4] = 'tomatoes';
Now, the value of the element in the fourth
position of the array is tomatoes, and no
element of $list is equal to oranges (that
value was overwritten by pears). With this
in mind, unless you intend to overwrite any
existing data, you’ll be better off not naming
a specific key when adding values to your
arrays. However, if the array uses strings for
indices, you’ll probably want to specify keys
so that you don’t end up with an unusual
combination of string keys and numeric keys.
166
Chapter 7
Deleting Arrays and Array
Elements
You won’t frequently need to delete
an individual item from an array, but it’s
possible to do using the unset() function. This function eliminates a variable
and frees up the memory it used. When
applied to an array element, that element
is deleted:
unset($array[4]);
unset($array['key']);
Removing a single element will not
re-index the array, however. The code
removes one element, no element is now
indexed at 4, and every other element
continues to be indexed where they were.
If you apply unset() to an entire array or
any other variable type, the whole variable is deleted:
unset($array);
unset($string);
You can also reset an array (empty it
without deleting the variable altogether)
using the array() function or short
array syntax:
$array = array();
$array = [];
This has the effect of initializing the variable: making it exist and defining its type
without assigning a value.
Script 7.2 You can directly add elements to an
array one at a time by assigning each element a
value with the assignment operator. The count()
function will help you keep track of how many
elements the array contains.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
No Soup for You!
Mmm...soups
'Clam Chowder',
'Tuesday' => 'White Chicken Chili',
'Wednesday' => 'Vegetarian'
];
// Count and print the current number of
elements:
$count1 = count($soups);
print "
The soups array originally
had $count1 elements.
";
// Add three items to the array:
$soups['Thursday'] = 'Chicken
Noodle';
$soups['Friday'] = 'Tomato';
$soups['Saturday'] = 'Cream of
Broccoli';
To test this process, in the following task
you’ll rewrite soups1.php to add more elements to the array. To see the difference
adding more elements makes, you’ll print
out the number of elements in the array
before and after the new additions. Just
as you can find the length of a string—how
many characters it contains—by using
strlen(), you can determine the number
of elements in an array by using count():
$how_many = count($array);
To add elements to an array:
1. Open soups1.php in your text editor or
IDE, if it is not already open.
2. After the array is initialized on lines 14
through 18, add the following (Script 7.2,
to be named soups2.php):
$count1 = count($soups);
print "
The soups array
➝ originally had $count1
➝ elements.
";
The count() function determines
how many elements are in $soups. By
assigning that value to a variable, you
can easily print out the number.
3. Add three more elements to the array:
// Count and print the number of
elements again:
$soups['Thursday'] = 'Chicken
➝ Noodle';
$soups['Friday'] = 'Tomato';
$soups['Saturday'] = 'Cream of
➝ Broccoli';
$count2 = count($soups);
print "
After adding 3 more soups,
the array now has $count2 elements.
";
This code adds three more soups—
indexed at Thursday, Friday, and
Saturday—to the existing array.
// Print the contents of the array:
print_r($soups);
continues on next page
?>
Using Arrays 167
4. Recount how many elements are in the
array, and print out this value:
$count2 = count ($soups);
print "
After adding 3 more
➝ soups, the array now has
➝ $count2 elements.
";
This second print call is a repetition of
the first, showing how many elements
the array now contains.
5. Delete this line:
print "
$soups
";
This line isn’t needed anymore, so you
can get rid of it (you now know that you
can’t print out an array that easily).
6. Save your script as soups2.php, place
it in the proper directory for your
PHP-enabled server, and test it in your
browser A.
Be very careful when you directly add
elements to an array. There’s a correct way to
do it—
$array[] = 'Add This';
or
$array[1] = 'Add This';
—and an incorrect way:
$array = 'Add This';
If you forget to use the brackets, the new
value will replace the entire existing array,
leaving you with a simple string or number.
The code
$array[] = 'Value';
creates the $array variable if it doesn’t
yet exist.
A A direct way to ensure that the new elements were
successfully added to the array is to count the number of
elements before and after you make the additions.
168
Chapter 7
While working with these arrays, I’m
using single quotation marks to enclose both
the keys and the values. Nothing needs to
be interpolated (like a variable), so double
quotation marks aren’t required. It’s perfectly
acceptable to use double quotation marks,
though, if you want to.
You don’t (and, in fact, shouldn’t) quote
your keys if they’re numbers, variables, or
constants (you’ll learn about constants in
Chapter 8, “Creating Web Applications”).
For example:
$day = 'Sunday';
$soups[$day] = 'Mushroom';
The sizeof() function is an alias to
count(). It also returns the number of
elements in an array.
Merging Arrays
PHP has a function that allows you to append one array onto another. Think of it as concatenation for arrays. The function, array_merge(), works like so:
$new_array = array_merge($array1, $array2);
You could also write the soups2.php page using this function:
$soups2 = [
'Thursday' => 'Chicken Noodle',
'Friday' => 'Tomato',
'Saturday' => 'Cream of Broccoli'
];
$soups = array_merge($soups, $soups2);
You could even accomplish this result with the plus sign (thus adding two arrays together):
$soups = $soups + $soups2;
or
$soups += $soups2;
A difference between using array_merge() and the plus sign is that array_merge() will
re-index the arrays in the new array, whereas the plus sign maintains the existing indexes.
Also, with array addition, only elements in the second array indexed at new positions are
added in. Any element in the second array indexed at the same position as an element in the
first array will be ignored.
Using Arrays
169
Accessing Array
Elements
print "The first item is $array[0]";
that the other variable types don’t have:
You must know the keys of the array in
order to access its elements. If the array
was set using strings, like the $soups array,
then referring to $soups[1] points to nothing C. For that matter, because indexes
are case-sensitive, $soups['monday'] is
meaningless because Clam Chowder was
indexed at $soups['Monday'].
If the array uses strings for indexes, you
must quote the index, which results in a
problematic syntax when you’re trying to
print an individual array element A:
The fastest and easiest way to access all
the values of an array is to use a foreach
loop. This construct loops through every
element of an array:
print "
Monday's soup is
➝ $soups['Monday'].
";
foreach ($array as $key => $value) {
print "
Key is $key. Value is
➝ $value
";
}
Regardless of how you establish an array,
there’s only one way to retrieve a specific
element (or value) from it, and that is to
refer to its index:
To combat this issue, wrap the whole array
construct within braces (aka curly brackets)
B:
print "
Monday's soup is
➝ {$soups['Monday']}.
";
Ironically, the feature that makes arrays so
useful—being able to store multiple values
in one variable—also gives it a limitation
With each iteration of the loop, the current
array element’s key will be assigned to
the $key variable and the value to $value.
Note that you can use any variable name
here: $k and $v are likely choices, too.
You can now write a new soups script to
use this knowledge.
A Referencing within double
quotation marks a specific
element in an associative
array will cause parse errors.
B Wrapping an array element
reference in braces is one way
to avoid parse errors.
C Referring to an array index that does
not exist will create an Undefined offset
or Undefined Index notice.
170
Chapter 7
Script 7.3 A foreach loop is the easiest way to
access every element in an array.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
No Soup for You!
Mmm...soups
'Clam Chowder',
'Tuesday' => 'White Chicken Chili',
'Wednesday' => 'Vegetarian',
'Thursday' => 'Chicken Noodle',
'Friday' => 'Tomato',
'Saturday' => 'Cream of Broccoli'
];
// Print each key and value:
foreach ($soups as $day => $soup) {
print "
$day: $soup
\n";
}
?>
To print out the values of any array:
1. Begin a new document in your text
editor or IDE (Script 7.3, to be named
soups3.php):
No Soup for You!
Mmm...soups
2. Start the PHP section of the page, and
address error management, if needed:
'Clam Chowder',
'Tuesday' => 'White Chicken
➝ Chili',
'Wednesday' => 'Vegetarian',
'Thursday' => 'Chicken
➝ Noodle',
'Friday' => 'Tomato',
'Saturday' => 'Cream of
➝ Broccoli'
];
Here the entire array is created at once,
although you could create the array
in steps, as in the preceding script, if
you’d rather.
continues on next page
Using Arrays
171
4. Create a foreach loop to print out each
day’s soup:
foreach ($soups as $day =>
➝ $soup) {
print "
$day: $soup
\n";
}
The foreach loop iterates through
every element of the $soups array,
assigning each index to $day and each
value to $soup. These values are then
printed out within HTML paragraph
tags. The print statement concludes
with a newline character (created by
\n), which will make the HTML source
code of the page more legible.
5. Close the PHP section and the HTML
page:
?>
Another way to access all of a numerically indexed array’s elements is to use a
for loop:
for ($n = 0; $n < count($array);
➝ $n++) {
print "The value is $array[$n]";
}
The braces are used to avoid errors
when printing array values that have strings
for keys. Here are two examples where using
quotation marks is not problematic, so the
braces aren’t required:
$name = trim($array['name']);
$total = $_POST['qty'] *
➝ $_POST['price'];
Braces can also be used to separate a
variable reference from a dollar sign or other
characters:
print "The total is ${$total}.";
6. Save the page as soups3.php, place it
in the proper directory for your PHPenabled server, and test it in your
browser D.
One option for working with arrays is to
assign a specific element’s value to a separate
variable using the assignment operator:
$total = $array[1];
By doing this, you can preserve the original
value in the array and still manipulate the
value separately as a variable.
If you need to access only an array’s
values (and not its keys), you can use this
foreach structure:
foreach ($array as $value) {
// Do whatever.
}
172
Chapter 7
D The execution of the loop for every
element in the array generates this page.
The foreach construct allows the script to
access each key and value without prior
knowledge of what they are.
Creating
Multidimensional
Arrays
Multidimensional arrays are both simple
and complicated at the same time. The
structure and concept may be somewhat
difficult to grasp, but creating and accessing multidimensional arrays in PHP is
surprisingly easy.
You use a multidimensional array to create
an array containing more information than
a standard array. You accomplish this by
using other arrays for values instead of just
strings and numbers. For example:
$fruits = ['apples', 'bananas',
➝ 'oranges'];
$meats = ['steaks', 'hamburgers',
➝ 'pork chops'];
$groceries = [
'fruits' => $fruits,
'meats' => $meats,
'other' => 'peanuts',
'cash' => 30.00
];
This array, $groceries, now consists of
one string (peanuts), one floating-point
number (30.00), and two arrays ($fruits
and $meats).
Pointing to an element in an array within
an array can seem tricky. The key (pardon
the pun) is to continue adding indexes in
brackets as necessary, working from the
outer array inward. With that example,
bananas is at $groceries['fruits'][1].
First, you point to the element (in this case,
an array) in the $groceries array by using
['fruits']. Then, you point to the element
in that array based on its position—it’s the
second item, so you use the index [1].
Using Arrays 173
In this next task, you’ll write a script that
creates another multidimensional array
example.
To use multidimensional arrays:
1. Begin a new document in your text
editor or IDE, to be named books.php
(Script 7.4):
Larry Ullman's Books and
➝ Chapters
Some of Larry Ullman's
➝ Books
2. Create the initial PHP tags, and address
error management, if necessary:
Script 7.4 The multidimensional $books array
stores a lot of information in one big variable.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
'Getting
➝ Started with PHP', 'Variables',
➝ 'HTML Forms and PHP', 'Using
➝ Numbers'];
To build up the multidimensional array,
you’ll create three standard arrays and
then use them as the values for the
larger array. This array (named $phpvqs,
which is short for PHP for the Web:
Visual QuickStart Guide) uses numbers
for the keys and strings for the values.
The numbers begin with 1 and correspond to the chapter numbers. The
values are the chapter titles.
18
19
20
21
22
23
24
25
26
27
28
29
30
Larry Ullman's Books and
Chapters
Some of Larry Ullman's Books
'Getting Started with
PHP', 'Variables', 'HTML Forms and PHP',
'Using Numbers'];
// Create the second array:
$phpadv = [1 => 'Advanced PHP
Techniques', 'Developing Web
Applications', 'Advanced Database
Concepts', 'Basic Object-Oriented
Programming'];
// Create the third array:
$phpmysql = [1 => 'Introduction to
PHP', 'Programming with PHP', 'Creating
Dynamic Web Sites', 'Introduction to
MySQL'];
// Create the multidimensional array:
$books = [
'PHP VQS' => $phpvqs,
'PHP Advanced VQP' => $phpadv,
'PHP and MySQL VQP' => $phpmysql
];
// Print out some values:
print "
The third chapter of my
first book is {$books['PHP VQS']
[3]}.
";
code continues on next page
174
Chapter 7
Script 7.4 continued
31
32
33
34
35
36
37
38
39
40
41
print "
The first chapter of my
second book is {$books['PHP
Advanced VQP'][1]}.
";
print "
The fourth chapter of my
fourth book is {$books['PHP and
MySQL VQP'][4]}.
";
// See what happens with foreach:
foreach ($books as $key => $value) {
print "
$key: $value
\n";
}
?>
4. Create the next two arrays:
$phpadv = [1 => 'Advanced PHP
➝ Techniques', 'Developing Web
➝ Applications', 'Advanced
➝ Database Concepts', 'Basic
➝ Object-Oriented Programming'];
$phpmysql = [1 => 'Introduction
➝ to PHP', 'Programming with PHP',
➝ 'Creating Dynamic Web Sites',
➝ 'Introduction to MySQL'];
For each array, add only the book’s
first four chapters for simplicity’s sake.
These other two arrays represent my
PHP Advanced and Object-Oriented
Programming: Visual QuickPro Guide
(3rd Edition) (ISBN: 078-5342832181)
and PHP and MySQL for Dynamic Web
Sites: Visual QuickPro Guide (4th Edition) (ISBN: 978-0321784070) books.
5. Create the main, multidimensional array:
$books = [
'PHP VQS' => $phpvqs,
'PHP Advanced VQP' => $phpadv,
'PHP and MySQL VQP' =>
➝ $phpmysql
];
The $books array is the master array
for this script. It uses strings for keys,
which are shortened versions of the
book titles, and arrays for values. Use
the short array syntax or the array()
function to create it, as you would any
other array.
continues on next page
Using Arrays 175
6. Print out the name of the third chapter
of the PHP Visual QuickStart Guide
book:
print "
The third chapter of
➝ my first book is {$books
➝ ['PHP VQS'][3]}.
";
Following the rules stated earlier, all you
need to do to access any individual chapter name is to begin with $books, follow
that with the first index (['PHP VQS']),
and follow that with the next index ([3]).
Because you’re placing this in a print
call, you enclose the whole construct in
braces to avoid parse errors.
7. Print out two more examples:
print "
The first chapter of my
➝ second book is {$books['PHP
➝ Advanced VQP'][1]}.
";
print "
The fourth chapter of
➝ my fourth book is {$books
➝ ['PHP and MySQL VQP'][4]}
➝ .
";
8. Run the $books array through a
foreach loop to see the results:
foreach ($books as $key =>
➝ $value) {
print "
$key: $value
\n";
}
The $key variable will be assigned
each abbreviated book title, and the
$value variable ends up containing
each chapter array.
9. Close the PHP section and complete
the HTML page:
?>
10. Save the file as books.php, place it
in the proper directory for your PHPenabled server, and test it in your
browser A.
A The second through fourth lines are
generated by print statements. The error
message and the last line show the results
of the foreach loop (and the notices come
from attempting to print an array).
176
Chapter 7
To access every element of every array,
you can nest two foreach loops like this B:
foreach ($books as $title =>
➝ $chapters) {
print "
$title";
foreach
($chapters as $number =>
➝ $chapter) {
print
" Chapter $number is
➝ $chapter";
}
print '
';
}
B One foreach loop within another can access
every element of a two-dimensional array.
Using the print_r() or var_dump()
function (preferably enclosed in HTML
tags for better formatting), you can view an
entire multidimensional array C.
You can create a multidimensional array
in one statement instead of using several
steps as in this example. However, doing so
isn’t recommended for beginners, because
it’s all too easy to make syntactical errors as a
statement becomes more and more nested.
Although all the subarrays in this
example have the same structure (numbers for
indexes and four elements), that isn’t required
with multidimensional arrays.
To learn about the greater “Larry Ullman
collection,” including the three books referenced here, head to www.LarryUllman.com.
C The print_r() function shows the structure
and contents of the $books array.
Using Arrays
177
Sorting Arrays
PHP supports a variety of ways to sort an
array. Sort refers to an alphabetical sort if
the values being sorted are strings, or a
numerical sort if the values being sorted are
numbers. When sorting an array, you must
keep in mind that an array consists of pairs
of keys and values. Thus, an array can be
sorted based on the keys or the values. This
is further complicated by the fact that you
can sort the values and keep the corresponding keys aligned, or you can sort the values
and have them be assigned new keys.
To sort the values without regard to the
keys, use sort(). To sort these values
(again, without regard to the keys) in
reverse order, use rsort(). The syntax for
every sorting function is
function_name($array);
So, sort() and rsort() are used as
follows:
sort($array);
rsort($array);
To sort the values while maintaining the
correlation between each value and its key,
use asort(). To sort the values in reverse
while maintaining the key correlation, use
arsort().
To sort by the keys while maintaining the
correlation between the key and its value,
use ksort(). Conversely, krsort() sorts
the keys in reverse. Table 7.2 lists all these
functions.
Finally, shuffle() randomly reorganizes
the order of an array. Like sort() and
rsort(), shuffle() drops the existing
keys in the process.
As an example of sorting arrays, you’ll
create a list of students and the grades
they received on a test, and then sort this
list first by grade and then by name.
178
Chapter 7
TABLE 7.2 Array Sorting Functions
Function
Sorts By
Maintains
Key-Values?
sort()
Values
No
rsort()
Values (inverse)
No
asort()
Values
Yes
arsort()
Values (inverse)
Yes
ksort()
Keys
Yes
krsort()
Keys (inverse)
Yes
Script 7.5 PHP provides a number of different
functions for sorting arrays, including arsort()
and ksort().
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
My Little Gradebook
95,
'Sherwood' => 82,
'Toni' => 98,
'Franz' => 87,
'Melissa' => 75,
'Roddy' => 85
];
// Print the original array:
print '
Originally the array looks
like this: ';
foreach ($grades as $student => $grade)
{
print "$student: $grade \n";
}
print '
';
// Sort by value in reverse order, then
print again:
arsort($grades);
print '
After sorting the array by
value using arsort(), the array looks
like this: ';
foreach ($grades as $student => $grade)
{
print "$student: $grade \n";
}
print '
';
code continues on next page
To sort an array:
1. Begin a new document in your text
editor or IDE, to be named sort.php
(Script 7.5):
My Little Gradebook
➝
2. Begin the PHP section, and address
error handling, if desired:
95,
'Sherwood' => 82,
'Toni' => 98,
'Franz' => 87,
'Melissa' => 75,
'Roddy' => 85
];
The $grades array consists of six
students’ names along with their corresponding grades. Because the grades
are numbers, they don’t need to be
quoted when assigning them.
4. Print a caption, and then print each element of the array using a foreach loop:
print '
Originally the array
➝ looks like this: ';
foreach ($grades as $student =>
➝ $grade) {
print "$student: $grade \n";
}
print '
';
continues on next page
Using Arrays 179
Because the $grades array will be
printed three times, captions indicating
each state of the array will be useful.
At first, the script prints the array in the
original order. To do that, use a foreach
loop, where each index—the student’s
name—is assigned to $student, and
each value—the student’s grade—is
assigned to $grade. The final print call
closes the HTML paragraph.
5. Sort the array in reverse order by value
to determine who has the highest grade:
arsort($grades);
To determine who has the highest
grade, you need to use arsort()
instead of asort(). The latter, which
sorts the array in numeric order, would
order the grades 75, 82, 85, and so on,
rather than the desired 98, 95, 87.
You also must use arsort() and not
rsort() in order to maintain the keyvalue relationship (rsort() would
eliminate the student’s name associated
with each grade).
6. Print the array again (with a caption),
using another loop:
print '
After sorting the array
➝ by value using arsort(), the
➝ array looks like this: ';
foreach ($grades as $student =>
➝ $grade) {
print "$student: $grade \n";
}
print '
';
7. Sort the array by key to put the array in
alphabetical order by student name:
ksort ($grades);
The ksort() function organizes the
array by key (in this case, alphabetically) while maintaining the key-value
correlation.
180
Chapter 7
Script 7.5 continued
38
39
40
41
42
43
44
45
46
47
48
// Sort by key, then print again:
ksort($grades);
print '
After sorting the array by
key using ksort(), the array looks like
this: ';
foreach ($grades as $student => $grade)
{
print "$student: $grade \n";
}
print '
';
?>
8. Print a caption and the array one last
time:
print '
After sorting the array
➝ by key using ksort(), the array
➝ looks like this: ';
foreach ($grades as $student =>
➝ $grade) {
print "$student: $grade \n";
}
print '
';
9. Complete the script with the standard
PHP and HTML tags:
?>
A You can sort an array in a number of ways with
varied results. Pay close attention to whether you
want to maintain your key-value association when
choosing a sort function.
10. Save your script as sort.php, place it
in the proper directory for your PHPenabled server, and test it in your
browser A.
Because each element in an array must
have its own unique key, the $grades array
will only work using unique student names.
The natsort() and natcasesort()
functions sort a string (while maintaining
key-value associations) using natural order.
The most obvious example of natural order
sorting is that it places name2 before name12,
whereas sort() orders them name12 and
then name2.
The usort(), uasort(), and ursort()
functions let you sort an array using a userdefined comparison function. These functions
are most often used with multidimensional
arrays.
Using Arrays
181
Transforming Between
Strings and Arrays
Now that you have an understanding of
both strings and arrays, this next section
introduces two functions for switching
between the formats. The first, implode(),
turns an array into a string. The second,
explode(), does just the opposite. Here
are some reasons to use these functions:
n
n
n
To turn an array into a string in order
to pass that value appended to a URL
(which you can’t do as easily with an
array)
To turn an array into a string in order to
store that information in a database
To turn a string into an array to convert
a comma-delimited text field (say, a
keyword search area of a form) into its
separate parts
The syntax for using explode() is as
follows:
$array = explode(separator, $string);
The separator refers to whatever
character(s) define where one value ends
and another begins. Commonly this is a
comma, a tab, or a blank space. Thus your
code might be
$array = explode(',', $string);
or
$array = explode(' ', $string);
To go from an array to a string, you need
to define what the separator (aka the glue)
should be, and PHP does the rest:
$string = implode(glue, $array);
$string = implode(',', $array);
or
$string = implode(' ', $array);
To demonstrate how to use explode() and
implode(), you’ll create an HTML form that
takes a space-delimited string of names
from the user A. The PHP script will then
turn the string into an array so that it can
sort the list. Finally, the code will create
and return the alphabetized string B.
A This HTML form takes a list of words, which is then alphabetized by the list.php
script B.
182
Chapter 7
To create the HTML form:
1. Begin a new document in your text
editor or IDE, to be named list.html
(Script 7.6):
I Must Sort This Out!
➝
2. Create an HTML form with a text input:
B Here’s the same list, alphabetized for
the user. This process is quick and easy to
code, but doing so would be impossible
without arrays.
Script 7.6 This is a simple HTML form where a
user can submit a list of words. Including detailed
instructions for how the form should be used is a
prudent web design policy.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
I Must Sort This Out!
Enter the words you want
alphabetized with each individual word
separated by a space:
<input type="text" name="words"
size="60">
Enter the words you
➝ want alphabetized with each
➝ individual word separated by
➝ a pace:
It’s important in cases like this to
instruct the user. For example, if the
user enters a comma-delimited list, the
PHP script won’t be able to handle the
string properly (after completing both
scripts, try using commas in lieu of
spaces and see what happens).
3. Create a submit button, and then close
the form and the HTML page:
4. Save your script as list.html, and
place it in the proper directory for your
PHP-enabled server.
Now you’ll write the list.php page to process the data generated by list.html.
Using Arrays
183
To convert between
strings and arrays:
1. Begin a new document in your text
editor or IDE, to be named list.php
(Script 7.7):
I Have This Sorted
➝ OutI Have This Sorted Out
',
$words_array);
// Print the results:
print "
An alphabetized version of
your list is: $string_words
";
?>
4. Create a new string out of the sorted
array:
$string_words = implode(' ',
➝ $words_array);
Arrays don’t print as easily as strings,
so turn $words_array into a string
named $string_words. The resulting
string starts with the value of
$words_array[0], followed by the
HTML tag, the value of
$words_array[1], and so on. Using
instead of a space or comma gives
the list a more readable format when it’s
printed to the browser.
5. Print the new string to the browser:
print "
An alphabetized
➝ version of your list is:
➝ $string_words
";
6. Close the PHP section and the HTML
page:
?>
7. Save your page as list.php, place it in
the same directory as list.html, and
test both scripts in your browser A
and B.
You’ll also run across code written using
the join() function, which is synonymous
with implode().
As an extra precaution, use the techniques covered in Chapter 6, “Control
Structures,” to verify that $_POST['words']
is not empty before attempting to explode it.
Better yet, check that at least one comma is
present first!
Using Arrays
185
Creating an Array
from a Form
Throughout this chapter, you’ve established arrays entirely from within a PHP
page. You can, however, send an array
of data to a PHP script via an HTML form.
In fact, every time you use $_POST, this is
the case. But you can take this one step
further by creating arrays using an HTML
form. Such arrays will then be a part of
the greater $_POST array (thereby making
$_POST a multidimensional array).
A logical use of this capability is in dealing
with checkboxes, where users might need
to select multiple options from a group A.
The HTML source code for a checkbox is
as follows:
The problem in this particular case is that
each form element must have a unique
name. If you created several checkboxes,
each with a name of topping, only the
value of the last selected checkbox would
be received in the PHP script. If you were
to create unique names for each checkbox—ham, tomato, black_olives, and
so on—working with the selected values
would be tedious.
The workaround is to use array syntax, as
demonstrated in the next example.
To create an array with
an HTML form:
1. Begin a new document in your text
editor or IDE, to be named event.html
(Script 7.8):
Add an Event
Use this form to add an
➝ event:
2. Begin the HTML form:
This form will be submitted to
event.php, found in the same directory
as this HTML page.
3. Create a text input for an event name:
Event Name:
This example allows the user to enter
an event name and the days of the
week when it takes place.
A Checkboxes in an HTML form, presenting several possible options.
186
Chapter 7
Script 7.8 This HTML form has an array for the
checkbox input names.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Add an Event
Use this form to add an event:
p>
Event
Name:
Event Days:
input type="checkbox"
<
name="days[]" value="Sunday"> Sun
Mon
Tue
Wed
Thu
Fri
Sat
</p>
4. Create the days checkboxes:
Event Days:
Sun
Mon
Tue
Wed
Thu
Fri
Sat
All of these checkboxes use days[ ]
as the name value, which creates a
$_POST['days'] array in the PHP script.
The value attributes differ for each
checkbox, corresponding to the day of
the week.
5. Complete the HTML form:
6. Complete the HTML page:
7. Save your page as event.html, and
place it in the proper directory for your
PHP-enabled server.
You also need to write the event.php page
to handle this HTML form.
Using Arrays
187
To handle the HTML form:
1. Begin a new document in your text
editor or IDE, to be named event.php
(Script 7.9):
Add an Event
Script 7.9 This PHP script receives an array of
values in $_POST['days'].
1
2
3
4
5
6
7
8
9
10
11
2. Create the initial PHP tag, address error
management (if need be), and print an
introductory message:
12
13
14
You want to add an
➝ event called {$_POST['name']}
➝ which takes place on:
➝ ";
15
16
17
The print line prints out the value
of the event’s name. In a real-world
version of this script, you would add a
conditional to check that a name value
was entered first (see Chapter 6).
3. Begin a conditional to check that at
least one weekday was selected:
if (isset($_POST['days']) AND
➝ is_array($_POST['days'])) {
If no checkbox was selected, then
$_POST['days'] won’t be an existing
variable. To avoid an error caused by
referring to a variable that does not
exist, the first part of the conditional
checks that $_POST['days'] is set.
188
Chapter 7
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Add an Event
You want to add an event
called {$_POST['name']} which
takes place on: ";
// Print each weekday:
if (isset($_POST['days']) AND
is_array($_POST['days'])) {
foreach ($_POST['days'] as $day) {
print "$day \n";
}
} else {
print 'Please select at least one
weekday for this event!';
}
// Complete the paragraph:
print '';
?>
The List Function
The list() function is used to assign
array element values to individual variables. Start with an example:
$date = ['Thursday', 23,
➝ 'October'];
list($weekday, $day, $month) =
➝ $date;
Now there is a $weekday variable with a
value of Thursday, a $day variable with a
value of 23, and a $month variable with a
value of October.
Using list() has two caveats. First,
list() works only on arrays numerically indexed starting at 0. Second, when
you’re using the list() function, you
must acknowledge each array element.
You could not do this:
list($weekday, $month) = $date;
But you can use empty values to ignore
elements:
list ($weekday, , $month) =
$date;
or
list (, , $month) = $date;
The list() function is often used when
retrieving values from a database.
The second part of the condition—
and both must be TRUE for the entire
condition to be TRUE—confirms that
$_POST['days'] is an array. This is a
good step to take because a foreach
loop will create an error if it receives a
variable that isn’t an array B.
4. Print each selected weekday:
foreach ($_POST['days'] as $day)
{
print "$day \n";
}
To print out each selected weekday,
run the $_POST['days'] array through
a foreach loop. The array contains the
values (from the HTML form inputs; for
example, Monday, Tuesday, and so on)
for every checkbox that was selected.
5. Complete the is_array() conditional:
} else {
print 'Please select at least
➝ one weekday for this event!';
}
If no weekday was selected, then the
isset() AND is_array() condition is
FALSE, and this message is printed.
continues on next page
B Attempting to use foreach on a variable that is not an array is a common
cause of errors.
Using Arrays
189
6. Complete the main paragraph, the PHP
section, and the HTML page:
print '';
?>
The same technique demonstrated here
can be used to allow a user to select multiple
options in a drop-down menu. Just give the
menu a name with a syntax like something[],
and the PHP script will receive every selection
in $_POST['something'].
7. Save the page as event.php, place it in
the same directory as event.html, and
test both pages in your browser C, D,
and E.
C The HTML form with its checkboxes.
D The results of the HTML form.
E If users don’t select any of the day checkboxes, they’ll see this
message.
190
Chapter 7
Review and Pursue
If you have any problems with the review
questions or the pursue prompts, turn
to the book’s supporting forum
(www.LarryUllman.com/forums/).
Review
n
n
n
n
n
n
n
n
n
What’s the difference between an
indexed array and an associative
array?
What is the short array syntax and
when was it added to PHP?
When should you use quotation marks
for an array’s key or value? When
shouldn’t you?
How do you print a specific array element? How do you print out every
element in an array?
What happens if you don’t use the
brackets when adding an element to
an array?
What function returns the number of
elements in an array?
When must you use braces for printing
array elements?
What is the difference between
the sort() and asort() functions?
Between sort() and rsort()?
What is the syntax for explode()? For
implode()? If you don’t remember,
check out the PHP manual page for
either function.
Using Arrays
191
Pursue
n
n
n
n
n
n
192
Check out the PHP manual’s pages
for the array-related functions. Look
into some of the other available array
functions. I recommend familiarizing
yourself with array_key_exists(),
array_search(), and in_array().
Rewrite soups2.php so that it displays
the number of elements in the array
without using a separate variable. Hint:
You’ll need to concatenate the count()
function call into the print statement.
Create another script that creates and
displays a multidimensional array (or
some of it, anyway).
Rewrite list.php so that it uses
foreach instead of implode() but still
prints out each sorted word on its own
line in the browser. Also add some form
validation so that it attempts to parse
and sort the string only if it has a value.
Modify event.php so that it prints the
selected days as an unordered list.
Add validation conditionals to both
list.php and event.php that check
for submitted form values before
using them.
Chapter 7
8
Creating Web
Applications
The book to this point has covered the
fundamentals of programming with PHP;
now it’s time to begin tying it all together
into actual web applications. In this chapter, you’ll learn a number of functions and
techniques for making your websites more
professional, more feature-rich, and easier
to maintain.
In This Chapter
Creating Templates
194
Using External Files
201
Using Constants
207
Working with the Date and Time
211
First, you’ll learn how to use external files to
break pages into individual pieces, allowing
you to separate the logic from the presentation. Then you’ll tinker with constants, a
special data type in PHP. After that, you’ll
be introduced to some of the date- and
time-related functions built into PHP.
Handling HTML Forms with PHP,
Revisited
214
Two of the chapter’s topics discuss techniques rather than functions: having the
same page both display and handle an
HTML form, and having a form remember
user-submitted values. After that, you’ll see
how easy it can be to send email from PHP.
The chapter concludes with the slightly
more advanced topics of output buffering
and HTTP headers.
Making Forms Sticky
220
Sending Email
228
Output Buffering
233
Manipulating HTTP Headers
237
Review and Pursue
241
Creating Templates
Every example thus far has been a onepage script that handles an HTML form,
sorts arrays, performs calculations, and so
on. As you begin to develop multiple-page
websites (which is to say, web applications), it quickly becomes impractical to
repeat common elements on multiple pages.
On more sophisticated websites, many
features, such as the HTML design, will be
used by every, or almost every, page within
the site. You can put these elements into
each page, but when you need to make
a change, you’ll be required to make that
change over and over again. You can save
time by creating templates that separate
out the repeating content from the pagespecific materials. For example, a website
may have navigation, copyright, and other
features that repeat across multiple pages
A and B.
When you first start doing dynamic web
development, creating and using templates
can be daunting. The key is to start with
a basic prototype, as if you were creating
a static web page, and then divide that
prototype into reusable parts. By using the
PHP functions introduced in the next section of this chapter, you can easily include
the repeating parts in each page while the
new content is generated on a page-bypage basis.
To create the template in use by this
chapter’s examples, let’s start with the
prototype. This example’s layout C was
created using the Concise CSS Framework
(http://concisecss.com). Concise CSS is one
of many frameworks available that make
developing stylish and responsive web
pages a breeze, even for nondesigners.
194
Chapter 8
A The home page for the fifth edition of this book
has its page-specific content in the left column and
common elements in the right.
B The table of contents page uses some of the
same common elements as the home page A,
thanks to the templates.
C The design for this chapter’s examples, as a
single, static HTML page.
Script 8.1 This script represents the basic look
each page in the site should have.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Raise High the Roof Beam!
title>
32
To create the layout model:
1. Begin a new HTML document in
your text editor or IDE, to be named
template.html (Script 8.1):
Raise High the Roof
➝ Beam!
The first step in developing any template
system is to create a model document—
an example of what a basic page
should look like. Once you’ve created
this, you can break it down into its parts.
This template begins with the meta
tags recommended by the Concise CSS
Framework.
2. Add the CSS code:
This example uses CSS for the formatting and layout controls. The CSS
itself is stored in two external files that
become part of this page through the
link tag. The files are concise.min.css
and masthead.css, stored in a folder
named css.
continues on next page
code continues on next page
Creating Web Applications
195
Note that you’ll need to download the
CSS files from the book’s corresponding website (www.LarryUllman.com).
You’ll find it as part of the book’s downloadable code.
Script 8.1 continued
33
3. Close the HTML head, and begin the
body:
4. Create the page’s header:
Lorem
ipsum dolor sit
amet, consectetur adipisicing
elit, sed do eiusmod tempor
incididunt ut labore et
dolore magna aliqua. Ut
enim ad minim veniam, quis
nostrud exercitation ullamco
laboris nisi ut aliquip ex ea
commodo consequat. Duis aute
irure dolor in reprehenderit
in voluptate velit esse
cillum dolore eu fugiat
nulla pariatur. Excepteur
sint occaecat cupidatat non
proident, sunt in culpa qui
officia deserunt mollit anim
id est laborum.
The header area (also defined in the
CSS code) creates the banner and the
primary navigation links to the other
pages in the web application. The
specific links reference four PHP
scripts, all of which will be developed
in this chapter.
5. Begin, and mark, the start of the pagespecific content:
Everything up until this comment will
remain the same for every page in the
web application. To indicate where the
page-specific content begins (for your
own benefit), include an HTML comment. When making a choice, err on
the side of overcommenting your HTML
and PHP code!
Just before the comment, the
siteContent area is begun. This area
is defined in the CSS code and properly formats the main content part of
the page. In other words, on every
page, that page’s content will go within
the one main that has a class of
siteContent.
7. Mark the end of the changeable
content:
The code in Step 6 is the only text that
will change on a page-by-page basis.
Just as an HTML comment indicates
where that section starts, one here
indicates where it ends.
8. Add the footer:
The footer includes a credit.
9. Finish the HTML page:
10. Save the file as template.html, and
test it in your browser C.
Once you’ve completed a prototype that
you like, you can break it into its various
parts to generate the template system.
6. Create the page’s content:
Welcome to a J.D. Salinger
➝ Fan Club
Lorem ipsum dolor sit
➝ amet...
For the prototype, the content is just a
header and a whole lot of text (there’s
more in the actual script than I’ve
included in this step).
Creating Web Applications
197
To create the header file:
1. Open template.html (Script 8.1) in your
text editor or IDE, if it isn’t already open.
2. Select everything from the initial HTML
code to the HTML comment D.
Part of the benefit of identifying the
start of the page-specific content with
an HTML comment is that it simplifies
breaking the model into its parts.
D Using the prototype file, select and copy the initial lines of code to create the header.
198
Chapter 8
Script 8.2 This is a basic header file that creates
the HTML head information, includes the CSS file,
and begins the body.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Raise High the Roof Beam!
3. Copy this code.
Using your Edit menu or keyboard
shortcut (Ctrl+C on Windows,
Command+C on the Macintosh), copy
all the highlighted code to your computer’s clipboard.
4. Create a new, blank document in
your text editor or IDE, to be named
header.html.
5. Paste the copied text into the document
(Script 8.2).
Using your Edit menu or keyboard
shortcut (Ctrl+V on Windows,
Command+V on the Macintosh), paste
all the highlighted code into this new
document.
6. Save the file as header.html.
Now that the header file has been created,
you’ll make the footer file using the
same process.
Creating Web Applications
199
To create the footer file:
1. Open template.html (Script 8.1) in your
text editor or IDE, if it isn’t already open.
2. Select everything from the HTML
comment to the end of the script E.
3. Copy this code.
4. Create a new, blank document in your
text editor, to be named footer.html.
5. Paste the copied text into the document
(Script 8.3).
Script 8.3 This is a basic footer file that concludes
the HTML page.
1
2
3
4
5
6
7
8
9
10
6. Save the file as footer.html.
There are many far more complex template systems you can use in PHP to separate
the design from the logic. The best known of
these is probably Smarty (www.smarty.net).
E Again using the prototype file, select and copy the concluding lines of code for the footer.
CSS Templates
Cascading Style Sheets (CSS) have been an increasingly important part of the web for some time.
Their initial usage was focused on cosmetics (font sizes, colors, and so on), but now CSS is commonly used, as in this chapter, to control the layout of pages.
This example defines three areas of the page—header, main (i.e., content), and footer. The main
area will change for each page. The other areas contain standard items, such as navigation links,
that appear on each page of the site.
Just to be clear: The relationship between PHP and CSS is the same as that between PHP and
HTML—PHP runs on the server and HTML and CSS are significant to the browser. As with HTML,
you can use PHP to generate CSS, but in this example, the CSS is hard-coded into a separate file.
200
Chapter 8
Using External Files
As the preceding section stated, you can
save development time by creating separate
pages for particular elements and then incorporating them into the main PHP pages
using specific functions. Two of these functions are include() and require():
include('file.php');
require('file.html');
Both functions work the same way, with
one relatively key difference: If an include()
function fails, the PHP script generates
a warning A but continues to run. Conversely, if require() fails, it terminates the
execution of the script B.
Both include() and require() incorporate the referenced file into the main
file (for clarity’s sake, the file that has the
include() or require() line is the including or parent file). The result is the same
as if the included code were part of the
parent file in the first place.
Understanding this basic idea is key to
making the most of external files: Including a file makes it as if that file’s contents
were in the parent script to begin with. This
means that any code within the included
file not within PHP tags is treated as HTML.
And this is true regardless of what extension the included file has, because it’s the
extension of the including file that counts.
A When an include() fails, warnings are issued, but the script continues to execute.
B When a require() function call fails, warnings and errors are issued and the script stops running.
Creating Web Applications
201
There are many reasons to use included
files. You could put your own defined
functions into a common file (see Chapter
10, “Creating Functions,” for information
on writing your own functions). You might
also want to place your database access
information into a configuration file. First,
however, let’s include the template files
created in the preceding section of the
chapter in order to make pages abide by a
consistent design.
To use external files:
1. Create a new document in your text
editor or IDE, to be named index.php.
Script 8.4 Once the two included files have been
created, the include() function incorporates them
into the parent file to create the complete HTML
page on the fly.
1
2
3
4
5
6
7
8
9
10
11
2. Start with the initial PHP tags, and add
any comments (Script 8.4):
Welcome to a J.D. Salinger Fan
Club!
Lorem ipsum dolor sit amet,
consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
12
13
14
include('templates/footer.html');
// Include the footer.
File Navigation and Site Structure
To be able to use external files, you need
to understand file navigation on your
computer or server. Just as you must correctly refer to other pages in HTML links
or images in websites, you must properly
point a parent file to the included scripts.
You can do this by using absolute or
relative paths. An absolute path is a complete, specific address, like the following:
include('C:\inetpub\wwwfiles\
➝ file.php');
include('/Users/larry/Sites/
➝ file.php');
As long as the included file isn’t moved,
an absolute path will always work.
A relative path indicates where the
included file is in relation to the parent
file. These examples assume both are
within the same directory:
include('file.php');
include('./file.php');
The included file can also be in a directory below the parent one, as in this
chapter’s example (also see C):
include('templates/header.html');
Or, the included file could be in the directory above the parent:
include('../file.php');
Finally, a note on site structure: Once you
divvy up your web application into multiple pieces, you should begin thinking
about arranging the files in appropriate
folders. Complex sites might have the
main folder, another for images, one for
administration files, and a special directory for templates and included files. As
long as you properly reference the files
in your include() or require() statement, structuring your applications will
work fine and give the added benefit of
making them easier to maintain.
4. Include the header file:
include('templates/header.html');
To use the template system, you include
the header file here by invoking the
include() function. Because the header
file contains only HTML, all of its contents will be immediately sent to the
browser as if they were part of this file.
This line uses a relative path to refer
to the included file (see the “File
Navigation and Site Structure” sidebar)
and assumes that the file is stored in
the templates directory.
5. Close the PHP section, and create the
page-specific content:
?>
Welcome to a J.D. Salinger
➝ Fan Club
Lorem ipsum dolor sit
➝ amet...
Because the bulk of this page is standard HTML, it’s easier to just exit out
of the PHP section and then add the
HTML rather than using print to send
it to the browser. Again, there’s more
blather in the actual script than I’ve
included here.
6. Create another PHP section, and
include the footer file:
To finish the page, you need to include
the footer file, which displays the footer
and closes the HTML code. To do this,
you create a new section of PHP—you
can have multiple sections of PHP code
within a script—and call the include()
function again.
continues on next page
Creating Web Applications
203
7. Save the file as index.php.
8. Create a folder named templates
within the main web document directory on your PHP-enabled computer
or server.
To further separate the design elements
from the main content, the header and
footer files go within their own directory.
9. Place header.html and footer.html
in the templates directory you just
created.
10. Place index.php in the same directory
as the templates folder.
The relative locations on the computer
between the index page and the two
HTML pages must be correct in order
for the code to work. The two HTML
pages go within the templates
folder, and the templates folder and
index.php are in the same folder
(such as the web root directory).
11. Create a folder named css within the
main web document directory on your
PHP-enabled computer or server.
The CSS scripts will need to go in
this directory.
204
Chapter 8
web root
index.php
header.html
templates
footer.html
concise.min.css
css
masthead.css
C How the files and folders should be organized
on your PHP-enabled server.
12. Place the concise.min.css and
masthead.css scripts, available as part
of the book’s downloadable code, in
the css directory C.
Even though the header file includes
the CSS scripts, the reference to that
script must be relative to index.php.
It’s that page, after all, that will include
header.html.
13. Run index.php in your browser D.
The resulting page should look exactly
like the original layout (C in the previous section of the chapter).
14. View the page’s source code in your
browser.
The source code should be exactly like
the source code of the template.html
script (Script 8.1), aside from the
added comments for the script names
and numbers.
D This page has been dynamically generated using included files.
Creating Web Applications
205
All three files in this template system—
header.html, footer.html, and index.php
—must use the same encoding in order to avoid
problems (see Chapter 1, “Getting Started
with PHP,” for more on encoding). Each file’s
encoding must also match the encoding established in the HTML code.
The require() and include() functions can be used with or without parentheses:
require 'filename.html';
You might sometimes use a variable that
stores the name of the file to be included:
require $filename;
Both include() and require()
have variations: include_once() and
require_once(). Each is identical to its
counterpart except that it ensures that the
same file can be included only one time (in
a parent script). You should generally avoid
using these, because they’ll adversely affect
the script’s performance.
If a section of PHP executes only a single
command, it’s common to place both it and
the PHP tags on a single line:
If you see error messages like those
in A and B, the parent script can’t locate an
included file. This problem is most likely caused
by a misspelled included filename or an error
in the path (for example, using header.html
instead of templates/header.html).
206
Chapter 8
If the rendered page does not seem to
be reflecting the CSS styling, the HTML page
can’t find the corresponding file. Make sure
you’ve stored the file in the proper folder, with
the correct name, and that the reference is
correct relative to index.php.
A file’s extension is less important for
included files because they aren’t intended
to be run directly. As a general rule of thumb,
you’ll be safe using .html for an included file
containing only or mostly HTML (in which case
the extension indicates it’s an HTML-related
file) and .php for included files containing
only or mostly PHP. Some programmers use
an .inc extension (for include), but security
risks can arise with this practice. For that
reason, use the .php extension for any file
containing sensitive information (like database
access parameters). And, of course, always
use the .php extension for any PHP script that
will be executed directly.
Another good use of an external file is
to place your error settings code there so that
those changes are applied to every page in the
website.
The final closing PHP tag is not required,
and many developers advocate omitting it
because it’s unnecessary and the script may
run faster without it.
Using Constants
Many of PHP’s data types have already
been discussed in this book, primarily:
numbers, strings, and arrays. Constants
are another data type, but unlike variables,
their values cannot change.
Whereas variables are assigned values
via the assignment operator (=), constants
are assigned values using the define()
function:
define('CONSTANT_NAME', value);
Notice that—as a rule of thumb—constants
are named using all capital letters, although
doing so isn’t required. Most important,
constants don’t use the initial dollar sign
as variables do, because constants are not
variables. Here are two constants:
define('PI', 3.14);
define('CURRENCY', 'euros');
As with any value, quote those that are
strings, not those that are numbers.
Referring to constants is generally
straightforward:
print CURRENCY;
number_format(PI, 1);
But using constants within quotation
marks is more complicated. You can’t print
constants within single or double quotation
marks, like this A:
print "The cost is 468 CURRENCY";
print 'The cost is 468 CURRENCY';
Instead, concatenation or multiple print
statements are required:
print 'The cost is 468 ' . CURRENCY;
or
print 'The cost is 468 ';
print CURRENCY;
Along with the define() function for creating
constants is the defined() function (note
the final “d”). This function returns TRUE if
the submitted constant has been defined. It’s
often used as the basis for a conditional:
if (defined('CONSTANT_NAME')) { ...
As an example of working with constants,
you’ll give the sample application the ability
to display a different title (which appears
at the top of the browser window) for each
page. To accomplish this, you’ll define a
constant in the parent script that will then
be printed by the header file. This technique works because any variables or
constants that exist in the parent document
before the include() or require() call are
available to the included file (it’s as if the
included file were part of the parent file).
A The value of a constant cannot be printed using the
constant’s name within quotation marks.
Creating Web Applications
207
To use constants:
1. Create a new PHP document in
your text editor or IDE, to be named
books.php (Script 8.5):
J.D. Salinger's Books
The Catcher in the Rye
Nine Stories
Franny and Zooey
Raise High the Roof Beam,
➝ Carpenters and Seymour: An
➝ Introduction
The content here is simple but serves
the page’s purpose nicely.
5. Create a new PHP section that includes
the footer file:
208
Chapter 8
9
10
11
12
13
14
15
16
17
18
19
// Leave the PHP section to display lots
of HTML:
?>
J.D. Salinger's Books
The Catcher in the Rye
Nine Stories
Franny and Zooey
Raise High the Roof Beam,
Carpenters and Seymour: An
Introduction
Script 8.6 The header.html file is modified so
that it can set the page title value based on the
existence and value of a constant.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
8. If you want, add the constant definition
line to index.php to change its title.
The formal rules for naming constants
are exactly like those for variables except for
the omission of a dollar sign. Constant names
must begin with a letter or an underscore; can
contain any combination of letters, numbers,
and the underscore; and are case-sensitive.
PHP runs with several predefined
constants. These include PHP_VERSION (the
version of PHP running) and PHP_OS (the operating system of the server).
B The books page uses a PHP constant to create
its title.
In Chapter 9, “Cookies and Sessions,”
you’ll learn about another constant, SID
(which stands for session ID).
An added benefit of using constants is
that they’re global in scope. This concept will
mean more to you after you read the section
“Understanding Variable Scope” in Chapter 10.
Not only can the value of a constant
never be changed, a constant can’t be deleted
(unset, technically).
As of PHP 5.6, a constant can contain
an array of values. In earlier versions of the
language, a constant was scalar: it could store
only a single value.
210
Chapter 8
C Because the index page didn’t have a TITLE
constant defined in it, the default page title is used
(thanks to the conditional in Script 8.6).
Working with the
Date and Time
that can be. The basic usage of the date()
function is just
PHP has a few functions for working with
the date and time, the most important of
which is date(). The only thing the date()
function does is return date and time information in a format based on the arguments
it’s fed, but you’d be surprised how useful
A long list of possible options is available
for formatting, as indicated in Table 8.1
(the PHP manual lists a few more). These
parameters can also be combined—for
example, date('l F j, Y') returns
Thursday January 26, 2017.
date('formatting');
TABLE 8.1 Date() Function Formatting
Character
Meaning
Example
Y
Year as 4 digits
2017
y
Year as 2 digits
17
L
Is it a leap year?
1 (for yes)
n
Month as 1 or 2 digits
2
m
Month as 2 digits
02
F
Month
February
M
Month as 3 letters
Feb
j
Day of the month as 1 or 2 digits
8
d
Day of the month as 2 digits
08
l (lowercase L)
Day of the week
Monday
D
Day of the week as 3 letters
Mon
w
Day of the week as a single digit
0 (Sunday)
z
Day of the year: 0 to 365
189
t
Number of days in the month
31
S
English ordinal suffix for a day, as 2 characters
rd
g
Hour; 12-hour format as 1 or 2 digits
6
G
Hour; 24-hour format as 1 or 2 digits
18
h
Hour; 12-hour format as 2 digits
06
H
Hour; 24-hour format as 2 digits
18
i
Minutes
45
s
Seconds
18
u
Microseconds
1234
a
am or pm
am
A
AM or PM
PM
U
Seconds since the epoch
1048623008
e
Time zone
UTC
I (capital i)
Is it daylight savings?
1 (for yes)
O
Difference from GMT
+0600
Creating Web Applications
211
The date() function can take a second
argument, named a timestamp. A timestamp
is a number representing how many seconds
have passed since midnight on January 1,
1970—a moment known as the epoch.
Finally, realize that at least three time
zones are involved, then:
The time() function returns the timestamp
for the current moment. The mktime()
function can return a timestamp for a particular time and date:
mktime(hour, minute, second, month,
➝ day, year);
So the code
$ts = mktime(12, 30, 0, 11, 5,
➝ 2016);
assigns to $ts the number of seconds
from the epoch to 12:30 on November 5,
2016. That number can then be fed into
the date() function like so:
date('D', $ts);
This returns Sat, which is the three-letter
format for that day of the week.
An important thing to understand is that
timestamps and the epoch use Universal
Coordinated Time (curiously abbreviated
UTC), which is equivalent to Greenwich
Mean Time (GMT).
As of PHP 5.1, you should establish the
server’s time zone prior to calling any dateor time-related function. To do so, use
date_default_timezone_set(timezone);
The timezone value is a string like
America/New_York or Pacific/Auckland.
There are too many to list here (Africa
alone has over 50), but see the PHP
manual for them all. If you don’t take this
step, you might see errors about a date or
time function used without the time zone
being set.
212
Chapter 8
n
UTC
n
The server’s time zone
n
The time zone of the user
Because PHP is a server-side technology,
these functions reflect either UTC or the
date and time on the server. To get the
time on the client (in other words, on the
computer where the browser viewing the
page is located), you must use JavaScript.
To demonstrate the date() function, let’s
update the footer file so that it shows the
current date and time in the sidebar A. It’s
a trivial use of the function but will get you
started sufficiently.
To use date():
1. Open footer.html (Script 8.3) in your
text editor or IDE.
2. After the Concise CSS Framework mention, add the following (Script 8.7):
5. Close the PHP section, and finish the
HTML code:
?>
6. Save the file as footer.html, place
it in the templates directory of your
PHP-enabled server, and test it in your
browser A.
The server’s time zone can also be set
in the PHP configuration file (see Appendix A,
“Installation and Configuration”). Establishing
the time zone there is generally a better idea
than doing so on a script-by-script basis.
Added to PHP 5.3 are new ways to
create and manipulate dates and times using
the DateTime class. While useful, this new
tool requires familiarity with object-oriented
programming, therefore making it beyond the
scope of this beginner’s book.
Creating Web Applications
213
Handling HTML Forms
with PHP, Revisited
All the examples in this book so far have
used two separate scripts for handling
HTML forms: one that displayed the form
and another that received and processed
the form’s data. There’s certainly nothing
wrong with this method, but coding the
entire process in one script has its advantages. To make a page both display and
handle a form, use a conditional A.
if (/* form has been submitted */) {
// Handle the form.
} else {
//
Display the form.
}
There are many ways to determine if a
form has been submitted. One option is to
check whether any of the form’s variables
are set:
if (isset($_POST['something'])) { ...
However, if the user submitted the form
without completing it, that variable may not
be set (depending on the corresponding
form element type). A more reliable solution is to add a hidden input to a form so
that it can be checked:
214
Chapter 8
Script
A This flowchart represents how the same PHP
script can both display and handle an HTML form.
Again, the only purpose of this hidden
input is to reliably indicate that the form
has been submitted, even if the user did
nothing to complete the form. To check for
that, the handling PHP code would use this
conditional:
is the standard request made of most web
pages. When the form is submitted, and its
action attribute points to the same page,
a second request of the script will be
made, this time a POST request (assuming
the form uses the POST method). With this
in mind, you can test for a form’s submission by checking the request type, found in
the $_SERVER array:
if (isset($_POST['submitted'])) {
...
Another way of checking for a form’s submission is to examine how the page was
accessed. When you have a form that will
be submitted back to the same page, two
different types of requests will be made
of that script B. The first request, which
loads the form, will be a GET request. This
if ($_SERVER['REQUEST_METHOD'] ==
➝ 'POST') { ...
As an example of this, you’ll create the
basics of a login form.
Script
B When the same PHP script both displays and handles an HTML form, the script
will be requested using two different methods.
Creating Web Applications
215
To use one page to display
and handle a form:
1. Begin a new PHP document in your text
editor or IDE, to be named login.php
(Script 8.8):
Login Form
Users who are logged in
➝ can take advantage of certain
➝ features like this, that, and
➝ the other thing.
';
This text, which appears outside the
main conditional, will always show in
the browser, whether the form is being
displayed or has been submitted.
Because the core of this script revolves
around a PHP conditional, it’s arguably
clearer to print out HTML from PHP
rather than exit out of the PHP code as
you did in the previous two examples
(index.php and books.php).
4. Begin the conditional to check whether
the form has been submitted:
Script 8.8 The login page serves two purposes: It
displays the login form and handles its submission.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Login Form
Users who are logged in can take
advantage of certain features like
this, that, and the other thing.
';
// Check if the form has been submitted:
if ($_SERVER['REQUEST_METHOD'] ==
'POST') {
Handle the form:
//
( (!empty($_POST['email'])) &&
if
(!empty($_POST['password'])) ) {
17
18
if ( (strtolower($_
POST['email']) == 'me@example.
com') && ($_POST['password'] ==
'testpass') ) { // Correct!
19
20
print '
You are logged
in! Now you can blah,
blah, blah...
';
21
22
23
24
} else { // Incorrect!
print
'
The submitted email
address and password do not
match those on file! Go
back and try again.
';
if ($_SERVER['REQUEST_METHOD'] ==
➝ 'POST') {
To test whether the form has
been submitted, check whether
$_SERVER['REQUEST_METHOD']
equals POST (case-sensitive).
25
26
27
28
29
}
} else { // Forgot a field.
code continues on next page
216
Chapter 8
Script 8.8 continued
30
print '
Please make sure you
enter both an email address and
a password! Go back and try
again.
';
37
38
39
40
41
42
43
44
45
}
include('templates/footer.html'); //
Need the footer.
?>
5. Create a nested pair of conditionals to
process the form data:
if ( (!empty($_POST['email'])) &&
(!empty($_POST['password'])) ) {
if ( (strtolower
➝ ($_POST['email']) ==
➝ 'me@example.com') &&
➝ ($_POST['password'] ==
➝ 'testpass') ) { // Correct!
print '
You are logged
➝ in! Now you can blah,
➝ blah, blah...
';
}
else { // Incorrect!
print '
The submitted email
➝ address and password do not
➝ match those on file! Go
➝ back and try again.
';
}
} else { // Forgot a field.
print
'
Please make sure you
➝ enter both an email address
➝ and a password! Go back
➝ and try again.
';
}
These conditionals handle the form data.
The first conditional checks that both the
email address and password variables
have values. If they don’t, a message is
displayed (Please make sure…). Within
that first conditional, another conditional
checks whether the email address is
equal to me@example.com and the
password is equal to testpass. If so, let’s
say the user is logged in (it would be
too advanced at this juncture to store
and retrieve user information to create
a real login system). Otherwise, a message indicates that the wrong values
were entered.
Creating Web Applications 217
Be certain to use the equals operator (==)
here and not the assignment operator (=)
in this conditional, which is a common
mistake. Also, in case users enter their
address as Me@example.com, or any
other capitalized permutation, the
strtolower() function is first applied
to the email address, prior to checking
for equality.
Finally, some Concise CSS Framework
classes are used to add styling—green
and red coloring—to the printed text.
6. Complete the main conditional:
} else { // Display the form.
print '
➝
';
}
This concludes the main conditional,
which checks whether the form has
been submitted. If the form hasn’t been
submitted, then the form is displayed.
The form itself is very simple C.
To clarify a point of possible confusion,
even though the form’s method attribute
has a value of post (all lowercase), to
check for the form’s submission the
request method value is still POST (all
uppercase).
218
Chapter 8
C This simple login page takes an
email address and a password.
7. Require the footer file, and complete
the PHP page:
include('templates/footer.html');
?>
message.
8. Save the file as login.php, place it in
the same directory as index.php, and
test it in your browser D, E, and F.
E Failure to submit either an email address or a
This trick of checking for the presence
of a hidden input can be confusing. It works
because the same script—login.php—will be
accessed twice by the user. The first time the
form will not have been submitted, so a conditional checking if $_POST['submitted']
is set will be FALSE and the form will be displayed. Then the page will be accessed again
after the user clicks submit, at which point the
conditional becomes TRUE.
D Upon successfully logging in, the user sees this
password results in this message.
F If either the email address or the password
doesn’t match that in the script, the user sees this
error message.
If you want a page to handle a form and
then immediately display the form again, use
this:
if ($_SERVER['REQUEST_METHOD'] ==
➝ 'POST') {
//
Handle the form.
}
// Display the form.
Creating Web Applications
219
Making Forms Sticky
A sticky form remembers values entered
into it. A common example is a search
engine, which often displays your terms in
the search box, even when showing the
results of the search. You might also want
to use sticky forms on occasions where the
user failed to complete a form accurately
and therefore must resubmit it A.
From a technological standpoint, sticky
forms work by having their form element
values predetermined. You can make this
happen by setting the value attribute of
text inputs:
A Creating sticky forms makes it easier for
users to correct omissions in incomplete form
submissions.
To have PHP preset that value, print the
appropriate variable between the quotation marks:
The first time the form is run, the PHP code
prints nothing (because the variable has no
value). If the form is displayed again after
submission, a value that the user originally
entered in the form input will be displayed
there automatically. That’s the basic idea,
but a more professional implementation
would address two things.
B The HTML source of the page shows the PHP error caused by referring to a variable that does not exist.
220
Chapter 8
First, it’s best not to refer to variables that
don’t exist. Doing so creates PHP warnings,
and with the PHP code buried in a form
element’s attribute, the warning itself will
only be fully visible in the HTML source
code B. To avoid that, check that the variable is set before printing it:
C The registration form as the user first sees it.
Second, certain characters that could
be in a submitted value will cause problems if printed as a form element’s value.
To prevent such problems, apply the
htmlspecialchars() function (discussed
in Chapter 5, “Using Strings”). With this in
mind, a longer but better version of this
code is as follows:
To demonstrate this concept, you’ll create
the shell of a registration form C.
Creating Web Applications
221
To make a sticky form:
1. Create a new PHP script in your
text editor or IDE, to be named
register.php (Script 8.9):
Registration Form
Register so that you can
➝ take advantage of certain
➝ features like this, that, and
➝ the other thing.
';
4. Check whether the form has been
submitted:
if ($_SERVER['REQUEST_METHOD'] ==
➝ 'POST') {
Like the login page, this one script both
displays and handles the registration
form. To check whether the form has
been submitted, the same code previously explained is used here.
5. Create a flag variable:
$problem = false;
The $problem variable will be used to
indicate whether a problem occurred.
Specifically, you want to make sure that
every form input has been filled out
before you formally register the user.
Initially, this variable is set to FALSE,
because no problems have occurred.
This is the same approach used in
Chapter 6, “Control Structures.”
Script 8.9 The registration form uses a sticky
feature so that it recalls the values previously
entered into it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Registration Form
Register so that you can take
advantage of certain features like
this, that, and the other thing.
p>';
// Check if the form has been submitted:
if ($_SERVER['REQUEST_METHOD'] ==
'POST') {
$problem
= false; // No problems so
far.
Check for each value...
//
if (empty($_POST['first_name'])) {
$problem = true;
print '
Please enter your first
name!
';
}
if (empty($_POST['last_name'])) {
$problem = true;
print '
Please enter your last
name!
';
}
if (empty($_POST['email'])) {
$problem = true;
print '
Please enter your email
address!
';
}
code continues on next page
222
Chapter 8
6. Check that a first name was entered:
Script 8.9 continued
33
34
35
36
37
38
39
40
41
42
43
if (empty($_POST['password1'])) {
$problem = true;
print '
Your
password did not match your
confirmed password!
';
}
(!$problem) { // If there weren't
if
any problems...
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Print a message:
//
print '
You are now
registered! Okay, you are not
really registered but...
';
Clear the posted values:
//
$_POST = [];
} else { // Forgot a field.
print
'
Please try again!
';
}
} // End of handle form IF.
// Create the form:
?>
if (empty($_POST['first_name']))
{
$problem = true;
print '
Please enter your
➝ first name!
';
}
As a simple test to determine whether
the user has entered a first name value,
check that the variable isn’t empty.
(This technique was first discussed
in Chapter 6.) If the variable is empty,
then indicate a problem by setting that
variable to TRUE and print an error message. The error message has a class
type of text--error, so that the CSS formatting is applied. (That class is defined
within the Concise CSS Framework.)
7. Repeat the validation for the last name
and email address:
if (empty($_POST['last_name'])) {
$problem = true;
print '
Please enter your last
➝ name!
';
}
if (empty($_POST['email'])) {
$problem = true;
print '
Please enter your
➝ email address!
';
}
Both of these checks are variations on
the username validation routine.
continues on next page
64
code continues on next page
Creating Web Applications
223
8. Validate the passwords:
if (empty($_POST['password1'])) {
$problem = true;
print '
Your password did
➝ not match your confirmed
➝ password!
';
}
The password validation requires two
conditionals. The first checks whether
the $_POST['password1'] variable is
empty. The second checks whether
the $_POST['password1'] variable isn’t
equal to the $_POST['password2']
variable. You don’t need to see if
$_POST['password2'] is empty because
if it is and $_POST['password1'] isn’t,
the second conditional will catch that
problem. If $_POST['password1']
and $_POST['password2'] are both
empty, the first conditional will catch
the mistake.
9. Check whether a problem occurred:
if (!$problem) {
print '
You are now
➝ registered! Okay, you
➝ are not really registered
➝ but...
';
$_POST = [];
If there were no problems, the
$problem variable is still FALSE, and
the initial condition here is TRUE (the
condition is that $problem has a value
of FALSE). In that case, the registration
224
Chapter 8
Script 8.9 continued
65
66
67
68
69
70
71
72
73
74
75
76
process would take place. The formal
registration process, where the data is
stored in a file or database, has not yet
been developed, so a simple message
appears in its stead here.
Next, the $_POST variable is assigned
the value of an empty array using the
short array syntax. This line has the
effect of wiping out the contents of
the $_POST variable (i.e., resetting it as
an empty array). This step is taken only
upon a successful (theoretical) registration so that the values are not redisplayed in the registration form (e.g., see
Step 12).
10. Complete the conditionals:
} else { // Forgot a field.
print '
Please try again!
➝
';
}
} // End of handle form IF.
The else clause applies if a problem
occurred, in which case the user is
asked to complete the form again.
11. Begin the HTML form:
?>
Unlike the login example, this page
always displays the form. Therefore,
the form isn’t part of any conditional.
Also, because there’s a lot of HTML to
be generated, it’ll be easier to leave the
PHP section of the page and just output
the HTML directly.
12. Create the sticky first name input:
To make the first name input sticky,
preset its value attribute by printing out
the $_POST['first_name'] variable,
but only if it’s set. The conditional is
therefore put within PHP tags within
the HTML’s value section of the form
element. As already mentioned, the
htmlspecialchars() function is used
to handle any potentially problematic
characters.
Note that if the user filled out the form
properly, the entire $_POST array will
have been reset, making this PHP conditional FALSE.
If it helps your comprehension, write out
the PHP code:
continues on next page
Creating Web Applications
225
13. Repeat the process for the last name
and email address:
➝
These are variations on Step 12, switching the variable names as appropriate.
14. Add the rest of the form:
➝
➝
➝
226
Chapter 8
D The registration form indicates any problems
and retains the form values.
E The registration form after the user successfully
fills it out.
It used to be the case that you couldn’t
preset a value for a password input,
but most browsers now support this
feature. Then there is the submit button
and the closing form tag.
15. Complete the PHP page:
The last step is to include the HTML
footer.
16. Save the file as register.php, place it
in the proper directory on your PHPenabled server, and test it in your
browser D and E.
To preselect a pull-down menu, use
selected="selected":
Again, you’d need to use a PHP conditional
to see if that text should be added to the element’s definition.
To preset the value of a text area, place
the value between the textarea tags:
You should quote all attribute values in
form inputs. If you don’t quote your values,
any spaces in them mark the end of the value
(for example, Larry Ullman will display as just
Larry in the form input).
To preset the status of radio buttons
or checkboxes as selected, add the code
checked="checked" to the input tag:
Of course, you’d need to use a PHP conditional to see if that text should be added to the
element’s definition.
Creating Web Applications
227
Sending Email
Sending email using PHP is theoretically
simple, merely requiring only PHP’s mail()
function. This function uses the server’s
email application (such as sendmail on
Unix or Mac OS X) or an SMTP (Simple Mail
Transfer Protocol) server to send out the
messages. The basic usage of this function
is as follows:
mail(to, subject, body);
The first argument is the email address
(or addresses, separated by commas)
to which the email should be sent. The
second argument establishes the message’s subject line, and the third argument
creates the message’s content.
This function can take another argument
through which you can add more details
(additional headers) to the email, including
a From address, email priority, and carboncopy (CC) addresses:
mail('someone@example.com', 'Test
➝ Email', 'This is a test email',
➝ 'From: 'email@example.com');
Although doing so is easy in theory, using
this function in real-world code can be far
more complex. For starters, setting up your
own computer to send out email can be
a challenge (see the sidebar “Configuring
Your Server to Send Email”).
Second, you should take steps to prevent
malicious people from using your forms
to send out spam. In our next example, an
email will be sent to the provided email
address. If a conniving user supplies multiple addresses A, an email will be sent to
each one. You can safeguard against this
in many ways. For the level of this book,
one simple option is to confirm that there’s
only a single @ present in the provided
address (i.e., it’s only one email address).
228
Chapter 8
A A user could easily attempt to send emails to
multiple recipients through a form like this.
Script 8.10 In PHP, you can send email by calling
the mail() function.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Registration Form
Register so that you can take
advantage of certain features like
this, that, and the other thing.
';
// Check if the form has been submitted:
if ($_SERVER['REQUEST_METHOD'] ==
'POST') {
$problem
= false; // No problems so
far.
Check for each value...
//
if (empty($_POST['first_name'])) {
$problem = true;
print '
Please enter your first
name!
';
}
if (empty($_POST['last_name'])) {
$problem = true;
print '
Your
password did not match your
confirmed password!
';
}
(!$problem) { // If there weren't
if
any problems...
Print a message:
//
print '
You are now
registered! Okay, you are not
really registered but...
';
Send the email:
//
$body
= "Thank you, {$_
POST['first_name']}, for
registering with the J.D.
Salinger fan club!'.";
mail($_POST['email'],
'Registration Confirmation',
$body, 'From: admin@example.
com');
// Clear the posted values:
$_POST = [];
} else { // Forgot a field.
You can count how many times a substring
is present in a string using the aptly named
substr_count() function:
if (substr_count($_POST
➝ ['email'],'@') == 1) {...
With those caveats, let’s add a mail()
function call to the registration page so
that you get a sense of how the function
might be used.
To send email with PHP:
1. Open register.php (Script 8.9) in your
text editor or IDE.
2. Change the email validation so that it
also checks for a single “at” symbol
(Script 8.10):
if (empty($_POST['email']) ||
➝ (substr_count($_POST['email'],
➝ '@') != 1) ) {
Now the email address validation fails
if the value is empty or if it doesn’t
contain exactly one @. This doesn’t constitute thorough validation—far from it—
but the email address becomes less of
a security risk to use. See the tips for
ways to improve upon this.
3. After the registration message (line 46),
add the following:
$body = "Thank you, {$_POST
➝ ['first_name']}, for
➝ registering with the J.D.
➝ Salinger fan club!";
mail($_POST['email'],
➝ 'Registration Confirmation',
➝ $body, 'From: admin@example.
➝ com');
continues on next page
code continues on next page
Creating Web Applications
229
Script 8.10 continued
57
58
59
60
61
62
63
64
65
66
67
print '
Please try again!
';
}
} // End of handle form IF.
// Create the form:
?>
68
69
70
71
72
73
74
75
76
77
78
79
80
81
230
Chapter 8
B If users provide multiple email addresses A,
they’ll see an error message.
Sometimes the easiest way to use this
function is to establish the body as a
variable and then feed it into the mail()
function (as opposed to writing the
email’s body within the function call).
The message itself is sent to the address
with which the user registered, with the
subject Registration Confirmation, from
the address admin@example.com. If
you’ll be running this script on a live
server, you should use an actual email
address for that site as the from value.
4. Save the file, place it in the proper
directory of your PHP- and emailenabled server, and test it in your
browser B.
C This email was sent by the PHP script upon
successful pseudo-registration.
5. Upon successfully completing the form,
check your email for the message C.
The “Review and Pursue” section at the
end of this chapter points you in the direction of an excellent tool for validating email
addresses, provided you’re using PHP version
5.2 or later.
The HTML5 email input type limits the
user to only entering a single email address,
but that can easily be circumvented.
In my PHP and MySQL for Dynamic Web
Sites: Visual QuickPro Guide (Peachpit Press)
and online in my forums (www.LarryUllman.com/
forums/), I discuss other ways to secure the
emails that get sent by a PHP script.
If you have problems receiving the PHPsent email, start by confirming that the mail
server works on its own without involving
PHP. Then make sure you’re using a valid from
address. Finally, try using different recipient
addresses, and keep an eye on your spam
folder to see that the message isn’t getting put
there (if applicable).
continues on next page
Creating Web Applications
231
It’s possible to send email with attachments or HTML email, although doing so
requires far more sophisticated coding
(normally involving classes and objects).
Fortunately, a number of programmers have
already developed workable solutions that are
available for use. See Appendix B, “Resources
and Next Steps,” for websites that may be of
assistance.
The mail() function returns a value
(1 or 0) indicating its successful use. This
value indicates only whether PHP was able
to attempt to send the email (by using
whatever email system is in place). There’s
no easy way to use PHP to see whether an
email address is valid or whether the end user
received the message.
To send an email to multiple addresses,
either use the CC parameter or separate each
TO address with a comma.
To create new lines within the email
body, either create the message over multiple
lines or use the newline character (\n) within
double quotation marks.
If you want to send multiple headers in
addition to the From address, separate them
with a combination of \r\n:
mail ('email@example.com',
➝ 'Testing', $body, "From:
➝ email@example.org\r\nBcc:
➝ hidden@example.net,
➝ third@example.com");
Configuring Your Server to Send Email
Sending email with PHP is easy, as long as your web server (or computer) is set up to send email. If
you’re using a web hosting service or your own Unix computer (such as Linux), this shouldn’t be a
problem at all. If you do have a problem, contact the hosting company for support.
If you’re running your own server (for example, if you’re developing locally), the ability to send
email could be a sticking point. If you’re using an all-in-one installer, such as MAMP or XAMPP (see
Appendix A), it should also have an email server as part of the package. If you don’t receive the
email after registering, check the associated software’s documentation for what you may need to
do to enable email.
If you’re using a web server built into the operating system, such as Apache on Mac OS X, you may
already be set up to send email. To start, go ahead and try this example using a valid email address.
If you don’t receive the email, see Appendix A for information about getting mail() to work.
I’ll also add that I almost never worry about getting PHP on my own computer to send out emails
because I’ll never be running live websites from my computer. In other words, why waste time getting something to work that you’ll never end up using (whereas getting PHP to send out email on a
live server does matter)?
232
Chapter 8
Output Buffering
A handful of functions that you’ll use in this
chapter and the next can be called only
if nothing has been sent to the browser.
These functions include header(),
setcookie(), and session_start().
If you use them after the browser has
already received some text, HTML, or even
a blank space, you’ll get the dreaded
“headers already sent” error message A.
One solution that I recommend for beginning PHP developers is to make use of
output buffering (also named output
control). In a normal PHP script, any HTML
outside the PHP tags is immediately sent
to the browser. This is also true when any
print statement is executed. With output
buffering, the HTML and printed data—the
output—will instead be placed into a buffer
(that is, memory). At the end of the script,
the buffer will then be sent to the browser,
or if more appropriate, the buffer can be
cleared without being sent to the browser.
There are many reasons to use output
buffering, but for beginners, one benefit is
that you can use certain functions without
worrying about headers already sent
errors. Although you haven’t dealt with any
of the named functions yet, this chapter
introduces output buffering now. Using this
feature will greatly reduce errors when you
begin using headers (in the next section of
this chapter), cookies (in the next chapter),
and sessions (also in the next chapter).
To begin output buffering, invoke the
ob_start() function at the very top of
your page. Once you call it, every print
and similar function will send data to a
memory buffer rather than to the browser.
Conversely, HTTP calls, such as header()
and setcookie(), won’t be buffered and
will operate as usual. To be more explicit,
it must be invoked before any print
statements or any HTML gets sent to the
browser.
A If the browser receives any HTML prior to a header() call, you’ll see this error message.
Creating Web Applications
233
At the conclusion of the script, call the
ob_end_flush() function to send the
accumulated buffer to the browser. Or use
the ob_end_clean() function to delete
the buffered data without passing it along.
Both functions also turn off output buffering for that script. PHP automatically runs
ob_end_flush() at the conclusion of a
script if it isn’t otherwise done. But it’s still
a good idea to call it yourself.
From a programmer’s perspective, output
buffering allows you to structure a script
in a more linear form, without concern for
HTTP headers. Let’s remake header.html
and footer.html so that every page uses
output buffering. You won’t appreciate the
benefits yet, but the number of errors you
won’t see over the rest of this book will go
a long way toward preserving your programming sanity.
To use output buffering:
Script 8.11 Add output buffering to the web
application by calling the ob_start() function at
the top of the header.html script.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1. Open header.html (Script 8.7) in your
text editor or IDE.
18
19
20
2. At the very top of the page, before any
HTML code, add the following (Script
8.11):
21
22
23
24
25
26
27
Script 8.12 Output buffering is completed at the
end of the footer file using ob_end_flush(), which
sends the accumulated buffer to the browser.
1
2
3
4
5
19
20
4. At the end of the script, after all the
HTML, add the following (Script 8.12):
This code turns off output buffering
and sends the accumulated buffer to
the browser. In other words, all the
HTML is sent at this point.
continues on next page
6
9
10
11
12
13
14
15
16
The key to using output buffering is to
call the ob_start() function as early as
possible in a script. In this example, you
create a special section of PHP prior to
any HTML and call ob_start() there.
By turning on output buffering in your
header file and turning it off in your
footer file, you buffer every page in the
application.
Now print the date and time:
//
print date('g:i a l F j');
?>
Creating Web Applications
235
5. Save both files, and place them in the
templates directory of your PHPenabled server.
6. Test any page in your browser B.
As a reminder, PHP code can be placed
in a file with an .html extension—as in these
two examples here—if that file is being
included by a PHP script (such as index.php).
For some time now, output buffering has
been automatically enabled in PHP’s default
configuration. The code added in this section
of the chapter will work regardless of that
setting.
You can set the maximum buffer size
in php.ini (PHP’s configuration file). The
default is 4,096 bytes.
The ob_get_length() function returns
the length (in number of characters) of the current buffer contents.
The ob_get_contents() function
returns the current buffer so that it can be
assigned to a variable, should the need arise.
For example, you could take the accumulated
content and process it to add dynamic highlighting or text manipulation.
The ob_flush() function sends the
current contents of the buffer to the browser
and then discards them, allowing a new buffer
to be started. This function lets your scripts
maintain more moderate buffer sizes.
The ob_clean() function deletes the
current contents of the buffer without stopping the buffer process.
PHP automatically runs ob_end_flush()
at the conclusion of a script if it isn’t otherwise
done. But it’s still a good idea to call it yourself.
236 Chapter 8
B The site works the same as it did previously,
but it will be easier to work with when you use
HTTP headers in the next section of this chapter.
Manipulating
HTTP Headers
Most interactions between a server and
a browser (the client) take place over
HTTP (Hypertext Transfer Protocol). This is
why the addresses for pages begin with
http://. But HTTP communications between
browsers and servers go beyond just
sending HTML, images, and the like.
These additional communications can be
accomplished using HTTP headers. There
are dozens of uses for HTTP headers, all
of which you can do using PHP’s header()
function.
Perhaps the most common use of the
header() function is to redirect the user
from one page to another. To redirect the
user’s browser with PHP, you send a location header:
header('Location: page.php');
When using the header() function to
redirect the browser, follow that line by
calling exit() to cancel the execution of
the script (because the browser has been
redirected to another page):
If you don’t invoke exit(), the rest of the
script’s code will be executed, despite the
fact that the browser has moved on.
The most important thing to understand
about using header() is that the function
must be called before anything else is
sent to the browser—otherwise, you’ll see
the all-too-common headers already sent
error message (see A in the section “Output Buffering”). If your page receives any
HTML or even blank space, the header()
function won’t work.
Fortunately, you learned about output
buffering in the previous section. Because
output buffering is turned on in the application, nothing is sent to the browser until
the very last line of the footer script (when
ob_end_flush() is called). By using this
method, you can avoid the dreaded headers already sent error message.
To practice redirection, you’ll update the
login page to take the user to a welcome
page upon successful login.
header('Location: page.php');
exit();
Creating Web Applications
237
To use the header() function:
1. Open login.php in your text editor or
IDE (Script 8.8).
2. Delete the You are logged in… print
statement (Script 8.13).
Because the user is redirected to
another page, there’s no need to
include this message.
3. Where the print statement was, add
the following:
ob_end_clean();
header('Location: welcome.php');
exit();
The first line destroys the page buffer
(because the accumulated buffer won’t
be used). This isn’t strictly required but
is a good idea. The next line redirects
the user to welcome.php. The third line
terminates the execution of the rest of
the script.
Script 8.13 The new version of the login page
redirects the user to another page using the
header() function.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
4. Save the file, and place it in the proper
directory for your PHP-enabled server
(along with the other scripts from
this chapter).
17
18
Now you need to create the welcome.php
page to which the user will be redirected.
19
20
Login Form
Users who are logged in can take
advantage of certain features like
this, that, and the other thing.
';
// Check if the form has been submitted:
if ($_SERVER['REQUEST_METHOD'] ==
'POST') {
Handle the form:
//
if ( (!empty($_POST['email'])) &&
(!empty($_POST['password'])) ) {
( (strtolower($_POST['email'])
if
== 'me@example.com') && ($_
POST['password'] == 'testpass') )
{ // Correct!
21
Redirect the user to the
//
welcome page!
ob_end_clean();
// Destroy
22
header('Location: welcome.
23
24
25
26
27
exit();
the buffer!
php');
} else { // Incorrect!
print '
The submitted email
address and password do not
match those on file! Go
back and try again.
';
28
29
30
}
code continues on next page
238
Chapter 8
To write welcome.php:
Script 8.13 continued
31
32
33
34
35
36
37
38
39
} else { // Forgot a field.
print
'
Please make sure you enter both
an email address and a password!
Go back and try again.
';
}
} else { // Display the form.
print
'
';
40
41
42
43
44
45
46
47
48
}
include('templates/footer.html'); //
Need the footer.
?>
1. Begin a new PHP document in
your text editor or IDE, to be named
welcome.php (Script 8.14):
Welcome to the J.D. Salinger
➝ Fan Club!
You've successfully logged
➝ in and can now take advantage
➝ of everything the site has to
➝ offer.
4. Return to PHP, and include the footer:
continues on next page
Script 8.14 The welcome page greets users after
they’ve logged in.
1
2
3
4
5
6
7
8
9
10
11
code continues on next page
Creating Web Applications
239
5. Save the script as welcome.php, place
it in the same directory as the new version of login.php, and test it in your
browser A, B, and C.
The headers_sent() function returns
TRUE if the page has already received HTTP
headers and the header() function can’t be
used.
Script 8.14 continued
12
13
14
Using the GET method trick, you can
pass values from one page to another using
header():
$var = urlencode('Pass this text');
header("Location: page.php?
➝ message=$var");
The header() function should technically use a full path to the target page when
redirecting. For example, it should be
15
16
Welcome to the J.D. Salinger Fan
Club!
You've successfully logged in and
can now take advantage of everything the
site has to offer.
Lorem ipsum dolor sit amet,
consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
header('Location: http://
➝ www.example.com/welcome.php');
or
header('Location: http://localhost/
➝ welcome.php');
In my book PHP and MySQL for Dynamic
Web Sites: Visual QuickPro Guide, I show
some code for dynamically generating an
absolute URL based on the location of the current script.
A The login form…
B …and the redirection if the user properly
logged in.
240
Chapter 8
C If users don’t properly log in, they remain on
the login page.
Review and Pursue
If you have any problems with the
review questions or the pursue prompts,
turn to the book’s supporting forum
(www.LarryUllman.com/forums/).
Review
n
n
n
n
n
n
What is the difference between
include() and require()?
Why can you put PHP code into an
included file even when it uses an
.html extension?
What are the differences between relative and absolute references to a file?
How do you define a constant? Are
constant names case-sensitive or
case-insensitive? How do you check if
a constant has been defined?
What is the epoch? What is a
timestamp?
What is the significance of
$_SERVER['REQUEST_METHOD']?
n
n
n
How do you have a form element
“remember” previously submitted values?
How can you see a PHP error that
occurs within a form element (for
example, when presetting a form’s
element’s value)?
What does the headers already sent
error mean? How can it be prevented?
Creating Web Applications
241
Pursue
n
n
n
n
n
n
Create a new prototype design for
this chapter’s examples, and then
create new header and footer files.
View any of the site’s pages again (you
should not need to change any of the
PHP scripts).
Change the parameters to the date()
function in footer.html to display the
date and/or time in a different manner.
Rewrite the password conditionals
found in register.php as a nested pair
of conditionals. Hint: See Chapter 6 for
examples.
If you’re using PHP 5.2 or later, check
out the PHP manual pages for the
Filter extension. Then incorporate the
filter_var() function to validate the
email address in register.php.
Change the subject and body of the
email sent upon (pseudo-) registration
to something more interesting and
informative.
Update login.php so that it also shows
the form upon a failed login attempt.
242
Chapter 8
9
Cookies and
Sessions
Chapter 8, “Creating Web Applications,”
covered a number of techniques for developing more fully realized websites. One
missing piece—the focus of this chapter
—is how to maintain “state” as the user
traverses a multipage site. The Hypertext
Transfer Protocol (HTTP) is a stateless
technology, meaning that it has no built-in
method for tracking a user or remembering
data from one page of an application to the
next. This is a serious problem, because
e-commerce applications, user registration
and login systems, and other common online
services rely on being able to follow the
same user from page to page. Fortunately,
maintaining state is quite simple with PHP.
This chapter discusses the two primary
methods for tracking data: cookies and
sessions. You’ll start by learning how to
create, read, modify, and delete cookies.
Then you’ll see how easy it is to master
sessions, a more potent option for maintaining state.
In This Chapter
What Are Cookies?
244
Creating Cookies
246
Reading from Cookies
251
Adding Parameters to a Cookie
254
Deleting a Cookie
257
What Are Sessions?
260
Creating a Session
261
Accessing Session Variables
264
Deleting a Session
266
Review and Pursue
268
What Are Cookies?
Prior to the existence of cookies, traversing a website was a trip without a history.
Although the browser tracks the pages you
visit, allowing you to use the Back button
to return to previously visited pages and
indicating visited links in a different color,
the server does not follow what individual
users see and do. This is still true for sites
that don’t use cookies, as well as for users
who have disabled cookies in their web
browsers A.
A Most browsers let users set the cookie-
handling preferences. In Internet Explorer 11, you
will find this in the Advanced Privacy Settings area.
Debugging Cookies
When you begin working with cookies in PHP, you’ll need to know how to debug your cookierelated scripts when difficulties arise. Three areas might cause you problems:
.. Sending the cookie with PHP
.. Receiving the cookie in your browser
.. Accessing a cookie in a PHP script
The first and last issues can be debugged by printing out the variable values in your PHP scripts,
as you’ll soon learn. The second issue requires that you know how to work with cookies in your
browser. For debugging purposes, you’ll want your browser to notify you when a cookie is being
sent. This is an easy option in Internet Explorer and not readily available in the other browsers.
With Internet Explorer on Windows, you can do this by choosing Internet Options under the Tools
menu. Then click the Privacy tab, followed by the Advanced button under Settings. Click “Override
automatic cookie handling,” and then choose Prompt for both First-party and Third-party Cookies
(you can actually block the third-party cookies, if you’d rather). Other versions of Internet Explorer
may use different variations on this process. Internet Explorer also has a Developer Tools window
(linked under the Tools menu) that can be useful.
The current versions of Chrome, Opera, Firefox, and Safari no longer offer the ability to be
prompted when cookies are created, which is unfortunate. But you can view existing cookies
in any browser, normally by finding the cookies area (often under Privacy) within the browser’s
preferences or options.
A browser’s developer tools, or third-party extensions such as Firebug, will normally show existing
cookies for the site being viewed without you having to navigate through the browser settings. If
you’re not using Internet Explorer, you’ll want to find what developer tools or extensions are available for your browser of choice.
244
Chapter 9
Why is that a problem? If the server can’t
track a user, there can be no shopping
carts for making purchases online. If cookies didn’t exist (or if they’re disabled in the
browser), people wouldn’t be able to use
popular sites that require user registration. In short, without cookies, there would
be no Amazon or Facebook or any of the
other most popular or useful sites (not in
their current incarnations, at least).
PHP has solid support for cookies. In this
chapter, you’ll learn how to set a cookie,
retrieve information from a cookie, and
then delete the cookie. You’ll also see
some of the optional parameters you can
use to apply limits to a cookie’s existence.
Before moving on, you ought to know two
more things about cookies. The first is how
to debug cookie-related problems. You’ll
inevitably need to know how to do that,
so the topic is discussed in the sidebar
“Debugging Cookies.” The second is how
a cookie is transmitted and received B.
Cookies are stored in the browser, but
only the site that originally sent a cookie
can read it. Also, the cookies are read
by the site when the page on that site is
requested by the browser. In other words,
when the user enters a URL in the address
bar and clicks Go (or whatever), the site
reads any cookies it has access to and
then serves up the requested page. This
order is important because it dictates when
and how cookies can be accessed.
Cookies are simply a way for a server to
store information on the user’s computer.
By doing so, the server can remember the
user over the course of a visit or through
several visits. Think of a cookie as a name
tag: You tell the server your name, and it
gives you a name tag. Then it can know who
you are by referring back to the name tag.
This brings up another point about the
security issues involved with cookies.
Cookies have gotten a bad rap because
users believe cookies allow a server to
know too much about them. However, a
cookie can only be used to store information that you give it, so it’s as secure as
you want it to be (although to be fair, your
“giving” of information is normally not a
conscious choice).
The ability to send, read, and delete
cookies is one of the few overlaps between
server-side PHP and browser-side JavaScript.
Web Browser (client)
Server
1. URL Requ
est
ies and HTML
2. Cook
3. URL Request
HTML page
if(conn
SELEC
WHERE
print
PHP script
and Cookies
if(conn
SELEC
WHERE
print
PHP script
B How cookies are sent back and forth between the server
and the client.
Cookies and Sessions
245
Creating Cookies
An important thing to understand about
cookies is that they must be sent from
the server to the client prior to any other
information. This means a script should
send cookies before any print statement,
before including an external file that contains HTML, and so forth.
Should the server attempt to send a
cookie after the web browser has already
received HTML—even an extraneous white
space—an error message will result and
the cookie won’t be sent A. This is by far
the most common cookie-related error.
Cookies are sent using the setcookie()
function:
setcookie(name, value);
setcookie('CookieName', 'This is the
➝ cookie value.');
That line of code sends to the browser a
cookie with the name CookieName and the
value This is the cookie value. B.
You can continue to send more cookies to
the browser with subsequent uses of the
setcookie() function, although you’re
limited by the browser as to how many
cookies can be sent from the same site:
setcookie('name2', 'some value');
setcookie('name3', 'another value');
There’s no universal, hard limit as to how
many cookies a browser will accept from
one site, but you should keep the number
to a minimum.
Finally, when creating cookies, you can—as
you’ll see in this example—use a variable for
the name or value attribute of your cookies:
setcookie($cookie_name,
➝ $cookie_value);
A A message like this is what you’ll see if the setcookie() function is called after anything,
even a blank line or space, has already been sent to the browser.
B If the browser is set to prompt the user
for cookies, a message like this will appear
for each cookie sent. (Note that the window,
from Internet Explorer 11, shows the value
in a URL-encoded format.)
246
Chapter 9
C This form is used to select the font size
and color for use on another PHP page.
For an example of setting cookies, you’ll
create a script that allows the user to specify
the default font size and color for a page.
The page displays a form for choosing
these values C and then handles the form
submission D. A separate page, created
in the next section of this chapter, will use
these settings.
To send cookies:
1. Create a new PHP document in
your text editor or IDE, to be named
customize.php (Script 9.1):
Your settings have been
entered! Now see them in action.';
12
code continues on next page
The most critical issue with cookies is
that they’re created before anything is
sent to the browser. To accomplish this,
the script begins with a PHP section
that handles the sending of cookies.
Also be certain not to have any extraneous spaces or lines before the initial
PHP tag.
2. Check whether the form has been
submitted:
if (isset($_POST['font_size'],
➝ $_POST['font_color'])) {
This page will both display and handle
the form. It could use the same method
explained in the previous chapter—
checking if the $_SERVER['REQUEST_
METHOD'] variable has a value of POST,
but as an alternative approach, the
script will perform basic, minimal validation as the test for a form submission.
The conditional checks for the existence of two variables: $_POST['font_
size'] and $_POST['font_color'].
If both are set, the form submission will
be addressed.
continues on next page
Cookies and Sessions 247
3. Create the cookies:
setcookie('font_size',
➝ $_POST['font_size']);
setcookie('font_color',
➝ $_POST['font_color']);
These two lines create two separate
cookies. One is named font_size and
the other font_color. Their values
will be based on the selected values
from the HTML form, which are stored
in the $_POST['font_size'] and
$_POST['font_color'] variables.
In a more fully developed application,
you should first confirm that the variables have acceptable values.
4. Create a message and complete the
conditional and the PHP section:
$msg = '
Your settings have
➝ been entered! Now see them
➝
➝ in action.
';
} // End of submitted IF.
?>
When the form has been submitted,
the cookies will be sent and the $msg
variable will be assigned a string value.
This variable will be used later in the
script to print a message. This approach
is necessary; you can’t print the message
at this juncture because not even the
HTML head has been created.
5. Create the HTML head and opening
body tag:
Customize Your Settings
➝
248
Chapter 9
Script 9.1 continued
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
} // End of submitted IF.
?>
Customize Your Settings
Use this form to set your
preferences:
All this code must come after the
setcookie() lines. Not to overstate
this, but no text, HTML, or blank spaces
can be sent to the browser prior to the
setcookie() calls.
6. Create another PHP section to report
on the cookies being sent:
This code prints out a message if the
cookies have been sent. The first time
the user comes to the page, the cookies haven’t been sent, so $msg is not
set, making this conditional FALSE, and
this print invocation never runs. Once
the form has been submitted, $msg has
been set by this point, so this conditional
is TRUE D.
7. Begin the HTML form:
Use this form to set your
➝ preferences:
The HTML form itself is very simple C.
The user is given one drop-down menu
to select the font size. The value for
each corresponds to the CSS code
used to set the document’s font size:
from xx-small to xx-large.
Because this script both displays and
handles the form, the form’s action
attribute points to the same file.
8. Complete the HTML form:
The second drop-down menu is used to
select the font color. The menu displays
the colors in text form, but the values
are HTML color values. Normally such
values are written using six characters plus a pound sign (for example,
#00cc00), but CSS allows you to use
just a three-character version, and the
pound sign will be added on the page
that uses these values.
continues on next page
Cookies and Sessions
249
9. Complete the HTML page:
10. Save the file as customize.php, and
place it in the proper directory for your
PHP-enabled server.
11. Make sure you’ve set your browser to
prompt for each cookie, if possible.
To guarantee that the script is working,
you want the browser to prompt you
for each cookie, if you can. See the
“Debugging Cookies” sidebar.
12. Run the script in your browser E
and F.
Cookies are one of the few areas in PHP
that can behave differently from browser to
browser or operating system to operating
system. You should test your cookie-based
applications on as many browsers and operating systems as you can.
E The user sees this message when the first
setcookie() call is made, if they’ve opted to be
prompted before accepting a cookie. This cookie
is storing the value of x-large in a cookie named
font_size.
If you use the output buffering technique
taught in Chapter 8, then you can place your
setcookie() calls anywhere within the script
(because the browser won’t receive the data
until the ob_end_flush() function is called).
Cookies are limited to approximately
4 KB of total data. This is more than sufficient
for most applications.
To test whether it’s safe to send a cookie,
use the headers_sent() function. It reports
on whether HTTP headers have already been
sent to the web browser.
250
Chapter 9
F The Chrome Developer Tools shows the
cookies received by the browser. The second
cookie that’s sent by the PHP script is named
font_color and has a value of c00, representing
the color gray.
Script 9.2 This script sets the font size and color in
CSS, using the values stored in the cookies.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
View Your Settings
yadda yadda yadda yadda yadda
yadda yadda yadda yadda yadda
yadda yadda yadda yadda yadda
yadda yadda yadda yadda yadda
yadda yadda yadda yadda yadda
Reading from Cookies
Just as form data is stored in the $_POST
array (assuming it used the POST method)
and values passed to a script in the
URL are stored in the $_GET array, the
setcookie() function places cookie data
in the $_COOKIE array. To retrieve a value
from a cookie, you only need to refer to
the cookie name as the index of this array.
For example, to retrieve the value of the
cookie established with the line
setcookie('user', 'trout');
you would use the variable
$_COOKIE['user'].
Unless you change the cookie’s parameters
(as you’ll see later in this chapter), the
cookie will automatically be accessible to
every other page in your web application.
You should understand, however, that a
cookie is never accessible to a script immediately after it’s been sent. You can’t do this:
setcookie('user', 'trout');
print $_COOKIE['user']; // No value.
The reason for this is the order in which
cookies are read and sent (see B in the
first section of this chapter).
To see how simple it is to access cookie
values, let’s write a script that uses the
preferences set in customize.php to
specify the page’s text size and color. The
script relies on CSS to achieve this effect.
To retrieve cookie data with PHP:
1. Begin a new PHP document in your
text editor or IDE, to be named
view_settings.php (Script 9.2):
continues on next page
Cookies and Sessions
251
View Your Settings
➝
2. Start the CSS section:
7. Start the HTML body, and create links to
two other pages:
These two links take the user to
two other PHP pages. The first,
customize.php, has already been
written and lets users define their settings. The second, reset.php, will be
written later in the chapter and lets
users delete their customized settings.
8. Add some text:
A This page reflects the customized font
choices made using the other PHP script.
yadda yadda yadda yadda yadda
yadda yadda yadda yadda yadda
yadda yadda yadda yadda yadda
yadda yadda yadda yadda yadda
yadda yadda yadda yadda yadda
This text exists simply to show the
effects of the cookie changes.
9. Complete the HTML page:
10. Save the file as view_settings.php,
place it in the same directory as
customize.php, and test it in your
browser A by clicking the link on
customize.php.
11. View the source of the page to see the
resulting CSS code B.
B By viewing the source code of the page, you
can also track how the CSS values change.
12. Use the customize page to change your
settings and return to this script.
Each submission of the form will create
two new cookies storing the form values,
thereby replacing the existing cookies.
The value of a cookie is automatically
encoded when it’s sent and decoded on being
received by the PHP page. The same is true of
values sent by HTML forms.
Cookies and Sessions
253
Adding Parameters
to a Cookie
one hour (60 seconds times 60 minutes)
from the current moment:
Although passing just the name and value
arguments to the setcookie() function will
suffice for most of your cookie uses, you
ought to be aware of the other arguments
available. The function can take up to five
more parameters, each of which limits the
operation of the cookie:
Because the expiration time will be calculated as the value of time() plus 3600,
that argument isn’t put in quotes (you don’t
want to literally pass time() + 3600 as
the expiration but rather the result of that
calculation).
setcookie(name, value, expiration,
➝ path, domain, secure, httponly);
The expiration argument is used to set a
specific length of time for a cookie to exist.
If it isn’t specified, the cookie will continue
to be functional until the user closes the
browser. Normally, you set the expiration
time by adding a particular number of
minutes or hours to the current time. You
can find the current time in PHP by using
the time() function (it returns a timestamp;
see Chapter 8). Therefore, this line of code
sets the expiration time of the cookie to be
setcookie(name, value, time()+3600);
The path and domain arguments are used
to limit a cookie to a specific folder in a
website—the path—or to a specific domain.
Using the path option, you could limit a
cookie to exist only while a user is in a
specific subfolder of the domain:
setcookie(name, value, time()+3600,
➝ '/subfolder/');
Cookies are already specific to a domain,
so the domain argument might be used
to limit a cookie to a subdomain, such as
forum.example.com:
setcookie(name, value, time()+3600, '',
➝ 'forum.example.com');
Script 9.3 When you add the expiration arguments to the two cookies, the cookies will persist even after
users have closed out of and later returned to their browser.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Your settings have been entered! Now see them in
action.';
} // End of submitted IF.
?>
code continues on next page
254
Chapter 9
Script 9.3 continued
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
Customize Your Settings
Use this form to set your
preferences:
The secure value dictates that a cookie
should only be sent over a secure HTTPS
connection. A value of 1 indicates that a
secure connection must be used, whereas
0 indicates that a secure connection isn’t
necessary. You could ensure a secure
cookie transmission for e-commerce sites:
setcookie('cart', '82ABC3012',
➝ time()+3600, '',
➝ 'shop.example.com', 1);
As with all functions that take arguments,
you must pass all the values in order. In the
preceding example, if there’s no need to
specify (or limit) the path, you use empty
quotes. With the path argument, you can
also use a single slash (/) to indicate the
root folder (i.e., no path restriction). By
doing so, you maintain the proper number
of arguments and can still indicate that an
HTTPS connection is necessary.
The final argument—httponly—was added
in PHP 5.2. It can be used to restrict access
to the cookie (for example, preventing a
cookie from being read using JavaScript)
but isn’t supported by all browsers.
Let’s add an expiration date to the existing
customize.php page so that users’ preferences will remain even after they’ve closed
their browser and then returned to the
site later.
To set a cookie’s expiration date:
1. Open customize.php (Script 9.1) in your
text editor or IDE.
2. Change the two setcookie() lines to
read as follows (Script 9.3):
setcookie('font_size', $_POST
➝ ['font_size'], time()+10000000,
➝ '/', '', 0);
continues on next page
Cookies and Sessions
255
setcookie('font_color', $_POST
➝ ['font_color'], time()
➝ +10000000, '/', '', 0);
To make these cookies persist for a
long time (specifically, for a couple of
months), set the expiration time to be
10,000,000 seconds from now. While
you’re at it, set the path argument to the
root of the site (/). Doing so may improve
the consistency of sending these cookies across the various browsers.
Because the expiration date of the
cookies is set months into the future,
the user’s preferences, which are
stored in the cookies, will be valid even
after the user has closed and reopened
the browser. Without this expiration date,
users would see the default font size and
color and have to reassign their preferences with every new browser session.
3. Save the file, place it in the proper directory for your PHP-enabled server, and
test it again in your browser A and B.
Not all browsers acknowledge a cookie’s
adjusted expiration time when the cookie is
being sent from your own computer (i.e., from
localhost). More generally, browsers can be
inconsistent in how they handle local cookies.
Here are some general guidelines for
what kind of expiration date to use with your
cookies: If the cookie should last as long
as the user browses through the site, don’t
set an expiration time. If the cookie should
continue to exist after the user has closed and
reopened the browser, set an expiration time
that’s weeks or months in the future. And if
the cookie can constitute a security risk, set an
expiration time of an hour or a fraction thereof
so that the cookie doesn’t continue to exist
too long after a user has left the browser.
For security purposes, you can set a
5- or 10-minute expiration time on a cookie
and have the cookie re-sent with every new
page the user visits. This way, the cookie will
continue to persist as long as the user is active
but will automatically expire 5 or 10 minutes
after the user’s last action.
A The browser’s cookie reporting tools (here, Chrome’s Developer Tools) now reflect
the cookie expiration dates.
B The new cookie parameters don’t
adversely affect the functionality of
the application.
256 Chapter 9
Deleting a Cookie
A How Firefox Developer Edition displays the
cookie information when a deletion cookie is sent.
The final thing to know about cookies is
how to delete them. Although a cookie
automatically expires when the user’s
browser is closed or when the expiration
date/time is met, sometimes you’ll want
to manually delete the cookie as well. For
example, websites that have registered
users and login capabilities delete any
created cookies when the user logs out.
The setcookie() function can take up to
seven arguments, but only one is required—
the name. If you send a cookie that consists
of a name without a value, it will have the
same effect as deleting the existing cookie
of the same name. For example, to create
the cookie username, you use this line:
setcookie('username', 'Larry');
To delete the username cookie, you code
setcookie('username', '');
or
setcookie('username', FALSE);
As an added precaution, you can also set
an expiration date that’s in the past A:
setcookie('username', FALSE,
➝ time() - 6000);
The only caveat when it comes to deleting
a cookie is that you must use the same
argument values that were used to set
the cookie in the first place, aside from
the value and expiration. For example, if
you set a cookie while providing a domain
value, you must also provide that value
when deleting the cookie:
setcookie('user', 'larry',
➝ time() + 3600, '',
➝ 'forums.example.com');
setcookie('user', '', time() - 600,
➝ '', 'forums.example.com');
continues on next page
Cookies and Sessions 257
To demonstrate this feature, let’s add a
reset page to the web application. This
PHP script will destroy the sent cookies so
that the user’s preferences are forgotten.
1. Begin a new PHP script in your text
editor or IDE, to be named reset.php
(Script 9.4):
These two lines send cookies named
font_size and font_color, each with
no value and an expiration time of more
than an hour ago. As you did when
creating cookies, you must call the
setcookie() function before anything
else is sent to the browser.
3. Create the HTML head:
Reset Your Settings
➝
258
Chapter 9
Script 9.4 To delete the existing cookies, send
new cookies with the same names, empty values,
and expirations in the past.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Reset Your Settings
Your settings have been reset!
Feel free to customize them again.
4. Add the page’s body:
Your settings have been reset!
➝ Feel free to customize
➝ them again.
B When the setcookie() function is used with
a name but no value, the existing cookie of that
name is deleted. The expiration date in the past
also guarantees proper destruction of the existing
cookie.
The body of this script merely tells
users that their settings have been
reset. A link is then provided to return
to the main page.
5. Complete the HTML:
6. Save the page as reset.php, place it
in the proper directory for your PHPenabled server, and test it in your
browser B, C, and D.
C The reset page sends two blank cookies and
then displays this message.
To test this page, either click the appropriate link in view_settings.php (Script
9.2) or just go to this page directly.
Just as creating a cookie doesn’t take
effect until another page is visited, deleting a
cookie doesn’t take effect until another page
is visited. In other words, you can delete a
cookie on a page but still access that cookie
on it (because the cookie was received by the
page before the delete cookie was sent).
D After accessing the reset page, PHP destroys
the cookies B, which will have the effect of
resetting the view_settings.php page to its
default formatting.
Just as creating cookies has mixed results
using different browsers, the same applies
to deleting them. Test your scripts on many
browsers and play with the setcookie() settings to ensure the best all-around compatibility.
Just as one example of how different
browsers handle cookies, Firefox Developer
Edition treats any cookie that expires in the
past as having an expiration just after the
epoch B.
Cookies and Sessions
259
What Are Sessions?
A session, like a cookie, provides a way
for you to track data for a user over a
series of pages. The difference between
the two—and this is significant—is that a
cookie stores the data on the client (in
the browser), whereas the session data is
stored on the server. Because of this difference, sessions have numerous benefits
over cookies:
n
n
n
n
Sessions are generally more secure,
because the data isn’t transmitted
back and forth between the client and
server repeatedly.
Sessions allow you to store more information than you can in a cookie.
Sessions can be made to work even
if the user doesn’t accept cookies in
their browser.
You can more easily store other types
of data in sessions, such as arrays
and Booleans.
When you start a session, PHP generates a
random session ID. Each user’s session will
have its own session ID, corresponding to
the name of the text file on the server that
stores the user’s session data (Script 9.5).
So that every PHP script on a site can associate the same session data with a particular user, the session ID must be tracked as
well. By default, this session ID is sent to
the browser as a cookie A. Subsequent
PHP pages will use this cookie to retrieve
the session ID and access the session
information.
Over the next few pages, you’ll see just
how easy sessions are to work with in PHP.
260
Chapter 9
A A session cookie being sent to the browser.
Script 9.5 How session data is stored in a file on
the server.
1
email|s:14:"me@example.
com";loggedin|i:1292883103;
Choosing Between Sessions
and Cookies
Sessions have many benefits over cookies, but there are still reasons why you
would use the latter. Cookies have these
advantages over sessions:
.. Marginally easier to create and retrieve
.. Require slightly less work from the
server
.. Normally persist over a longer period
of time
As a rule of thumb, you should use cookies in situations where security is less of
an issue and only a minimum of data is
being stored. If security’s a concern and
there will be oodles of information to
remember, you’re best off with sessions.
Understand, though, that using sessions
may require a little more effort in writing
your scripts.
Creating a Session
Creating, accessing, or deleting a session
begins with the session_start() function.
This function will attempt to send a cookie
the first time a session is started, so it
absolutely must be called prior to any HTML
or white space being sent to the browser.
Therefore, on pages that use sessions, you
should call the session_start() function
as one of the very first lines in your script:
Login Form
Users who are logged in can take
advantage of certain features like
this, that, and the other thing.
';
// Check if the form has been submitted:
if ($_SERVER['REQUEST_METHOD'] ==
'POST') {
Handle the form:
//
if ( (!empty($_POST['email'])) &&
(!empty($_POST['password'])) ) {
( (strtolower($_POST['email'])
if
== 'me@example.com') && ($_
POST['password'] == 'testpass') )
{ // Correct!
// Do session stuff:
session_start();
$_SESSION['email'] =
$_POST['email'];
$_SESSION['loggedin'] =
time();
Redirect the user to the
//
welcome page!
ob_end_clean(); // Destroy the
buffer!
header ('Location: welcome.
php');
exit();
} else { // Incorrect!
code continues on next page
262
Chapter 9
Script 9.6 continued
33
print
'
The submitted email
address and password do not
match those on file! Go
back and try again.
Please make sure you
enter both an email address and
a password! Go back and try
again.
';
}
} else { // Display the form.
print
'
';
46
47
48
49
50
51
52
53
54
}
include('templates/footer.html'); //
Need the footer.
?>
4. Load the form in your browser to ensure
that it has no errors A.
Don’t complete and submit the login
form yet, because the welcome page
needs to be updated prior to logging in.
The php.ini configuration file includes
many session-related settings that you can
tinker with if you have administrative-level
control over your server. Open the php.ini
file in a text editor and see the manual for
more information.
You can also alter some of the session
settings using the ini_set() function.
The session_name() function lets you
change the name of the session (instead of
using the default PHPSESSID). It must be used
before every session_start() call, like so:
session_name('YourVisit');
session_start();
The session_set_cookie_params()
function alters the session cookie settings,
such as the expiration time, the path, and the
domain.
The constant SID, short for Session ID,
stores a string in the format name=ID.
An example is PHPSESSID=
mo7puk861tm60tbm4b8coh0og2.
You can store any type of value—number,
string, array, or object—or any combination
thereof in your sessions.
A The login form.
Cookies and Sessions
263
Accessing Session
Variables
Now that you’ve stored values in a session,
you need to know how to access them. The
first step is to invoke the session_start()
function. This is necessary on every page
that will make use of sessions, whether it’s
creating a new session or accessing an
existing one.
From there it’s simply a matter of referencing the $_SESSION variable as you would
any other array. With this in mind, you’ll
write another welcome page—similar to
the one from Chapter 8—that accesses the
stored email and loggedin values.
Script 9.7 You can access stored session values
using the $_SESSION array, as long as your script
uses session_start() first.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
To access session variables:
1. Create a new PHP document in
your text editor or IDE, to be named
welcome.php (Script 9.7):
Welcome to the J.D. Salinger
Fan Club!';
print '
Hello, ' . $_
SESSION['email'] . '!
';
// Print how long they've been logged
in:
date_default_timezone_set('America/
New_York');
print '
You have been logged
in since: ' . date('g:i a', $_
SESSION['loggedin']) . '.
';
include('templates/footer.html'); //
Need the footer.
?>
4. Greet the user by email address:
print '
Welcome to the J.D.
➝ Salinger Fan Club!
';
print '
Hello, ' . $_SESSION
➝ ['email'] . '!
';
To access the stored user’s address,
refer to $_SESSION['email']. Here,
that value is concatenated to the rest of
the string that’s being printed out.
5. Show how long the user has been
logged in:
date_default_timezone_set
➝ ('America/New_York');
print '
You have been logged
➝ in since: ' . date('g:i a',
➝ $_SESSION['loggedin']) .
➝ '.
';
Show how long the user has been
logged in, by referring to the
$_SESSION['loggedin'] variable.
By using this as the second argument
sent to the date() function, along with
the appropriate formatting parameters,
you make the PHP script create text
like 11:22 pm.
Before using the date() function, you
need to set the default time zone (this
is also discussed in Chapter 8). If you
want, after setting the time zone here,
you can remove the use of the same
function from the footer file.
6. Complete the content:
print '
';
The next script will provide logout functionality, so a link to it is added here.
7. Include the HTML footer, and complete
the HTML page:
include('templates/footer.html');
?>
8. Save the file as welcome.php, place it
in the proper directory for your PHPenabled server, and test it (starting
with login.php, Script 9.6) in your
browser A.
To see whether a particular session variable exists, use isset($_SESSION['var'])
as you would to check if any other variable is
set.
A more secure version of this script
would both check that the variables exist (in
the session) before referring to them and
run the values through an escaping function
before printing them.
Always remember that the data stored in a
session is being stored as plain text in an openly
readable text file. Don’t be cavalier about what
gets stored in a session, and never store sensitive information, such as credit card data, there.
For added security, data can be encrypted
prior to storing it in a session and decrypted
upon retrieval. Doing so requires a cryptography
library and more advanced PHP knowledge,
however.
A After successfully logging in (using
me@example.com and testpass in
the form), the user is redirected to this
page, which greets them using the
session values.
Cookies and Sessions
265
Deleting a Session
It’s important to know how to delete a session, just as it’s important to know how to
delete a cookie: Eventually you’ll want to
get rid of the data you’ve stored. Session
data exists in two places—in an array during the execution of the script and in a text
file—so you’ll need to delete both. But first
you must begin with the session_start()
function, as always:
session_start();
Then, you clear the session variables by
resetting the $_SESSION array:
$_SESSION = []; // Or = array();
Finally, remove the session data from the
server (where it’s stored in temporary files).
To do this, use
session_destroy();
With that in mind, let’s write logout.php,
which will delete the session, effectively
logging out the user.
To delete a session:
1. Start a new PHP script in your text
editor or IDE, to be named logout.php
(Script 9.8).
Welcome to the J.D. Salinger Fan
Club!
You are now logged out.
Thank you for using this site. We
hope that you liked it.
Blah, blah, blah...
Blah, blah, blah...
this function call to $_SESSION, all the
existing key-value pairs in $_SESSION
will be erased.
A The logout page destroys the session data.
4. Destroy the session data on the server:
session_destroy();
This step tells PHP to remove the actual
session file on the server.
5. Include the HTML header, and complete
this PHP section:
define('TITLE', 'Logout');
include('templates/header.html');
?>
6. Make the page content:
Welcome to the J.D. Salinger
➝ Fan Club!
You are now logged out.
Thank you for using this site.
➝ We hope that you liked it.
Blah, blah, blah...
Blah, blah, blah...
7. Include the HTML footer:
8. Save the file as logout.php, place it
in the proper directory for your PHPenabled server, and test it in your
browser by clicking the link in
welcome.php A.
To delete an individual session value, use
unset($_SESSION['var']);
An additional step would be to delete the
session cookie too.
The PHP module on the server will automatically perform garbage collection based on
settings in its configuration. PHP uses garbage
collection to manually delete session files from
the server, with the assumption that they’re no
longer needed.
Cookies and Sessions 267
Review and Pursue
n
If you have any problems with the review
questions or the pursue prompts, turn
to the book’s supporting forum
(www.LarryUllman.com/forums/).
Review
n
n
n
n
n
n
Where does a cookie store data?
Where does a session store data?
Which is generally more secure?
Name two debugging techniques when
trying to solve issues involving cookies.
How do the path and domain arguments
to the setcookie() function affect the
accessibility of the cookie?
How do you delete a cookie?
n
n
n
What function must every page call if it
needs to assign or access session data?
Why do sessions also use cookies
(by default)?
Pursue
n
n
n
Make sure you know what developer
tools exist for your browser of choice,
and how to basically use them.
Look up the PHP manual page for the
setcookie() function. Review the
information and user comments there
for added instructions on cookies.
268
Chapter 9
n
Rewrite customize.php so that the
script also applies the user’s preferences. Hint: You need to take into
account the fact that the cookies aren’t
available immediately after they’ve
been set. Instead, you would write the
CSS code using the $_POST values
after the form has been submitted, the
$_COOKIE values upon first arriving at
the page (if the cookies exist), and the
default values otherwise.
Make the form in customize.php
sticky so that it reflects the user’s
current choices.
Rewrite welcome.php so that the print
statement that greets the user by email
address uses double quotation marks.
For an added challenge, rewrite
welcome.php so that the print statement that indicates how long the user
has been logged in also uses double
quotation marks. Hint: You’ll need to
use a variable.
Update welcome.php so that it confirms a session variable exists before it
attempts to use it. Also run the session
values through an escaping function—
see Chapter 5, “Using Strings”—to
prevent XSS attacks.
Rewrite the last three scripts so that the
session uses a custom name.
10
Creating
Functions
Throughout this book, you’ve used dozens
of functions that provide much-needed
functionality, such as date(), setcookie(),
and number_format(). Although those
functions have already been defined by PHP,
here you’ll be creating your own. However,
functions you’ve created and those built
into PHP are used in the same manner.
Defining your own functions can save
you oodles of time as a programmer.
In fact, they constitute a big step in the
process of creating web applications and
building a solid library of PHP code to use
in future projects.
In this chapter, you’ll see how to write your
own functions that perform specific tasks.
After that, you’ll learn how to pass information to a function, use default values
in a function, and have a function return a
value. You’ll also learn how functions and
variables work together.
In This Chapter
Creating and Using Simple Functions
270
Creating and Calling Functions
That Take Arguments
276
Setting Default Argument Values
282
Creating and Using Functions
That Return a Value
285
Understanding Variable Scope
290
Review and Pursue
296
Creating and Using
Simple Functions
As you program, you’ll discover that you
use certain sections of code frequently,
either within a single script or over the
course of several scripts. Placing these
routines into a self-defined function can
save you time and make your programming easier, especially as your websites
become more complex. Once you create
a function, the actions of that function take
place each time the function is called, just
as print sends text to the browser with
each use.
The syntax for creating a user-defined
function is
function function_name() {
statement(s);
}
For example:
function whatever() {
print
'whatever';
}
You can use roughly the same naming
conventions for functions as you do for
variables, just without the initial dollar sign.
Second to that is the suggestion that you
create meaningful function names, just as
you ought to write representative variable
names. For example, create_header would
be a better function name than function1.
Remember not to use spaces in the name,
though—doing so constitutes two separate
words for the function name, which will
result in error messages. The underscore is
a logical replacement for the space. Unlike
variables, function names in PHP are not
case-sensitive, but you should still stick
with a consistent naming scheme.
270 Chapter 10
Any valid PHP code can go within the
statement(s) area of the function, including
calls to other functions. Functions do not
have a limit on the number of statements
they can contain, but make sure you end
each statement with a semicolon, just as
you would within the rest of the PHP script.
Functions can also contain any combination
of control structures: conditionals and loops.
A These pull-down menus are created
by a user-defined PHP function.
The exact formatting of a function isn’t
important as long as the requisite elements
are there. These elements include the
word function, the function’s name, the
opening and closing parentheses, the opening and closing braces, and the statement(s).
It’s conventional to indent a function’s
statement(s) from the function keyword
line, for clarity’s sake, as you would with
a loop or conditional. In any case, select
a format style that you like—which is both
syntactically correct and logically sound—
and stick to it.
You call (or invoke) the function by referring to it just as you do any built-in function.
The line of code
whatever();
will cause the statement part of the previously defined function—the print command
—to be executed.
Let’s begin by creating a function that
generates month, day, and year pull-down
menus for a form A.
Creating Functions
271
To create and call a basic function:
1. Start a new PHP document in your text
editor or IDE, to be named menus.php
(Script 10.1):
Date Menus
2. Begin the PHP section:
'January',
➝ 'February', 'March', 'April',
➝ 'May', 'June', 'July',
➝ 'August', 'September',
➝ 'October', 'November',
➝ 'December'];
// Make the month pull-down menu:
print '';
foreach ($months as $key =>
➝ $value) {
print "\n";
}
print '';
To generate a list of months, first create
an array of the month names, indexed
numerically, beginning at 1 for January.
When you specify the index for the first
array element, the others will follow
sequentially without the need to be
explicit in naming them.
272
Chapter 10
After the array has been created, the
initial select tag is printed out. Then, a
foreach loop runs through the $months
array. For each element in the array, the
HTML option tag is printed, using each
element’s key (the numbers 1 through 12)
as the option value and each element’s
value (January through December) as
the displayed text. Each line is also
preceded by a newline character (\n)
so that each option starts on its own
line within the HTML source.
5. Create the day pull-down menu:
print '';
for ($day = 1; $day <= 31;
➝ $day++) {
print
"\n";
}
print '';
The day menu is a lot easier to create.
To do so, use a simple for loop, running
through the numbers 1 through 31.
6. Create the year pull-down menu:
print '';
$start_year = date('Y');
for ($y = $start_year; $y <=
➝ ($start_year + 10); $y++) {
print
"\n";
}
print '';
To create the year pull-down menu,
start by using the date() function to
get the current year. Then create
options for this year plus the next 10,
using a for loop.
continues on page 274
Script 10.1 The function defined in this script creates three pull-down menus for a form.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Date Menus
'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
'September', 'October', 'November', 'December'];
// Make the month pull-down menu:
print '';
foreach ($months as $key => $value) {
print "\n";
}
print '';
// Make the day pull-down menu:
print '';
for ($day = 1; $day <= 31; $day++) {
print "\n";
}
print '';
// Make the year pull-down menu:
print '';
$start_year = date('Y');
for ($y = $start_year; $y <= ($start_year + 10); $y++) {
print "\n";
}
print '';
} // End of make_date_menus() function.
// Make the form:
print '
';
make_date_menus();
print '
';
?>
Creating Functions
273
7. Close the function:
} // End of make_date_menus()
➝ function.
When you’re creating functions, it’s
easy to create parse errors by forgetting the closing brace. You may want to
add comments to help you remember
this final step.
8. Make the form tags, and call the
function:
print '
';
make_date_menus();
print '
';
The print statements are used to
create the HTML form tags. Without a
form, the date pull-down menus won’t
appear properly in the script.
Once you’ve created your function, you
simply have to call it by name—being
careful to use the exact spelling—to make
the function work. Be sure to include
the parentheses as well.
9. Complete the PHP and HTML:
?>
10. Save the file as menus.php, place it
in the proper directory for your PHPenabled server, and run it in your
browser A.
11. If you want, check out the HTML source
of the page to see what was dynamically generated B.
B The source of the page shows the HTML created by the print
statements in the make_date_menus() function.
274
Chapter 10
If you see a “Call to undefined function:
some_function…” error message, it means
you’re trying to call a function that doesn’t
exist C. If you’re trying to call a PHP function, either you misspelled the name or it’s
not supported on your version of PHP. Check
the PHP manual for more. If you’re calling a
user-defined function when you see this error,
either it hasn’t been defined or you’ve misspelled it. Recheck your spelling in both the
definition of the function and its usage to see
if you made a mistake.
The function_exists() function
returns TRUE or FALSE based on whether a
function exists in PHP. This applies to both
user-defined functions and those that can be
built into PHP:
if (function_exists
➝ ('some_function')){ ...
Although you aren’t required to, I recommend that you habitually define your functions
at the beginning of a script (or in an included
file), rather than at the end of the script.
Some people prefer this syntax for laying
out their functions:
function function_name()
{
statement(s);
}
User-defined functions add extra
memory requirements to your PHP scripts, so
you should be judicious in using them. If you
find that your function merely calls another
PHP function or has but one line of code, it’s
probably not the best use of this capability.
C This error means that the PHP script does not have access to a function defined under the given
name. In this case, the problem is due to a missing “s” in the function call: make_date_menus() versus
make_date_menu().
Creating Functions
275
Creating and Calling
Functions That
Take Arguments
Although being able to create a simple
function is useful, writing one that takes
input and does something with that input is
even better. The input passed to a function
is known as an argument. This is a concept
you’ve seen before: The sort() function
takes an array as an argument, which the
function then sorts.
The syntax for writing functions that take
arguments is as follows:
function function_name
➝ ($arg1,$arg2, ...) {
statement(s);
}
The function is defined with parameters:
variables that are assigned the values sent
to the function when you call it. The variables are defined using the same naming
rules as any other variable in PHP:
function make_full_name($first,
➝ $last) {
print
$first . ' ' . $last;
}
Functions that take input are called much
like those that don’t—you just need to
remember to pass along the necessary
values. You can do this either by passing
variables:
make_full_name($fn, $ln);
or by sending literal values, as in
make_full_name('Larry', 'Ullman');
or some combination thereof:
make_full_name('Larry', $ln);
276
Chapter 10
The important thing to note is that arguments
are passed quite literally: The first variable
in the function definition is assigned the
first value in the call line, the second function variable is assigned the second call
value, and so forth A. Functions aren’t
smart enough to intuitively understand how
you meant the values to be associated.
This is also true if you fail to pass a value,
in which case the function will assume that
value is null (null isn’t the mathematical 0,
which is actually a value, but closer to the
idea of the word nothing). The same thing
applies if a function takes two arguments
and you pass one—the second will be null,
which might create an error B.
(To clarify a minor point, the variables in the
function definition are known as parameters; the values passed to the function
when invoked are known as arguments.
That being said, it’s common enough to
use the terms interchangeably.)
To demonstrate functions that take arguments, let’s create a more interesting
example. In Chapter 8, “Creating Web
Applications,” you learned how to make
forms “sticky”: having them remember their
values from previous submissions. The
code for a sticky text input might be
First Name:
continues on next page
function make_full_name($first, $last) {
print $first . ' ' . $last;
}
make_full_name($fn, $ln);
make_full_name('Larry', 'Ullman');
make_full_name('Larry', $ln);
A How values in function calls are assigned to function
arguments.
B As with any function (user-defined or built into PHP), passing an incorrect number of arguments when
calling it yields warnings.
Creating Functions
277
Since many forms, such as register.php
from Chapter 8, repeatedly use similar
code, you have a good candidate for a
user-defined function.
This next script will define and call a function that creates sticky text inputs. The
function will take one argument for the
input’s name, and another for the input’s
label (its textual prompt). The function will
be called multiple times by the script to
generate multiple inputs C. Upon form
submission, the previously entered values
will be remembered D.
C These three form inputs are created
by a user-defined function.
To create and call a function
that takes an argument:
1. Start a new PHP document in your
text editor or IDE, to be named
sticky1.php (Script 10.2):
Sticky Text Inputs
➝
2. Begin the PHP section:
Sticky Text Inputs
';
} // End of make_text_input() function.
// Make the form:
print '
';
// Create some text inputs:
make_text_input('first_name', 'First Name');
make_text_input('last_name', 'Last Name');
make_text_input('email', 'Email Address');
print '
';
?>
Creating Functions
279
4. Print an opening paragraph and a
label tag:
print '';
} // End of make_text_input()
➝ function.
8. Make the form tags, and call the
function:
print '
';
make_text_input('first_name',
➝ 'First Name');
It’s important that the form uses the
POST method, because the function
checks for existing values in $_POST.
You can actually omit an action value,
in which case the form will automatically
be submitted back to the same page.
To create a “first name” input, call the
make_text_input() function, passing it
the name the input should have and an
appropriate label.
9. Create two more inputs:
make_text_input('last_name',
➝ 'Last Name');
make_text_input('email', 'Email
➝ Address');
Now the script has used the same
function three times, in three different
ways. The result will be three distinct
text inputs.
Note that although HTML5 has an email
input type, for the sake of simplicity,
only plain text inputs are being created.
10. Complete the form:
print '
';
The form needs a submit button in
order to test the sticky feature.
Declaring Parameter Types
PHP 7 supports the ability to declare
parameter types to indicate what kind of
value must be passed. To use this feature,
provide the type—bool, float, int, or
string—before the parameter name:
function make_full_name(string
➝ $first, string $last) {
With that code in place, PHP will return
an error if the function is called while provided with non-string arguments:
make_full_name(12, true);
➝ // Error!
Earlier versions of PHP supported type
hinting, which was similar but did not
support scalar variable types such as
string and int. This type of stricter
function definition is best when you want
to guarantee the type of value passed to
a function.
11. Complete the PHP and HTML:
?>
12. Save the file as sticky1.php, place it
in the proper directory for your PHPenabled server, and run it in your
browser C and D.
You can define as many functions as you
want, not just one per script as the examples
in this chapter portray.
A function is not limited as to the number
of arguments it can take.
Once you’ve defined your own functions
like this, you can place them in an external
file and then require that file when you need
access to the functions.
Creating Functions
281
Setting Default
Argument Values
PHP allows functions to have default argument values: Just assign a value to the
parameter in the function definition:
function greeting($who = 'world') {
print
"
Hello, $who!
";
}
Such a function will use the preset value
unless it receives a value that then overwrites the default. In other words, by
setting a default value for an argument, you
render that particular argument optional
when calling the function. You’d set an
argument’s default value if you wanted to
assume a certain value but still allow for
other possibilities A:
greeting();
greeting('Zoe');
(Note: This isn’t really a good use of a
user-defined function, or a default argument value, but it’s easily understood as
an example.)
The parameters with default values must
always be written after the other parameters (those without default values). This
is because PHP directly assigns values to
parameters in the order they’re received
from the call line. Thus, it isn’t possible
to omit a value for the first argument but
include one for the second. For example,
suppose you have
function calculate_total($qty,
➝ $price = 20.00, $tax = 0.06) {...
If you call the function with the line
calculate_total(3, 0.07);
with the intention of setting $qty to 3,
leaving $price at 20.00, and changing the
$tax to 0.07, there will be problems.
The result will be that $qty is set to 3,
$price is set to 0.07, and $tax remains at
0.06 B, which isn’t the desired outcome.
The proper way to achieve that effect
would be to code
calculate_total(3, 20.00, 0.07);
Let’s rework the make_text_input()
function to incorporate the notion of
setting default argument values.
A Calling the function without any arguments
uses the default value (the first greeting); calling it
with an argument provided means that value will
be used instead (the second).
function calculate_total($qty, $price = 20.00, $tax = 0.06) {
// Make the calculations.
}
calculate_total(3, 0.07);
B Because of the way function arguments work, you cannot “skip” an
argument when calling a function.
282
Chapter 10
Script 10.3 The function now takes three
arguments, but only two of them are required. If
no $size is passed to the function, its value will
be 20.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Sticky Text Inputs
';
} // End of make_text_input() function.
// Make the form:
print '
';
code continues on next page
Creating Functions
283
4. Change the function calls to vary
the sizes:
make_text_input('first_name',
➝ 'First Name');
make_text_input('last_name',
➝ 'Last Name', 30);
make_text_input('email', 'Email
➝ Address', 50);
Now the first input will use the default
size, and the others will be longer.
5. Save the script as sticky2.php, place
it in the proper directory of your PHPenabled server, and test it in your
browser C.
Script 10.3 continued
35
36
37
38
39
40
41
42
43
44
// Create some text inputs:
make_text_input('first_name', 'First
Name');
make_text_input('last_name', 'Last
Name', 30);
make_text_input('email', 'Email
Address', 50);
print '
form>';
?>
To pass no value to a function for a
particular argument, use an empty string ('')
or the word NULL (without quotes). Either of
these values will override the default value, if
one is established.
As mentioned way back in Chapter 1,
“Getting Started with PHP,” the PHP manual
marks optional function arguments using
square brackets. For example, when you use
the number_format() function, the number
of decimals to round to is optional:
string number_format(float number
➝ [, int decimals = 0])
284
Chapter 10
C Now the function is capable of changing the
size of the input, based on an argument. If no
value is provided for that argument, the default
size is used instead (the first input).
Creating and Using
Functions That
Return a Value
A This simple form takes two values on
which calculations will be made.
Functions do more than take arguments;
they can also return values. Doing so
requires just two more steps. First, you use
the return statement within the function.
Second, you use the output somehow
when you call the function. Commonly,
you’ll assign the returned value to a variable, but you can also, for example, directly
print the output. Here is the basic format
for a function that takes two arguments
and returns a value:
function make_full_name
➝ ($first, $last) {
$name
= $first . ' ' . $last;
return
$name;
}
B The result of the calculation, which
takes place within a user-defined function.
This function could be used like so:
$full_name = make_full_name
➝ ($fn, $ln);
There the returned value of the function
is assigned to a variable. Here it’s printed
immediately:
print make_full_name($fn, $ln)
To best demonstrate this concept, let’s
create a function that performs a simple
calculation and formats the result. This
script will display an HTML form where a
user enters a quantity and price A. When
the form is submitted (back to this same
page), a total value will be calculated and
printed B.
Creating Functions
285
To create and use a function
that returns a value:
1. Create a new PHP document in
your text editor or IDE, to be named
calculator1.php (Script 10.4):
Cost Calculator
2. Begin the PHP code:
Your total comes to
➝ $$total.";
This part of the PHP code—which
handles the form if it has been submitted—first checks that a numeric quantity
and price were entered. If so, the
total is determined by calling the
calculate_total() function and
assigning the result to the $total variable. This result is then printed out.
continues on page 288
Script 10.4 This script both displays and handles an HTML form in order to perform some basic calculations.
The script uses a function that takes two arguments and returns a single value.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Cost Calculator
Your total comes to $$total.";
} else { // Inappropriate values entered.
print '
';
}
}
If either of the form variables was
not properly submitted, a message is
printed indicating that. The final brace
closes the form submission conditional.
A little CSS is applied to both printed
messages (here and in Step 5).
7. Display the HTML form:
?>
Quantity:
Price:
The form itself is quite simple, requesting two different values from the user
A. Because this form is created outside
of the main submission conditional, the
form will always be displayed by the
page B.
8. Complete the HTML page:
288
Chapter 10
Returning Multiple Values
User-defined functions frequently return
just a single value but can return multiple
values by using arrays. Here’s how you
go about this:
function some_function($p1, $p2)
{
//
Do whatever.
return
[$a, $b];
//
Or: return array($v1, $v2);
}
Then, to call this function, use the
list() function to assign the array elements to individual variables:
list($v1, $v2) = some_function
➝ ($a1, $a2);
The result is that $a from the function is
assigned to $v1 in the PHP script, and $b
from the function is assigned to $v2.
Declaring Return Types
PHP 7 supports the ability to declare the
type of value returned by a function. To
use this feature, follow the function name
with a colon and the type returned:
function make_full_name
➝ ($first, $last): string {
Or
function calculate_total
➝ ($quantity, $price): float {
This type of stricter function definition
is best when you want to guarantee the
type of value returned by a function.
9. Save the page as calculator1.php,
place it in the proper directory for your
PHP-enabled server, and test it in your
browser B.
You can have only one return statement
executed in a function, but the same function
can have multiple return statements. As an
example, you may want to write a function
that checks for a condition and returns a value
indicating whether the condition was satisfied.
In such a case, the function might contain
if (condition) {
return true;
} else {
return
false;
}
The result returned by the function is
either TRUE or FALSE, indicating whether the
stated condition was met.
Creating Functions
289
Understanding
Variable Scope
The concept of variable scope wasn’t
introduced in earlier chapters because
without an understanding of functions,
scope makes little sense. Now that you
are acquainted with functions, this section
revisits the topic of variables and discusses
in some detail just how variables and functions work together.
As you saw in the second section of this
chapter, “Creating and Calling Functions
That Take Arguments,” you can send
variables to a function by passing them as
arguments. However, you can also reference an external variable from within a
function using the global statement. This
is possible because of variable scope.
The scope of a variable is the realm in
which it exists.
By default, the variables you write in a
script exist for the life of that lone script.
Conversely, environment variables, such as
$_SERVER['PHP_SELF'], exist throughout
every PHP script on the server.
Functions, though, create a new level
of scope. Function variables—the function’s parameters as well as any variables
defined within the function—exist only
within that function and aren’t accessible
outside of it. Put another way, function
variables are local variables with local
scope. Likewise, a variable from outside a
function is not available within the function, by default A. Even when a variable
is used as an argument to a function call,
that variable’s value is being passed to the
function, not the variable itself.
You can, however, make a variable external
to a function available within the function
by using the global statement. The global
statement roughly means, “I want this
variable within the function to refer to the
same named variable outside of the function.” In other words, the global statement
turns a local variable with local scope into
a global variable with global scope. Any
changes made to the variable within the
function are also reflected by the variable
outside of the function, without using the
return command (assuming the function is
called, of course).
A Adding function definitions to a script adds another area of
variable scope.
290
Chapter 10
The syntax of the global statement
is simply
function function_name($args) {
global
$variable;
statement(s);
}
There is another issue regarding functions
and variables: Because of variable scope,
a local variable within a function is a
different entity—perhaps with a different
value—than a variable outside of the
function, even if the two variables use
the exact same name. Let’s look at this
more explicitly…
Say you have:
function foo($param) {
//
Do whatever.
}
$var = 1;
foo($var);
When the function is called, the value of
$var will be assigned $param, so their
values are the same but their names are
different and they are different variables.
Now if the name of the parameter in the
function is also $var—
function bar($var) {
// Do whatever.
}
$var = 1;
bar($var);
then the $var variable within the function
is assigned the same value as the original
$var outside of the function—but they’re
still two separate variables. The one has
a scope within the function, and the other
has a scope outside of it. This means that
you can use the same name for variables in
the function as exist outside of the function
without conflict.
Creating Functions
291
Just remember they aren’t the same variable. What happens to a variable’s value
within a function only affects that variable
within the function. Here’s an example B:
function add_one($n) {
$n++;
print
'Added one! ';
}
$n = 1;
print "\$n equals $n ";
add_one($n);
print "\$n equals $n ";
This is all true unless you use the global
statement, which does make the two variables the same C:
function add_one() {
global
$n; // Same!
$n++;
print
'Added one! ';
}
$n = 1;
print "\$n equals $n ";
add_one();
print "\$n equals $n ";
Note that in this case, the variable’s value
no longer needs to be passed to the function either.
To demonstrate variable scope, let’s
rework the calculator1.php script using
the global statement.
292
Chapter 10
B Changes to a local variable inside
a function have no effect on a similarly
named global variable.
C Changes made to a global variable
inside of a function will change the
variable outside of that function.
Script 10.5 The function in this script can use the
$tax variable—even though it hasn’t been passed
to the function—thanks to the global statement.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Cost Calculator
Your total comes to
➝ $$total,
➝ including the $tax percent tax
➝ rate.";
The $tax variable defined at the beginning of the script is printed out at the
end. If you hadn’t used the $taxrate
variable within the function and made
the alterations to the global $tax
instead, those calculations would be
reflected in the value printed here.
6. Save the script, place it in the proper
directory for your PHP-enabled server,
and test it in your browser D and E.
Script 10.5 continued
35
36
37
38
39
40
41
42
43
44
45
46
Constants and the superglobal arrays
($_GET, $_POST, $_COOKIE, and $_SESSION)
have the added benefit that they’re always
available inside functions without requiring
the global statement. This is why they are
known as superglobals.
48
Each function has its own, separate
local scope.
50
51
52
294
Chapter 10
47
49
// Call the function and print
the results:
$total = calculate_
total($_POST['quantity'],
$_POST['price']);
rint "
Your total comes
p
to $$total,
including the $tax percent tax
rate.
Add A Quotation
2. Create a section of PHP code, and identify the file to be used:
Add A Quotation
Your quotation has
been stored.';
} else { // Could not open the
file.
print '
Your quotation could
not be stored due to a system
error.
';
}
code continues on next page
Script 11.1 continued
30
} else { // Failed to enter a
quotation.
print '
Please enter a quotation!
';
31
32
33
34
35
36
37
38
39
40
41
42
43
44
}
This simple conditional validates
the user-supplied data. The first part
confirms that the $_POST['quote']
variable isn’t empty. The second part
confirms that the variable doesn’t still
have the default value (as shown in A).
5. Confirm that the file can be written to:
} // End of submitted IF.
if (is_writable($file)) {
// Leave PHP and display the form:
?>
By placing this function call in a conditional, you make the PHP script attempt
to write to the file only if the file is
writable.
6. Write the data to the file, and then print
a message:
file_put_contents($file,
➝ $_POST['quote'] . PHP_EOL,
➝ FILE_APPEND);
print '
Your quotation has been
➝ stored.
';
The first line writes the user-submitted
data to the file. The PHP_EOL constant
is concatenated to the written data, so
that each submission gets stored on its
own line.
7. Complete the conditionals:
}
else { // Could not open
➝ the file.
print
'
Your quotation
➝ could not be stored
➝ due to a system error.
➝
';
}
} else { // Failed to enter
➝ a quotation.
print '
Please enter a
➝ quotation!
';
}
} // End of submitted IF.
continues on next page
Files and Directories
307
The first else completes the conditional
that checks if PHP could open the file
for writing B. If you see this message,
there’s likely a permissions issue or the
file reference is incorrect. The second
else completes the conditional that
checks whether no quotation was
entered C. The final closing brace
marks the end of the main submission
conditional.
If you’d rather, you can replace the
inline CSS with an actual CSS class
declaration.
B If the PHP script can’t find the quotes.txt
file, or if it’s not writable, the user will see this
message.
Because this page handles the form
and then displays it again (so that the
user may keep entering quotations),
the form isn’t displayed as part of an
else statement as it has been in other
examples in this book.
8. Complete the PHP section:
?>
Because the rest of this script is standard HTML, exit out of the PHP code by
closing the PHP tag.
9. Create the HTML form:
➝
This HTML form presents a text box
where the user can enter a quotation.
The text box has a preset value of Enter
your quotation here., created by putting
that text between the textarea tags.
308 Chapter 11
C The script includes basic form validation.
10. Complete the HTML page:
11. Save the file as add_quote.php, and
place it in the proper directory for your
PHP-enabled server.
Again, refer back to B in the previous section, “File Permissions,” of this
chapter for how add_quote.php and
quotes.txt should be placed on your
server relative to each other. If this
arrangement isn’t possible for you,
or if it’s just too confusing, then place
both documents within the same
directory (the one from which you can
execute PHP scripts), and change the
$file assignment line to
$file = 'quotes.txt';
12. Run the script several times in your
browser D and E.
13. If you want, open the quotes.txt file in
a text editor to confirm that the data has
been written to it.
Note that all of the file- and directoryrelated functions are usable only on files and
directories on the same computer (i.e., server)
on which PHP is running. A PHP script on a
server has no access to a file on a client’s computer (until the file is uploaded to the server).
If you receive a permissions error when
you run this script B, either the permissions
aren’t set properly or the PHP script couldn’t
access the data file. The latter can happen if
you misspell the filename or incorrectly reference the file’s path on the server.
If your version of PHP is running in safe
mode or has the open_basedir directive set,
you may be limited in using PHP to access
files and directories. Check your phpinfo()
script to see these settings for your server.
D Filling out the form…
E …and the result if all went well.
Files and Directories
309
Locking Files
Although the last example worked fine
(hopefully), it could be improved on. If only
a single user were submitting the form at
one time, there would be no problems.
But what if two or more users submitted
different quotations simultaneously? In
such a case, there could be problems
when multiple instances of the PHP script
attempt to write to the same text file at
once. The file could become corrupted.
When there’s a risk of multiple scripts
writing to the same file at once, the solution is to temporarily lock the file while
PHP is writing to it. To do that, add the
LOCK_EX constant as the third argument
to file_put_contents():
file_put_contents($file, $data,
➝ LOCK_EX);
To use both the LOCK_EX and FILE_APPEND
constants, separate them with the bitwise
OR operator (|):
file_put_contents($file, $data,
➝ FILE_APPEND | LOCK_EX);
It doesn’t matter in which order you provide the two constants (see the sidebar
“Bitwise Operators”).
The different lock types are represented
by the constants listed in Table 11.2.
A shared lock, LOCK_SH, is for reading from
a file, which means it’s okay if multiple
files use the file at the same time (all with
shared locks). Conversely, the exclusive
lock, LOCK_EX, means only the locking file
should have access.
The LOCK_UN constant is for releasing any
type of lock. It’s provided to the flock()
function, not used in this chapter (see the
PHP manual for more information).
310
Chapter 11
TABLE 11.2 flock( ) Lock Types
Lock
Meaning
LOCK_SH
Shared lock for reading purposes
LOCK_EX
Exclusive lock for writing
purposes
LOCK_UN
Release of a lock
LOCK_NB
Nonblocking lock
Bitwise Operators
A lesser-known but often useful set of
operators are the bitwise operators.
Beginners will most likely use them in
situations where constants are passed as
arguments, as in the file locking example.
Bitwise operators work with bits—the
smallest data type, also referred to as
binary digits. The operators look and
function like the standard ones: bitwise &
instead of &&, bitwise | instead of ||.
Bitwise operators are often used with
constants like LOCK_EX and FILE_APPEND
because each constant represents a
numeric value. The numeric value in turn
is a type of flag indicating what’s allowed.
The code FILE_APPEND | LOCK_EX
therefore says to apply whatever flags
are represented by the FILE_APPEND or
the LOCK_EX constants.
Note that you should unlock the
file once the script is done with it,
although PHP will kindly unlock it for
you should you forget.
To demonstrate, let’s update
add_quote.php to lock the file during
the writing process.
Script 11.2 The modified version of the
add_quote.php script locks the data file for
better security and reliability.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Add A Quotation
Your quotation has
been stored.';
} else { // Could not open the
file.
print '
Your quotation could
not be stored due to a system
error.
';
}
code continues on next page
Files and Directories
311
3. Save the file, place it in the proper
directory for your PHP-enabled server,
and test it again in your browser A
and B.
Technically, if a file is opened in an
appending mode, as in this example, not locking it probably won’t be a problem even if
multiple scripts are writing to the file simultaneously. That said, better safe than sorry!
For file locking to be reliable, every script
that writes to a file needs to use locking.
Script 11.2 continued
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
} else { // Failed to enter a
quotation.
print '
Please enter a quotation!
p>';
}
} // End of submitted IF.
// Leave PHP and display the form:
?>
A Using the form once again…
B …the quotation is still stored without a problem.
312
Chapter 11
Reading from Files
Now that you’ve created a script that
writes data to a file, it’s time to create one
that can read the information. There are a
number of ways to read from a file; which
approach you take depends on what your
needs are. To read an entire file in as one
string, use file_get_contents():
$data = file_get_contents($file);
Alternatively, if the file has some data on
each line, as is the case with quotes.txt,
you’re better off using the file() function:
$data = file($file);
The file() function is a valuable built-in
tool in PHP. It reads everything from a file
and, unlike file_get_contents(), returns
that information as an array. Each array
element contains one line from the file,
where each line is terminated by a newline
(\n or \r\n).
If the document represented by $file
contains two lines of information, each of
which ends with a newline, the corresponding array will contain two elements. The
first element will be equal to the first line
of $file, and the second element will be
equal to the second line. Once the data is
stored into an array, you can easily manipulate or print it, as you learned in Chapter 7,
“Using Arrays.”
Next, let’s use this knowledge to create
a script that randomly displays one of the
stored quotations.
Files and Directories
313
To read from a file:
1. Create a new PHP document in
your text editor or IDE, to be named
view_quote.php (Script 11.3):
View A Quotation
Random Quotation
2. Open a PHP code section:
View A Quotation
Random Quotation
' . trim($data[$rand]) .
'';
?>
If $data has 10 elements, they’re
indexed between 0 and 9, so that’s the
range to use for rand(). Therefore, to
calculate the range for a variable number
of lines in the text file, use 0 and 1 less
than the number of elements in $data.
A A random quotation is displayed each time the
page is viewed.
B Subsequent viewings of the view_quote.php
script display different quotations from the text file.
5. Print out the quotation:
print '
' . trim($data
➝ [$rand]) . '
';
A simple print statement involving
concatenation is used to print the random
quotation. To retrieve the quotation, you
refer to the $data array and use the
generated $rand number as the index.
The retrieved quotation is then trimmed
to cut off the newline characters from
the end of the quotation.
6. Complete the PHP code and the HTML
page:
?>
7. Save the file as view_quote.php, place
it on your web server (in the same
directory as add_quote.php), and test it
in your browser A.
8. Reload the page in your browser to
view another random quote B.
If you want to be extra careful, you can
use the is_readable() function to test that
PHP can read a file before you call the file()
function (although it’s rare that a file isn’t
readable).
The readfile() function reads through
a file and immediately sends the contents to the
output buffer. This means that with output
buffering enabled, the file’s contents get added
to the buffer. With output buffering disabled,
the file’s contents go straight to the browser.
Later in this chapter, you’ll learn a
more complex method of reading a file using
fgets() and fgetcsv().
Files and Directories
315
Handling File Uploads
As this book has demonstrated, handling
HTML forms using PHP is a remarkably
easy achievement. Regardless of the data
being submitted, PHP can handle it easily
and directly. The same is true when the
user uploads a file via an HTML form.
To give the user the option of uploading a file, you must make three changes
to the standard HTML form. First, the
initial form tag must include the code
enctype="multipart/form-data", which
lets the browser know to expect different
types of form data:
The form must also always use the POST
method.
Second, a special hidden input type should
be added to the form:
This tells the browser how large a file, in
bytes, can be uploaded.
Third, the file input is used to create the
necessary form field A and B:
The file type of form input allows users to
select a file on their computer, which, upon
submission, will be uploaded to the server.
Note that the file input should be placed
after the MAX_FILE_SIZE hidden input.
316 Chapter 11
A This is how Chrome interprets the
file input type (prior to selecting a file).
B This is how Internet Explorer
interprets the file input type.
TABLE 11.3 FILE Error Codes
Code
Meaning
0
No error has occurred.
1
The file exceeds the
upload_max_filesize setting
in php.ini.
2
The file exceeds the MAX_FILE_SIZE
setting in the HTML form.
3
The file was only partially uploaded.
4
No file was uploaded.
6
No temporary directory exists.
7
Failed write to disk.
8
Upload prevented by an extension.
Once you’ve configured the HTML form
and the user has submitted a file through
it, you can then use PHP to handle the file.
In the PHP script, you refer to the $_FILES
variable (think of it as the file equivalent of
$_POST) to reference the uploaded file. The
$_FILES array contains five elements:
n
name, the name of the file as it was on
the user’s computer
n
type, the MIME type of the file (for
example, image/jpg)
n
n
n
size, the size of the file in bytes
tmp_name, the temporary name of the
file as it’s stored on the server
error, an error code if something
goes wrong (Table 11.3; note that, as
strange as this may seem, there is no
error code 5).
When a file is uploaded, the server first
places it in a temporary directory. You should
then use the move_uploaded_file() function to move the file to its final destination:
move_uploaded_file($_FILES
➝ ['picture']['tmp_name'],
➝ '/path/to/dest/filename');
The first argument is the temporary
name of the file on the server, found in
$_FILES['input_name']['tmp_name'].
The second argument is the full path and
name of the destination.
continues on next page
Files and Directories
317
For PHP to be able to take these steps,
you must set several configurations in the
php.ini file (see the “Configuring PHP for
File Uploads” sidebar), and the web server
needs write access to both the temporary
and the final destination directories. (PHP
should have write access to the temporary
directory by default.)
Next, you’ll write a basic script that uploads
a file and stores it on the server. Like
the add_quote.php script, this example
also both creates the HTML form C and
processes it, all in one page. First, though,
you’ll create a writable directory as the
destination point.
C This HTML form lets users select a file on their
computer to upload to the server.
To create a writable directory:
1. Create a new folder named uploads,
located outside the web directory
root D.
2. Using the steps outlined in the first section of this chapter, “File Permissions,”
set the permissions so that everyone
can write to, read from, and search
(0777 in Unix terms) the directory.
D For this example, a writable uploads
directory must exist. Here, it’s placed in the
same directory as the web root folder. Thus,
uploads is in the directory above the one in
which the upload_file.php script resides and
is not accessible via HTTP.
Configuring PHP for File Uploads
In order for file uploading to work, a number of settings in your php.ini configuration file must be
set. These may or may not be enabled in your configuration, so you should check them by viewing
the php.ini file or running a phpinfo() script.
For starters, file_uploads must be on. Second, the upload_tmp_dir value must be set to a
directory on the server where PHP can place files (in other words, it must exist and be modifiable
by the web server). If this setting has no value, that’s probably fine (meaning that a hidden directory
created expressly for purposes such as these will be used).
The upload_max_filesize and post_max_size settings dictate how large a file can be sent,
such as 512 KB or 2 MB. Whereas the MAX_FILE_SIZE hidden form input is a recommendation to
the browser, these two settings control whether the file is uploaded.
Finally, if really large files—many megabytes or larger—will be uploaded, you may need to increase
the memory_limit and max_execution_time settings to give PHP the time and the resources to
do what it needs to do.
318
Chapter 11
Again, if you’re running Windows you
likely don’t need to do anything (try the
next script to see for sure). If you’re running another operating system, check
the list of bullet points in the first section
of the chapter for the suggestion that
works for your situation.
To use PHP for file uploads:
1. Create a new PHP document in
your text editor or IDE, to be named
upload_file.php (Script 11.4):
2. Create a section of PHP code:
Upload a File
continues on page 321
Script 11.4 This script handles a file upload by first defining the proper HTML form and, second, invoking
move_uploaded_file() to move the file to the desired location.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Upload a File
Your file has been uploaded.';
} else { // Problem!
print '
Your file could not be uploaded because: ';
// Print a message based upon the error:
switch ($_FILES['the_file']['error']) {
case 1:
print 'The file exceeds the upload_max_filesize setting in php.ini';
break;
case 2:
print 'The file exceeds the MAX_FILE_SIZE setting in the HTML form';
break;
case 3:
print 'The file was only partially uploaded';
break;
case 4:
print 'No file was uploaded';
break;
case 6:
print 'The temporary folder does not exist.';
break;
default:
print 'Something unforeseen happened.';
break;
}
print '.
'; // Complete the paragraph.
} // End of move_uploaded_file() IF.
} // End of submission IF.
// Leave PHP and display the form:
?>
Chapter 11
4. Attempt to move the uploaded file to its
final destination:
if (move_uploaded_file
➝ ($_FILES['the_file']
➝ ['tmp_name'], "../uploads/
➝ {$_FILES['the_file']
➝ ['name']}")) {
The move_uploaded_file() function
attempts to move the uploaded file
(identified by $_FILES['the_file']
['tmp_name']) to its new location (../
E If the file was uploaded and moved successfully,
a message is printed and the form is displayed
again.
uploads/{$_FILES['the_file']
['name']). The location is the uploads
directory, which is in the folder above
the one this script is in. The file’s name
will be the same as it was on the user’s
computer.
Placing this function as a condition in an
if statement makes it easy to respond
based on whether the move worked.
Note that there is an implicit trust here
that the user is uploading a file that’s
safe for you to put onto your server
retaining the same name. See the tips
for suggestions on how to make this
process more secure.
5. Print messages indicating the success
of the operation:
print '
Your file has been
➝ uploaded.
';
} else { // Problem!
print '
➝ Your file could not be
➝ uploaded because: ';
The first print statement is executed if
the move worked E. The else applies
if it didn’t work, in which case an error
message is begun. This message will
be made more explicit in Step 6.
continues on next page
Files and Directories
321
6. Print out the error message if the move
didn’t work:
switch ($_FILES['the_file']
['error']) {
case 1:
print 'The file exceeds the
➝ upload_max_filesize setting
➝ in php.ini';
break;
case 2:
print 'The file exceeds the
➝ MAX_FILE_SIZE setting in
➝ the HTML form';
break;
case 3:
print 'The file was only
➝ partially uploaded';
break;
case 4:
print 'No file was uploaded';
break;
case 6:
print 'The temporary folder
➝ does not exist.';
break;
default:
print 'Something unforeseen
➝ happened.';
break;
}
If a move doesn’t work, the
$_FILES['the_file']['error']
variable contains a number indicating
the appropriate error message. When
you use this in a switch conditional, the
PHP script can print out the appropriate
error message F.
You wouldn’t normally place code like
this in a public site—it’s a little too much
information—but it’s exceptionally good
for helping you debug a problem.
322
Chapter 11
F If a problem occurred, the script indicates the
cause.
7. Complete the error message, and close
both conditionals:
print '.
'; // Complete
paragraph.
}
// End of move_uploaded_
➝ file() IF.
} // End of submission IF.
➝ the
8. Exit out of PHP, and create the
HTML form:
?>
Upload a file using this
➝ form:
The HTML form is simple, containing
only two visible elements: a file input
type and a submit button. It differs from
other HTML forms in this book in that
it uses the enctype attribute and a
MAX_FILE_SIZE hidden input type.
Be careful when giving your file input a
name, because this value must exactly
match the index used in the $_FILES
variable. Here, you use a generic
the_file.
9. Complete the HTML page:
continues on next page
Files and Directories
323
10. Save the page as upload_file.php,
place it in the proper directory for your
PHP-enabled server relative to the
uploads directory D, and test it in your
browser G.
Only files smaller than about 300 KB
should be allowed, thanks to the
MAX_FILE_SIZE restriction.
11. Inspect the uploads directory to ensure
that the file was placed there.
If the file couldn’t be moved and a
permissions denied error is shown, check
the permissions on the uploads directory.
Then check that the path to the directory used
in the script is correct and that there are no
spelling errors.
As you might discover, files uploaded
through the browser are owned—in terms of
permissions—by the web server application,
which put them there.
From a security standpoint, it’s better
to rename an uploaded file. To do so, you’ll
need to devise a system that generates a new,
unique filename and stores both the original
and new filenames in a text file or a database.
A script can handle multiple file uploads
as long as they have different names. In such
a case, you need only one MAX_FILE_SIZE
hidden input. In the PHP script, you’d
apply the move_uploaded_file()
function to $_FILES['filename1'],
$_FILES['filename2'], and so on.
You can limit a file upload to a specific
size or type by referencing the appropriate
index (for example, $_FILES['the_file']
['size']) in your PHP script (after the file
has been uploaded).
Use unlink() to delete a file without
moving or copying it.
You can use the copy() function to
make a copy of a file on the server.
324
Chapter 11
G Select a file on your computer to upload.
Navigating Directories
The previous PHP scripts work with files,
but you can also do many things with
directories using PHP. In this example,
you’ll write a script that lists a directory’s
contents, but first you’ll need to understand the usage and syntax of many of the
functions you’ll use.
To find all the contents of a directory,
the easiest option is to use the
scandir() function:
$stuff = scandir($dir);
This function returns an array of every
item—directory or file—found within the
given directory. As with the file-related
functions, the value of $dir can be a relative or an absolute path to the directory
in question.
A The list_dir.php script shows the contents of
a directory. The top part lists the subfolders, and
the bottom table lists the files.
This next example uses scandir(), but
let’s look at a couple more functions first.
You’ll use the filesize() function in this
example; it determines how large a file is
in bytes. This value can be assigned to a
variable or be printed:
$size = filesize($file);
Similarly, the filemtime() function
retrieves the modification time of a file. It
returns a timestamp, which can be formatted using the date() function.
Finally, PHP includes several functions
that identify attributes. This chapter has
already mentioned is_writable() and
is_readable(), but there are also
is_dir() and is_file(). They return
TRUE if the item in question is a directory
or a file, respectively.
You’ll put all of these capabilities together
into one page, which will constitute a
web-based control panel for viewing a
directory’s contents A.
Files and Directories
325
To create the directory
control panel:
1. Create a new PHP document in
your text editor or IDE, to be named
list_dir.php (Script 11.5):
Directory Contents
title>
Script 11.5 This script displays the contents of a directory. First the subdirectories are listed, followed by the
files (with their sizes and modification dates) in a table.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Directory Contents
Directories
';
foreach ($contents as $item) {
if ( (is_dir($search_dir . '/' . $item)) AND (substr($item, 0, 1) != '.') ) {
print "
$item
\n";
}
}
print '
'; // Close the list.
code continues on next page
326 Chapter 11
Script 11.5 continued
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// Create a table header:
print '
Files
Name
Size
Last Modified
';
// List the files:
foreach ($contents as $item) {
if ( (is_file($search_dir . '/' .
$item)) AND (substr($item, 0, 1)
!= '.') ) {
// Get the file size:
fs = filesize($search_dir .
$
'/' . $item);
// Get the file's modification
date:
lm = date('F j, Y',
$
filemtime($search_dir . '/' .
$item));
// Print the information:
print "
$item
$fs bytes
$lm
\n";
} // Close the IF.
} // Close the FOREACH.
2. Begin the PHP code, and set the time
zone:
'; // Close the HTML
table.
?>
Files and Directories
327
4. List the subdirectories of this directory:
print '
Directories
';
foreach ($contents as $item) {
if ( (is_dir($search_dir . '/'
➝ . $item)) AND (substr($item,
➝ 0, 1) != '.') ) {
print "
$item
\n";
}
}
print '
';
This foreach loop accesses every item
in the array, assigning each one to the
$item variable. The script should first
list every directory, so the is_dir()
function is called to confirm the item’s
type. That same conditional also checks
that the current item isn’t the current
directory or a hidden directory—both
marked by a single period on Unix systems—or the parent directory, marked
by a double period on Unix systems. If
this conditional is TRUE, then the item’s
name is printed out, within list item tags,
followed by a newline (to make for
neater HTML source code).
So that the is_dir() function will work
when dealing with items found in other
directories, the $search_dir value, plus
a slash, is appended to each item. If the
code just referred to $item without adding the directory path, the code would
only work for the current directory.
5. Create a new heading, and start a table
for the files:
print '
Files
Name
Size
Last Modified
';
328
Chapter 11
The script also displays the files’ sizes
and modification dates. To make this
look nicer, the results are placed in an
HTML table.
6. Begin looping through the files in this
directory:
foreach ($contents as $item) {
if ( (is_file($search_dir . '/'
➝ . $item)) AND (substr($item,
➝ 0, 1) != '.') ) {
Another foreach loop is used to go
through the directory contents again.
This time, the conditional only wants
items that are files, but not hidden files
that begin with a single period.
Again, the $search_dir value and a
slash is prepended to each item.
7. Calculate the file’s size and modification
date, and then print out the information:
$fs = filesize($search_dir . '/'
➝ . $item);
$lm = date('F j, Y', filemtime
➝ ($search_dir . '/' . $item));
print "
$item
$fs bytes
$lm
\n";
The first line calls the filesize() function to retrieve the file’s size in bytes.
The second line calls the filemtime()
function, which returns a timestamp of
the file’s modification time. The timestamp is then fed into the date() function, along with the proper formatting,
to return a string like November 24,
2016. Finally, these two items and the
file’s name are printed in the appropriate columns of the table.
For additional security, you can also
apply htmlspecialchars() to the
item’s name when printing it.
8. Complete the conditional and the loop:
}
}
9. Close the table:
print '
';
10. Complete the PHP code and the
HTML page:
?>
11. Save the file as list_dir.php, place it
in the proper directory for your PHPenabled server, and test it in your
browser A.
12. If you want, change the value of
$search_dir, and retest the script in
your browser B.
B The directory listing for another folder
on the server.
Notice that you need to use double
backslashes to create absolute path names on
a Windows server. This is necessary because
the single backslash, used in Windows path
names, is the escape character. So, it must be
escaped to be taken literally:
C:\\myfiles\\directory
The glob() function lets you search a
directory for files whose name matches a pattern (like something.jpg or filename.doc).
Other file functions you might appreciate
include fileperms(), which returns the
file’s permissions; fileatime(), which
returns the last time a file was accessed; and
fileowner(), which returns the user who
owns the file.
The basename() and dirname()
functions are useful for finding subparts of
a full directory or file path.
The finfo_file() function is the best
way to find a file’s MIME type.
Files and Directories
329
Creating Directories
Understanding how to read from and write
to files on the server is only part of the data
storage process. It’s likely you’ll want to
read from and write to directories as well.
The command for creating a directory in
PHP is mkdir():
mkdir('directory_name',
➝ permissions);
The directory name is the name of the
directory to be created. This value can be
relative to the current directory (i.e., the
one the script is in), or it can be a full path:
mkdir('C:\\inetpub\\users\\rey');
On Windows servers, the permissions are
ignored and therefore not required (as in
the preceding example). On non-Windows
servers, the permissions are 0777 by
default (see the section “File Permissions”
earlier in this chapter to learn what those
numbers mean).
With this in mind, let’s create a script that
makes a new directory for a user when the
user registers—the theory being that a user
could upload files to that directory. This
script also records the username and password to a text file so that the user can be
validated when logging in. You’ll begin by
creating the parent directory, which must
be writable so that PHP can create subdirectories in it, and the users.txt data file.
330 Chapter 11
To create the directory
and the data file:
1. Create a new folder named users,
located outside of the web directory
root.
It could be created in the same directory as the uploads folder made earlier
(see D in “Handling File Uploads”).
2. Using the steps outlined in the first section of this chapter, “File Permissions,”
set the permissions so that everyone
can write to, read from, and search
(0777 in Unix terms) the directory.
If you’re running Windows, this step will
most likely not be necessary.
3. In your text editor, create a new, blank
document.
4. Save this file in the users directory with
the name users.txt.
5. Again using the steps outlined earlier
in the chapter, set the permissions on
users.txt so that everyone can write
to and read from the file (0666 in Unix
terms).
Again, this will probably not be necessary if you’re running Windows on your
PHP server.
Once you create a directory that PHP can
write to, PHP should be able to automatically
create a users.txt file in that directory to
which PHP can write. However, it’s best not to
make assumptions about such things.
To create the registration script:
1. Begin a new PHP document in your
text editor or IDE, to be named
register.php (Script 11.6):
Register
Register
In the page’s head, a CSS class is defined
that will be used to format errors.
continues on page 333
Script 11.6 The register.php script serves two purposes: It records the user’s information in a text file and
creates a new directory for that user’s stuff.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Register
Register
Please enter a username!';
}
if (empty($_POST['password1'])) {
$problem = TRUE;
print '
Your password did not match your confirmed password!
';
}
if (!$problem) { // If there weren't any problems...
if (is_writable($file)) { // Open the file.
// Create the data to be written:
subdir = time() . rand(0, 4596);
$
$data = $_POST['username'] . "\t" . sha1(trim($_POST['password1'])) . "\t" .
$subdir . PHP_EOL;
// Write the data:
file_put_contents($file, $data, FILE_APPEND | LOCK_EX);
// Create the directory:
mkdir ($dir . $subdir);
// Print a message:
print '
You are now registered!
';
} else { // Couldn't write to the file.
print '
You could not be registered due to a system error.
';
}
} else { // Forgot a field.
print '
Please go back and try again!
';
}
} else { // Display the form.
// Leave PHP and display the form:
?>
code continues on next page
332
Chapter 11
Script 11.6 continued
68
69
70
71
72
73
74
75
76
77
Username:
Password:
Confirm Password:
2. Begin the PHP code, and create two
variables:
Please
➝ enter a username!';
}
if (empty($_POST['password1'])) {
$problem = TRUE;
print '
Your
➝ password did not match your
➝ confirmed password!
';
}
continues on next page
Files and Directories
333
The registration form is a simpler version of earlier registration forms developed in this book. The same validation
process you previously developed is
used to check the submitted username
and passwords. The $problem variable
is used as a flag to indicate whether a
problem occurred.
5. Check for problems:
if (!$problem) {
Again, the $problem variable lets you
know if it’s okay to register the user.
If no problems occurred, it’s safe to
continue.
6. Confirm that the users.txt file is
writable:
if (is_writable($file)) {
Like before, the data file is first confirmed
as writable in a conditional so that the
script can respond accordingly.
7. Create the data to be written to the file,
and then write it:
$subdir = time() . rand(0, 4596);
$data = $_POST['username'] .
➝ "\t" . sha1(trim($_POST
➝ ['password1'])) . "\t" .
➝ $subdir . PHP_EOL;
file_put_contents($file, $data,
➝ FILE_APPEND | LOCK_EX);
The name of the directory being
created is a number based on the time
the user registered and a random value.
This system helps guarantee that the
directory created is unique and has a
valid name.
334
Chapter 11
A The result if the users.txt file is not writable.
Instead of storing a single string, as
you previously have, this script stores
three separate pieces of information:
the user’s name; an encrypted version
of the password (using the sha1() function; see the “Encrypting Passwords”
sidebar); and the directory name,
created in the preceding line. The
password is trimmed first, to get rid of
any extraneous spaces.
To distinguish between the pieces of
information, you insert a tab (created
using the \t code). A newline is used
to mark the end of the line, again using
the PHP_EOL constant.
8. Create the user’s directory, and print a
message:
mkdir($dir . $subdir);
print '
You are now
➝ registered!
';
B The script reports any form validation errors.
The mkdir() function creates the
directory in the users directory. The
directory is named whatever random
number was generated earlier.
9. Complete the conditionals:
} else { // Couldn't write to
the file.
print '
You
➝ could not be registered due
➝ to a system error.
';
}
} else { // Forgot a field.
print
'
Please
➝ go back and try again!
';
}
The first else completes the conditional
if the script couldn’t open the users.txt
file for writing A. The second else
completes the conditional if the user
failed to complete the form properly B.
Files and Directories
335
10. Add an else clause to the main conditional, and exit out of PHP:
} else {
?>
Unlike the previous examples in this
chapter, this PHP script first displays
the form and then handles it. Whereas
the other scripts would then display the
form again, this one does not, because
the form creation is part of an else
statement. The rest of the page is just
HTML, so you exit out of PHP to create
the form.
11. Display the HTML form:
Username:
➝
Password:
12. Complete the main conditional:
This final closing curly bracket closes
the main submit conditional. For it to
work, a new PHP section must first be
created.
13. Complete the HTML page:
336 Chapter 11
C The registration form is quite basic but
serves its purpose.
D This is what the user sees if the
registration process worked.
14. Save the file as register.php, place it
in the proper directory for your PHPenabled server, and test it in your
browser C and D.
15. If you want, open the users.txt file
in your text editor to see its contents
(Script 11.7).
You can also ensure that the page
worked as it should by looking in the users
directory for the new subdirectories.
The rmdir() function deletes an existing directory, assuming PHP has permission
to do so.
When using a character, such as the tab,
to separate stored values, you should additionally take measures to escape or strip that
character from the stored values.
Script 11.7 The users.txt file lists three tab-delineated fields of information: the username, a scrambled
version of the user’s password, and the user’s associated directory name.
1
2
3
4
5
larry 9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684 14615086124319
john 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8 14615086364092
paul f0578f1e7174b1a41c4ea8c6e17f7a8a3b88c92a 14615086461481
george 81fe8bfe87576c3ecb22426f8e57847382917acf 14615252264106
ringo c2543fff3bfa6f144c2f06a7de6cd10c0b650cae 1461525233328
Encrypting Passwords
The sha1() function creates a hash: a mathematically calculated representation of a string. So the
registration script doesn’t actually store the password but stores a representation of that password
(in theory, no two strings would have the same sha1() value). You’ll soon see how the hashed
password is used by a login script.
That being said, the sha1() does not create a secure representation of the password. For modern
computers, it’s far too easy to perform the calculations necessary to crack passwords hashed
with sha1(). But the book does use sha1() as an easy approach, with the expectation that you
wouldn’t replicate this in a real-life application.
The current, most secure solution for password management is to use PHP’s built-in password_
hash() and password_verify() functions. Although not overly complex, they are a bit involved
for beginners, especially if you’re not using at least PHP 5.5 or greater. When you’re ready to
implement your own login capability, see the PHP manual pages for these functions to learn how
to use them.
Files and Directories
337
Reading Files
Incrementally
In the view_quote.php script (Script 11.3),
an entire file was read into an array using
the file() function. But what if you
want to read in only a little of the file at
a time? Then you need to use the
fgets() function.
The fgets() function reads a string of a
certain length. It’s most often placed in a
while loop that uses the feof() function
to make sure the end of the file hasn’t
been reached. For example:
$fp = fopen($file, 'rb');
while (!feof($fp)) {
$string
= fgets($fp, 1024);
}
fclose ($fp);
With that code, 1,023 bytes of data at a
time will be read in, as fgets() always
reads 1 byte less than the length you
specify. Or fgets() will stop reading once
it reaches the end of the line or the end of
the file. The second argument is optional,
but if present, it should be a number larger
than a single line of text in the file. If you
want to just read to the end of the line,
omit the length argument:
$string = fgets($fp);
In an example where the data is stored in a
delineated format (commonly using a
comma, hence a CSV—comma-separated
values—format), you can use the fgetcsv()
function instead. It breaks the string into
parts, using the marked separator, and
returns an array:
$array = fgetcsv($fp, length,
➝ delimiter);
$array = fgetcsv($fp, 1024);
338 Chapter 11
Again, the preceding function call returns
1023 bytes of data, but it breaks the string
into an array using the default delimiter—a
comma—as an indicator of where to make
elements. This function is the equivalent of
using the fgets() and explode() functions together. If you provide a delimiter
argument, you can change what character
is used to delineate the data.
Finally, because these functions rely on
identifying the end of a line, it’s a smart
extra precaution to enable PHP’s
auto_detect_line_endings setting. You
can do so using the ini_set() function:
ini_set('auto_detect_line_endings',
➝ 1);
As an example, let’s create a login script
that uses the users.txt file created in the
preceding example. It will continue to read
a file until a matching username/password
combination has been found.
To read a file incrementally:
1. Begin a new PHP document in your text
editor or IDE, to be named login.php
(Script 11.8):
Login
Login
2. Create the PHP section, and identify the
file to use:
Login
Login
You are now logged in.
';
} else {
print '
The
username and password you entered
do not match those on file.
';
}
} else { // Display the form.
// Leave PHP and display the form:
?>
Username:
Password:
7. Check the submitted values against the
retrieved values:
if ( ($line[0] == $_POST
➝ ['username']) AND ($line[1] ==
➝ sha1(trim($_POST
➝ ['password']))) ) {
This two-part conditional checks the
submitted username against the stored
username ($line[0]) and checks
the submitted password against the
stored password ($line[1]). However,
because the stored password was
scrambled using sha1(), apply sha1()
to the submitted value and then make
the comparison.
8. If a match was found, set $loggedin to
TRUE, and exit the while loop:
$loggedin = TRUE;
break;
If the conditional is TRUE, the submitted
username and password match those
on file. In this case, the $loggedin flag
is set to TRUE, and the break statement
is used to exit the while loop. The
benefit of this system is that only as
much of the file is read as is required
to find a match.
9. Close the conditional, the while loop,
and the file:
}
}
fclose ($fp);
10. Print a message to the user:
if ($loggedin) {
print '
You are now logged
➝ in.
';
} else {
print '
➝ The username and password you
➝ entered do not match those on
➝ file.
';
}
Using the $loggedin flag, the script can
now say whether the user is “logged in.”
You could add some functionality to this
process by storing the user’s directory
in a session and then sending them to
a file-upload page.
11. Continue the main submit conditional,
and exit PHP:
} else {
?>
12. Create the HTML form:
Username:
➝
Password:
➝
continues on next page
Files and Directories
341
13. Return to PHP to complete the main
conditional:
14. Finish the HTML page:
15. Save the file as login.php, place it
in the proper directory for your PHPenabled server, and test it in your
browser A, B, and C.
A The login form takes a username and
password.
As of PHP 5.3, the fgetcsv() function
takes another optional argument: the character used to escape problematic characters.
Naturally, the default escape character is the
backslash.
If a line is blank, fgetcsv() returns an
array containing a single null value.
B If the submitted username and password
match those previously recorded, the user
sees this message.
C The result if the user submits a username and
password combination that doesn’t match the
values previously recorded.
342
Chapter 11
Review and Pursue
If you have any problems with the review
questions or the pursue prompts, turn
to the book’s supporting forum
(www.LarryUllman.com/forums/).
Review
n
n
n
n
n
n
n
n
n
n
What version of PHP are you running?
What steps did you need to take to
make a file or directory writable for
your server?
What is the web root directory (as a
concept)? What is the web root directory for your website (whether on your
own computer or on a live server)?
What are two ways you can write data
to a file?
How do you append new data to
existing files (as opposed to replacing
any existing data)?
How do you ensure that new data is
placed on its own line?
In order for a form to accept file
uploads, what attributes must the
opening form tag have?
In what variable will a PHP script be
able to access an uploaded file? What
function is used to move the file to its
final destination on the server?
How does the fgetcsv() function differ
from file() or file_get_contents()?
Is sha1() a secure method for
hashing data?
Files and Directories
343
Pursue
n
n
n
n
n
n
n
Check out some of the other filesystemrelated functions in the PHP manual
(start at www.php.net/manual/en/
ref.filesystem.php).
n
n
Modify add_quote.php so that it confirms that the quotes.txt file exists
prior to checking if it’s writable.
Make the text area in
add_quote.php sticky.
Change add_quote.php so that it
takes the quotation and the attribution
as separate inputs and writes them
separately to the text file. Then modify
view_quote.php so that it retrieves
and displays both pieces of data.
Modify view_quote.php so that it
displays two random quotations.
Update upload_file.php, making it
confirm that the uploads directory
is writable.
View the PHP manual page for the
glob() function to see what it can do
and how to use it.
344 Chapter 11
n
n
Update list_dir.php to display other
information about the files in a directory.
Create a system to guarantee unique
usernames in register.php. Hint:
Before you attempt to create the
directory, use PHP to check your list
of existing usernames for a match to
the just-registered name. If no match
is found, the new name is acceptable.
If the username is already in use, then
PHP can create an error message
requesting a new username.
Use the combination of writing to and
reading from text files, plus either
sessions or cookies, to create a real
registration and login system.
When you’re ready for a bigger challenge, rewrite register.php and
login.php to use the password_hash()
and password_verify() functions.
12
Intro to
Databases
The Internet wouldn’t be what it is today if
not for the existence of databases. In fact,
PHP probably wouldn’t be as popular or
as useful if not for its built-in support for
numerous types of databases. This chapter
will use MySQL as the example database
management system (DBMS). Although
MySQL—which is available for most
platforms—may not be as powerful as the
highest-end commercial database servers,
it has enough speed and functionality for
most purposes. And its price—free for most
uses—makes it the common choice for
web development.
This chapter walks through the development of a simple database for running a
basic blog. Although you’ll learn enough
here to get started working with databases,
you’ll want to visit Appendix B, “Resources
and Next Steps,” once you’ve finished this
chapter to find some references where you
can learn more about the topic.
In This Chapter
Introduction to SQL
346
Connecting to MySQL
348
MySQL Error Handling
352
Creating a Table
355
Inserting Data into a Database
360
Securing Query Data
366
Retrieving Data from a Database
371
Deleting Data in a Database
376
Updating Data in a Database
382
Review and Pursue
388
Introduction to SQL
TABLE 12.1 Common SQL Commands
A database is a collection of tables
(made up of columns and rows) that stores
information. Most databases are created,
updated, and read using SQL (Structured
Query Language). SQL has surprisingly few
commands (Table 12.1 lists the seven most
important), which is both a blessing and
a curse.
Command
Purpose
ALTER
Modifies an existing table
CREATE
Creates a database or table
DELETE
Deletes records from a table
DROP
Deletes a database or table
INSERT
Adds records to a table
SELECT
Retrieves records from a table
SQL was designed to be written a lot like
the English language, which makes it very
user friendly. But SQL is still extremely
capable, even if it takes some thought to
create more elaborate SQL statements
with only the handful of available terms. In
this chapter, you’ll learn how to execute all
the fundamental SQL commands.
UPDATE
Updates records in a table
For people new to PHP, confusion can
stem from PHP’s relationship to HTML
(i.e., PHP can be used to generate HTML,
but PHP code is never executed in the
browser). When you incorporate a database, the relationships can become even
fuzzier. The process is quite simple: PHP is
used to send SQL statements to the database application, where they are executed.
The result of the execution—the creation
of a table, the insertion of a record, the
retrieval of some records, or even an
error—is then returned by the database to
the PHP script A.
With that in mind, PHP’s mysqli_query()
function will be the most-used tool in
this chapter. It sends an SQL command
to MySQL:
$result = mysqli_query(database
➝ connection, SQL command);
346 Chapter 12
Database application
if(conn
SELEC
WHERE
print
1. SQL query
2. Result of execution
PHP script
A PHP will be used to send an SQL statement
to MySQL. MySQL will execute the statement and
return the result to the PHP script.
MySQL Support in PHP
Support for the MySQL database server
has to be built into PHP in order for you
to use PHP’s MySQL-specific functions.
For most PHP installations, this should
already be the case. You can confirm
support for MySQL by calling the
phpinfo() function, which reveals
details of your installation.
When working through this chapter,
if you see an error message saying …
undefined function mysqli_…, this
means the version of PHP you’re using
doesn’t have support for MySQL (or you
misspelled the function name, which you
should also check).
Enabling support for MySQL takes a little
effort, but it can be done if you have
administrative-level control over your
server. For more information, see the
PHP manual.
I start this chapter with this prologue
because the addition of SQL and MySQL to
the web development process will complicate things. When problems occur—and
undoubtedly they will—you’ll need to know
how to solve them.
When a PHP script that interacts with a
MySQL database does not perform as
expected, the first step is to determine if
the problem is in the query itself—number 1
in A—or in the results of the query—
number 2 in A. To take this step, you can
start by printing out the query being executed, using code such as the following:
print $query;
Assuming that $query represents the complete SQL command, often containing the
values of PHP variables, this one simple
line will reveal to you the actual SQL statement being run.
Next, you would take the printed query and
execute it using another application. The
two most common options are
n
n
The MySQL client B, a command-line
tool for interacting with MySQL
phpMyAdmin C, a PHP-based
MySQL interface
One or both of these should be provided to
you by your hosting company or the software you installed on your own computer.
For a demonstration of using each, see
Appendix A, “Installation and Configuration.”
Technically, a DBMS, or database application, is the software that interfaces with the
database proper. However, a lot of people use
the terms database and DBMS synonymously.
Lots of other applications are available
for interacting with MySQL aside from the
MySQL client and phpMyAdmin. Some are free,
and others cost. A quick search using Google
for MySQL, admin, and your operating system
should turn up some interesting results.
B The MySQL client comes
with the MySQL database
software and can be used to
execute queries without the
need for a PHP script.
C phpMyAdmin is perhaps the most popular software written in PHP. It provides a web-based
interface for a MySQL database.
Intro to Databases
347
Connecting to MySQL
When you worked with text files in
Chapter 11, “Files and Directories,” you saw
that some functions, such as fwrite()
and fgets(), require that you first create
a file pointer using fopen(). This pointer
then acts as a reference to that open file.
You use a similar process when working
with databases. First, you have to establish
a connection to the database server—in
this case, MySQL. This connection is then
used as the access point for any future
commands. The syntax for connecting to
a database is
$dbc = mysqli_connect(hostname,
➝ username, password,
➝ database_name);
The database connection—assigned to
$dbc in this example—is normally established using at least four arguments: the
host, which is almost always localhost; the
username; the password for that username; and the database name.
If you’re using a database through a
hosting company, the company will most
likely provide you with all of these values.
If you’re running MySQL on your own
computer, see Appendix A to learn how
you create a user and a database before
proceeding.
Once you’re finished working with a database, you can close the connection, just as
you’d close an open file:
mysqli_close($dbc);
The PHP script will automatically close
the database connection when the script
terminates, but it’s considered good form
to formally close the connection once it’s
no longer needed.
348 Chapter 12
For the first example of this chapter, you’ll
write a simple script that attempts to connect to the MySQL database. Once you
have this connection working, you can
proceed through the rest of the chapter.
Again, you’ll need to already know the
right hostname, username, password, and
database values in order to execute this
example. And the database will need to
have been created!
To connect to a MySQL database:
1. Begin a new PHP document in
your text editor or IDE, to be named
mysqli_connect.php (Script 12.1):
Connect to MySQL
2. Start the section of PHP code:
Successfully
➝ connected to the database!
➝ ';
mysqli_close($dbc);
} else {
print '
➝ Could not connect to the
➝ database.
';
}
Script 12.1 Being able to connect to the MySQL
database is the most important step. This script
tests that process.
1
2
3
4
5
6
7
8
9
10
11
12
Connect to MySQL
Successfully connected to
the database!';
15
16
17
18
19
20
21
22
23
24
25
26
ysqli_close($dbc); // Close the
m
connection.
} else {
print '
Could
not connect to the database.
';
}
?>
By placing the connection attempt as
the condition in an if-else statement,
you make it easy to report on whether
the connection worked.
This chapter will continue to use
username and password as values.
For your scripts, you’ll need to replace
these with the values provided by your
web host or set them when you add
a user using the steps outlined in
Appendix A.
The database being used in this chapter
is named myblog. It will need to be
created prior to executing this script,
either by your hosting company or by
yourself (see Appendix A).
If a connection was established, a
positive message is printed and then
the connection is closed. Otherwise,
a message stating the opposite is
printed, and there is no need to close
the database connection (because it
wasn’t opened).
4. Complete the PHP code and the
HTML page:
?>
continues on next page
Intro to Databases
349
5. Save the file as mysqli_connect.php,
place it in the proper directory of your
PHP-enabled computer, and test it in
your browser A.
If you see results like those in B,
double-check the username and password values. They should match up
with those provided to you by your web
host or those you used to create the
user. You can always test your connection username and password by using
them in the MySQL client (again, see
Appendix A).
A If PHP has support for MySQL and the
username/password/host/database combination
you used was correct, you should see this simple
message.
If you see call to undefined function
mysqli_connect…, your version of PHP
doesn’t support MySQL (see the “MySQL
Support in PHP” sidebar).
B If PHP couldn’t connect to MySQL, you’ll probably see something like this. The warning message may or
may not appear, depending on your error management settings.
350
Chapter 12
The localhost value is used as the
hostname when both the PHP script and the
MySQL database reside on the same computer. You can use PHP to connect to a MySQL
database running on a remote server by
changing the hostname in the PHP script and
creating the proper permissions in MySQL.
PHP has built-in support for most
databases, including MySQL, SQLite,
MongoDB, Oracle, and PostgreSQL. If you’re
using a type of database that doesn’t have
direct support—for example, Access or SQL
Server—you’ll need to use PHP’s ODBC (Open
Database Connectivity) functions along with
that database’s ODBC drivers to interface with
the database.
The combination of using PHP and
MySQL is so common that you may run
across terms that identify servers configured
with both PHP and MySQL: LAMP, MAMP,
and WAMP. These stand for the operating
system—Linux, Mac OS X, or Windows—plus
the Apache web server, the MySQL DBMS,
and PHP.
You’ll be working with MySQL,
so all the functions you use in this chapter
are MySQL specific. For example, to connect
to a database in MySQL the proper function
is mysqli_connect(), but if you’re using
PostgreSQL, you’d instead write
pg_connect(). If you aren’t using a
MySQL DBMS, use the PHP manual (available
through www.PHP.net) to find the appropriate
function names.
You don’t have to select the database
when connecting, but it’s more common to
do so. The most likely exception is if your
application uses multiple databases.
You haven’t done so in these examples,
but in general it’s a good idea to set your
database information—hostname, username,
password, and database name—as variables
or constants. Then you can plug them into the
appropriate functions. By doing so, you can
separate the database specifics from the functionality of the script, allowing you to easily
port that code to other applications.
Intro to Databases
351
MySQL Error Handling
Before this chapter gets too deep into
working with MySQL, it would be best to
discuss some error-handling techniques up
front. Common errors you’ll encounter are
n
Failure to connect to MySQL
n
Inability to run a query
n
No results returned by a query
n
Data not inserted into a table
Experience will teach you why these errors
normally occur, but immediately seeing
what the problem is when running your
scripts can save you much debugging
time. To have your scripts give informative
reports about errors that occur, use the
mysqli_error() function. This function
returns a textual version of the error that
the MySQL server returned. It needs to be
provided with the database connection:
$dbc in this chapter:
print mysqli_error($dbc);
Connection errors are slightly different,
however. To report upon those, invoke
mysqli_connect_error(). This function
does not take any arguments:
print mysqli_connect_error();
Along with these functions, you may want
to use some PHP tools for handling errors.
For beginners, you can start with the error
suppression operator (@). When used preceding a function name, it suppresses any
error messages or warnings the function
might invoke:
@function_name();
352 Chapter 12
Database Permissions
Database permissions are a bit more
complicated than file permissions, but
you need to understand this: Different
types of users can be assigned different database capabilities. For example,
one DBMS user may be able to create
new databases and delete existing ones
(you may have dozens of databases in
your DBMS), but a lower-level user may
only be able to create and modify tables
within a single database. The most basic
user may just be able to read from, but
not modify, tables.
If you’re using PHP and MySQL for a
live hosted site, the hosting company
will most likely give you the second
type of access—control over a single
database but not the DBMS itself—and
establish the initial database for you. If
you’re working on your own server or
have administrative access, you should
have the capability to create new users
and databases.
Script 12.2 By adding error control to the script (the
@ symbol and the mysqli_error() function), you
can more purposefully address problems
that occur.
1
2
3
4
5
6
7
8
9
10
11
12
Connect to MySQL
Successfully connected to
the database!';
15
16
17
18
19
20
21
22
23
24
25
26
mysqli_close($dbc); // Close the
connection.
} else {
rint '
Could not connect to the
database: ' . mysqli_connect_
error() . '.
';
}
?>
Note that this operator doesn’t stop the
error from happening; it just prevents the
message from being immediately displayed. You’d use it in situations where you
intend to handle the error yourself, should
one occur. This is an important point: The
error still happens, so you should use the
error suppression operator only when
you’re handling the error in another way.
To use error handling:
1. Open mysqli_connect.php (Script 12.1)
in your text editor or IDE.
2. Suppress any PHP errors created by the
mysqli_connect() function by changing the if conditional as follows (Script
12.2):
if ($dbc = @mysqli_connect
➝ ('localhost', 'username',
➝ 'password', 'myblog')) {
Rather than have PHP print out an error
message when the mysqli_connect()
function backfires (B in the previous
section, “Connecting to MySQL”), the
message will be suppressed here using
the @ symbol. The errors still occur, but
they’re handled by the change made in
the next step.
3. Add the mysqli_error() function
to the print statement in the else
section:
print '
Could not connect to
➝ MySQL: ' . mysqli_connect_
➝ error() . '.
';
continues on next page
Intro to Databases
353
Instead of printing a message or relying
on whatever error PHP kicks out (see
B in the previous section, “Connecting
to MySQL”), the script now prints the
MySQL error within this context. You
accomplish this by printing some
HTML concatenated with the
mysqli_connect_error() function.
You should note that the
mysqli_connect_error() function is
not provided with the database connection—$dbc—as an argument, since no
database connection was made.
4. Save the file, and test it again in your
browser A.
If there was a problem, this result now
looks better than what would have
been shown previously. If the script
connected, the result is like that
shown in A in the previous section,
“Connecting to MySQL,” because
neither of the error-management tools
is involved.
In this chapter, error messages are
revealed to assist in the debugging process.
Live websites should not have this level of
explicit error messages shown to the user.
The error suppression operator should
be used only in very limited situations—
namely, when you’re handling the error in
other ways. As you build your PHP skills, you’ll
learn more sophisticated approaches for error
management, such as using exceptions and
writing your own error handler.
You may also see code where die(),
which is an alias for exit(), is called when a
connection error occurs. The thinking is that
since a database connection cannot be made,
there’s no point in continuing. In my opinion,
that’s too heavy-handed an approach.
354 Chapter 12
A Using PHP’s error-control functions, you can
adjust how errors are handled.
Creating a Table
Once you’ve created and selected the
initial database, you can begin creating
individual tables in it. A database can
consist of multiple tables, but in this simple
example you’ll create one table in which all
the chapter’s data will be stored.
To create a table in the database, you’ll use
SQL—the language that databases understand. Because SQL is a lot like spoken
English, the proper query to create a new
table reads like this:
CREATE TABLE tablename (column1
➝ definition, column2 definition,
➝ etc.)
For each column, separated by commas,
you first indicate the column name and
then the column type. Common types are
TEXT, VARCHAR (a variable number of characters), DATETIME, and INT (integer).
Because it’s highly recommended that you
create a column that acts as the primary
key (a column used to refer to each row),
a simple CREATE statement could be
CREATE TABLE my_table (
id INT PRIMARY KEY,
information TEXT
)
A table’s primary key is a special column
of unique values that is used to refer to the
table’s rows. The database makes an index
of this column in order to more quickly navigate through the table. A table can have
only one primary key, which you normally
set up as an automatically incremented column of integers. The first row has a key of
1, the second has a key of 2, and so forth.
Referring back to the key always retrieves
the values for that row.
Intro to Databases
355
Finally, it’s a good idea to establish the
default character set when creating a table
(or a database). This is accomplished by
adding CHARACTER SET name at the end of
the table creation statement:
CREATE TABLE my_table (
id INT PRIMARY KEY,
information TEXT
) CHARACTER SET utf8
Like the charset meta tag in HTML, this is
merely an indication of what encoding to
use for the stored characters. You almost
certainly want to use utf8 here.
You can visit the MySQL website for more
information on SQL, column definitions,
and character sets. By following the directions in this section, though, you should be
able to accomplish some basic database
tasks. The table that you’ll create in this
example is represented by Table 12.2.
In this example, you’ll create the database
table that will be used to store information
submitted via an HTML form. In the next
section of the chapter, you’ll write the script
that inserts the submitted data into the
table created here.
To create the table with PHP, you use the
mysqli_query() function to execute a
CREATE TABLE SQL command:
mysqli_query($dbc, 'CREATE TABLE
➝ entries...');
Alternatively, you can execute that same
SQL command via another interface, such
as the command-line MySQL client or the
web-based phpMyAdmin.
356 Chapter 12
TABLE 12.1 The ENTRIES Table
Column Name
Column Type
id
Positive, non-null,
automatically incrementing
integer
Title
Text up to 100 characters
in length
Entry
Text of any length
date_entered
A timestamp including both
the date and the time the row
was added
Script 12.3 To create a database table, define the
appropriate SQL statement and then invoke the
mysqli_query() function.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Create a Table
The table has been
created!';
} else {
print '
Could not create the
table because: ' . mysqli_
error($dbc) . '.
The
query being run was: ' . $query
. '
';
}
mysqli_close($dbc); // Close the
connection.
} else { // Connection failure.
print '
Could
not connect to the database: ' .
mysqli_connect_error() . '.
';
}
?>
To create a new table:
1. Begin a new PHP document in your
text editor or IDE, to be named
create_table.php (Script 12.3):
Create a Table
2. Begin a section of PHP code:
The table has been
➝ created.';
} else {
print '
Could not create the
➝ table because: ' . mysqli_
➝ error($dbc) . '.
The
➝ query being run was: ' .
➝ $query . '
';
}
To create the table, call the
mysqli_query() function using the
database connection as the first argument and the query variable—$query—
as the second. If a problem occurred,
the MySQL error is printed, along with
the value of the $query variable. This
last step—printing the actual query
being executed—is a particularly useful
debugging technique A.
A If the query caused an error, the MySQL error will be reported and the query
itself displayed (for debugging purposes).
358 Chapter 12
6. Close the database connection, and
complete the $dbc conditional:
B If all went well, all you’ll see is this message.
mysqli_close($dbc);
} else { // Connection failure.
print '
Could not connect to
➝ the database: ' . mysqli_
➝ connect_error() . '.
';
7. Complete the PHP code and the
HTML page:
?>
8. Save the script as create_table.php,
place it in the proper directory for your
PHP-enabled server, and test it in your
browser B.
It’s not necessary to write your SQL
keywords in all capital letters as I do here, but
doing so helps distinguish the SQL terms from
the table and column names.
On larger web applications, I highly
recommended that you place the database
connection code in a separate file, located outside the web directory. Then, each page that
requires the database can include this external
file. You’ll see an example of this in Chapter 13,
“Putting It All Together.”
The mysqli_query() function returns
TRUE if a query was successfully run on a
database. That result doesn’t necessarily
mean the desired result occurred.
This chapter presents the basics of
MySQL- and SQL-related knowledge (including
column types). You’ll want to check out other
resources—listed in Appendix B—once you’re
comfortable with the fundamentals.
You wouldn’t normally use a PHP script
to create a table, just as you wouldn’t normally
create a database using a PHP script, but
when you’re just starting with MySQL, this is
an easy way to achieve the desired results.
Intro to Databases
359
Inserting Data
into a Database
As mentioned, this database will be used
as a simple blog, an online journal. Blog
entries—consisting of a title and text—will
be added to the database using one page
and then displayed on another page.
The last script created the table, which
consists of four columns: id, title, entry,
and date_entered. The process of adding
information to a table is similar to creating
the table itself in terms of which PHP functions you use, but the SQL query is different.
To insert records, use the INSERT SQL command with either of the following syntaxes:
INSERT INTO tablename VALUES
➝ (value1, value2, value3, etc.)
INSERT INTO tablename
➝ (column1_name, column2_name)
➝ VALUES (value1, value2)
The query begins with INSERT INTO
tablename. Then you can either specify
which columns you’re inserting values for
or not name the columns explicitly. The
former is more specific and is therefore
preferred, but it can be tedious if you’re
populating a slew of columns. In either
case, you must be certain to list the right
number of total values and the right type
of value for each column.
The values are placed within parentheses,
with each value separated by a comma.
Non-numeric values—strings and dates—
need to be quoted, whereas numbers do
not:
INSERT INTO example (name, age)
➝ VALUES ('Jonah', 1)
The query is executed using the
mysqli_query() function. Because INSERT
queries can be complex, it makes sense to
assign each query to a variable and send
that variable to the mysqli_query() function (as previously demonstrated).
To demonstrate, let’s create a page that
adds blog entries to the database. Like
many of the examples in the preceding
chapter, this one will both display and
handle the HTML form. Before getting into
the example, though, I’ll say that this script
knowingly has a security hole in it; it’ll be
explained and fixed in the next section of
the chapter.
Building on This Example
The focus in this chapter is on explaining
and demonstrating the basics of using
PHP with MySQL. This also includes the
core components of SQL. However, this
chapter’s examples do a few things that
you wouldn’t want to do in a real site,
such as allow anyone to insert, edit, and
delete database records.
In the next chapter, a different example
will be developed that is also database
driven. That example will use cookies to
restrict what users can do with the site.
360
Chapter 12
To enter data into a database
from an HTML form:
1. Begin a new PHP document in your
text editor or IDE, to be named
add_entry.php (Script 12.4):
Add a Blog Entry
Add a Blog Entry
continues on next page
Script 12.4 The query statement for adding information to a database is straightforward enough, but be sure
to match the number of values in parentheses to the number of columns in the database table.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Add a Blog Entry
Add a Blog Entry
Please submit both a title and an entry.';
$problem = TRUE;
}
if (!$problem) {
// Connect and select:
$dbc = mysqli_connect('localhost', 'username', 'password', 'myblog');
code continues on next page
Intro to Databases
361
2. Create the initial PHP section, and
check for the form submission:
Please submit both a
➝ title and an entry.';
$problem = TRUE;
}
Before you use the form data in an INSERT
query, it ought to be validated. Just a
minimum of validation is used here, guaranteeing that some values are provided.
If so, new variables are assigned those
values, after trimming away extraneous
spaces and applying strip_tags() (to prevent cross-site scripting attacks and other
potential problems). If either of the values
was empty, an error message is printed A,
and the $problem flag variable is set to
TRUE (because there is a problem).
Script 12.4 continued
29
30
// Define the query:
query = "INSERT INTO entries (id, title, entry, date_entered) VALUES (0,
$
'$title', '$entry', NOW())";
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// Execute the query:
f (@mysqli_query($dbc, $query)) {
i
print '
The blog entry has been added!
';
} else {
print '
Could not add the entry because: ' . mysqli_
error($dbc) . '.
The query being run was: ' . $query . '
';
}
mysqli_close($dbc); // Close the connection.
} // No problem!
} // End of form submission IF.
// Display the form:
?>
Entry Title:
Entry Text:
362 Chapter 12
4. Connect to the database:
if (!$problem) {
$dbc = mysqli_connect
➝ ('localhost', 'username',
➝ 'password', 'myblog');
A The PHP script performs some basic form
validation so that empty records are not inserted
into the database.
Having basically valid data, it’s safe to
add the record to the database, so a
connection must be established. At this
point, if you’re running these examples
in order, I’ll assume you have a working connection and selection process
down, so I’ll dispense with all the conditionals and error reporting (mostly to
shorten the script). If you have problems
connecting to and selecting the database, apply the code already outlined in
the chapter.
5. Define the INSERT query:
$query = "INSERT INTO entries
➝ (id, title, entry, date_
➝ entered) VALUES (0, '$title',
➝ '$entry', NOW())";
The query begins with the necessary
INSERT INTO tablename code. Then it
lists the columns for which values will be
submitted. After that is VALUES, followed
by four values—one for each column,
in order—separated by commas. When
assigning this query to the $query variable, use double quotation marks so that
the values of the variables will be automatically inserted by PHP. The $title
and $entry variables are strings, so
they must be placed within single quotation marks in the query itself.
continues on next page
Intro to Databases
363
Because the id column has been set
to AUTO_INCREMENT, you can use 0 as
the value and MySQL will automatically use the next logical value for that
column. You can also use the special
keyword NULL. To set the value of the
date_entered column, use the MySQL
NOW() function. It inserts the current
time as that value.
6. Run the query on the database:
if (@mysqli_query($dbc, $query)) {
print '
The blog entry has
➝ been added!
';
} else {
print '
Could not add the
➝ entry because: ' .
➝ mysqli_ error($dbc) . '.
➝
The query being run
➝ was: ' . $query . '
';
}
The query, once defined, is run using
the mysqli_query() function. By calling
this function as the condition of an
if-else statement, you can print
simple messages indicating the result
of the query execution.
As an essential debugging tool, if the
query didn’t run properly, the MySQL
error and the query being run are both
printed to the browser B.
7. Close the database connection, the
$problem conditional, and complete the
main conditional and the PHP section:
mysqli_close($dbc);
} // No problem!
} // End of form submission IF.
?>
From here on out, the form will be
displayed.
8. Create the form:
Entry
Title:
Entry Text:
B If the INSERT query didn’t work, the MySQL error is printed out along with the
query that was run.
364 Chapter 12
The HTML form is very simple, requiring
only a title for the blog entry and the
entry itself. As a good rule of thumb,
use the same name for your form inputs
as for the corresponding column names
in the database. Doing so makes errors
less likely.
9. Finish the HTML page:
C This is the form for adding an entry to the
database.
10. Save the script as add_entry.php,
place it in the proper directory for your
PHP-enabled server, and test it in your
browser C and D.
You should probably avoid using
apostrophes in your form values or you
might see results like those in B. You’ll
find the explanation and solution in the
next section.
To retrieve the automatically incremented
number created for an AUTO_INCREMENT column, call the mysqli_insert_id() function.
Because of the way auto-incrementing
primary keys work, this query is also fine:
D If the INSERT query ran properly, a message is
printed and the form is displayed again.
INSERT INTO entries (title, entry,
➝ date_entered) VALUES ('$title',
➝ '$entry', NOW())";
MySQL allows you to insert several
records at once, using this format:
INSERT INTO tablename
➝ (column1_name, column2_name)
➝ VALUES (value1, value2), (value3,
➝ value4);
Most other database applications don’t support
this construct, though.
Intro to Databases
365
Securing Query Data
as the blog post title, the resulting query
would be
As I mentioned in the introduction to the
section “Inserting Data into a Database,”
the code as written has a pretty bad security hole in it. As it stands, if someone
submits text that contains an apostrophe,
that data will break the SQL query A
(security concerns aside, it’s also a pretty
bad bug). The result is obviously undesirable, but why is it insecure?
INSERT INTO entries
➝ (id, title, entry, date_entered)
➝ VALUES (0, '';DROP TABLE
➝ entries;', '', NOW())
If malicious users know they can break a
query by typing an apostrophe, they may try
to run their own queries using this hole. If
someone submitted ‘;DROP TABLE entries;
The initial apostrophe in the provided entry
title has the effect of completing the blog
title value part of the query. The semicolon
then terminates the INSERT query itself.
This will make the original query syntactically invalid. Then the database will be
provided with a second query—DROP TABLE
entries—with the hope that it will be executed when the original INSERT query fails.
A The poor handling of apostrophes allows users to break the query
because apostrophes (or single quotation marks) are used to delimit strings
used in queries.
366 Chapter 12
This is known as an SQL injection attack,
but fortunately it’s easy to prevent.
To do so, send potentially insecure data
to be used in a query through the
mysqli_real_escape_string() function.
This function will escape—preface with a
backslash—any potentially harmful characters, making the data safe to use in a
query:
$var = mysqli_real_escape_string
➝ ($dbc, $var);
For this function to work properly, the
character set needs to be established for
the communications:
mysqli_set_charset($dbc, 'utf8')
This code effectively serves the same
purpose as the charset meta tag in HTML:
indicating the character set—or character
encoding—of the data to follow. The previous code does assume your PHP script,
database, and table are all using UTF-8,
which they really ought to be by default (and
was specifically established on the table
when it was created, just to be certain).
Showing MySQL Errors
Even if MySQL doesn’t execute an
injected SQL command (normally MySQL
will only run a single SQL query sent
through the mysqli_query() function),
hackers will provide bad characters in
form data in the hopes that the syntactically broken query generates a database
error. By seeing the database error,
the hacker seeks to gain knowledge
about the database that can be used for
malicious purposes. For this reason, it’s
imperative that a live site never reveal
the actual MySQL errors or queries being
executed. The scripts in this chapter
do so only for your own debugging
purposes.
Let’s apply this function to the
preceding script. Because both
mysqli_real_escape_string() and
mysqli_set_charset() require the data-
base connection, the logic of the script
must be tweaked a bit.
Intro to Databases
367
To secure query data:
1. Open add_entry.php (Script 12.4) in
your text editor or IDE, if it is not already
open.
2. Update the assignment of the $title
and $entry variables to read (Script
12.5) as follows:
$title = mysqli_real_escape_
➝ string($dbc, trim(strip_tags
➝ ($_POST['title'])));
$entry = mysqli_real_escape_
➝ string($dbc, trim(strip_tags
➝ ($_POST['entry'])));
These two lines will greatly improve
the security and functionality of the
script. For both posted variables, their
values are first trimmed and stripped of
tags, then sent through mysqli_real_
escape_string(). The result will be
safe to use in the query.
If the application of three functions to
one variable is too confusing for you,
you can separate the code into discrete
steps:
$title = $_POST['title'];
$title = trim(strip_tags
➝ ($title));
$title = mysqli_real_escape_
➝ string($dbc, $title);
3. Move the database connection code—
line 27 in Script 12.4—to above the
validation lines.
The database connection should be
established within the form handling
code, but before $problem = FALSE;.
continues on page 370
Script 12.5 To better secure the web application and the database, the mysqli_real_escape_string()
function is applied to the form data used in the query.
1
2
3
4
5
6
7
8
9
10
11
12
13
Add a Blog Entry
Add a Blog Entry
Please submit both a title and an entry.';
$problem = TRUE;
}
if (!$problem) {
// Define the query:
$query = "INSERT INTO entries (id, title, entry, date_entered) VALUES (0, '$title',
'$entry', NOW())";
// Execute the query:
if (@mysqli_query($dbc, $query)) {
print '
The blog entry has been added!
';
} else {
print '
Could not add the entry because: ' . mysqli_
error($dbc) . '.
The query being run was: ' . $query . '
';
}
} // No problem!
mysqli_close($dbc); // Close the connection.
} // End of form submission IF.
// Display the form:
?>
Entry Title:
Entry Text:
Intro to Databases
369
4. Move the database closing code—
line 39 in Script 12.4—to just before
the close of the form submission
conditional.
Because the database connection is
opened first thing within the form handling conditional, the database connection should be closed as the last step
within that same block.
5. After opening the database connection,
identify the character set in use:
mysqli_set_charset($dbc, 'utf8');
B Now apostrophes in form data…
This needs to be done before
mysqli_real_escape_string()
is invoked.
6. Save the script, place it on your PHPenabled server, and test it in your
browser B and C.
PHP’s addslashes() function works
similarly to mysqli_real_escape_string()
but is not nearly as secure.
370 Chapter 12
C …will not cause problems.
Retrieving Data
from a Database
The next process this chapter demonstrates is retrieving data from a populated
table. You still use the mysqli_query()
function to run the query, but retrieving
data is slightly different than inserting
data—you have to assign the query result
to a variable and then use another function
to fetch the data.
The basic syntax for retrieving data is the
SELECT query:
SELECT what columns FROM what table
The easiest query for reading data from a
table is
SELECT * FROM tablename
The asterisk is the equivalent of saying
every column. If you require only certain
columns to be returned, you can limit your
query, like so:
SELECT name, email FROM users
That query requests that only the information from two columns—name and
email—be gathered. Keep in mind that
this structure doesn’t limit what rows (or
records) are returned, just what columns
for those rows.
Another way to alter your query is to add
a conditional restricting which rows are
returned, accomplished using a WHERE
clause:
SELECT * FROM users WHERE name=
➝ 'Larry'
Here you want the information from every
column in the table, but only from the rows
where the name column is equal to Larry.
This is a good example of how SQL uses
only a few terms effectively and flexibly.
The main difference in retrieving data
from a database as opposed to inserting
data into a database is that you need to
handle the query differently. You should
first assign the results of the query to
a variable:
$result = mysqli_query($dbc,
➝ $query);
Just as $dbc is a reference to an open
database connection, $result is a reference to a query result set. This variable
is then provided to the mysqli_fetch_
array() function, which retrieves the
query results:
$row = mysqli_fetch_array($result);
The function fetches one row from the
result set at a time, creating an array
in the process. The array will use the
selected column names as its indexes:
$row['name'], $row['email'], and so on.
As with any array, you must refer to the
columns exactly as they’re defined in the
database (the keys are case-sensitive).
So, in this example, you must use
$row['email'] instead of $row['Email'].
If the query will return multiple rows,
execute the mysqli_fetch_array()
function within a loop to access them all:
while ($row = mysqli_fetch_
➝ array($result)) {
//
Do something with $row.
}
continues on next page
Intro to Databases
371
With each iteration of the loop, the next
row of information from the query (referenced by $result) is assigned to an array
named $row. This process continues until
no more rows of information are found.
Within the loop, you would do whatever
you want with $row.
The best way to understand this new code
is to try it. You’ll write a script that retrieves
the posts stored in the entries table and
displays them A. You may want to run
through add_entry.php a couple of more
times to build up the table first.
A This dynamic web page uses PHP to pull data
from a database.
To retrieve data from a table:
1. Begin a new PHP document in your
text editor or IDE, to be named
view_entries.php (Script 12.6):
View My Blog
My Blog
Script 12.6 The SQL query for retrieving all data from a table is quite simple, but in order for PHP to access
every returned record, you must loop through the results one row at a time.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
View My Blog
Could not retrieve the data because: ' . mysqli_
error($dbc) . '.
The query being run was: ' . $query . '
';
} // End of query IF.
mysqli_close($dbc); // Close the connection.
?>
Intro to Databases
373
5. Print out the returned results:
while ($row = mysqli_fetch_
➝ array($r)) {
print "
{$row['title']}
➝
{$row['entry']} EditDelete\n";
}
This loop sets the variable $row to
an array containing the first record
returned in $r. The loop then executes
the following command (the print
statement). Once the loop gets back to
the beginning, it assigns the next row,
if it exists. It continues to do this until
there are no more rows of information
to be obtained.
Within the loop, the array’s keys are the
names of the columns from the table—
hence, id, title, and entry (it’s not
printing out the date_entered).
At the bottom of each post, two links
are created: to edit_entry.php and
delete_entry.php. These scripts will
be written in the rest of the chapter.
Each link passes the posting’s database
ID value along in the URL. That information will be necessary for those other
two pages to edit and delete the blog
posting accordingly.
374
Chapter 12
B Thanks to the SELECT query, which orders the
returned records by the date they were entered,
the most recently added entry is always listed first.
6. Handle the errors if the query didn’t run:
} else { // Query didn't run.
print '
➝ Could not retrieve the
➝ data because: ' .
➝ mysqli_error($dbc) . '.
➝
The query being run
➝ was: ' . $query . '
';
} // End of query IF.
If the query couldn’t run on the database, it should be printed out, along
with the MySQL error (for debugging
purposes).
7. Close the database connection:
mysqli_close($dbc);
8. Complete the PHP section and the
HTML page:
?>
9. Save the script as view_entries.php,
place it in the proper directory for your
PHP-enabled server, and test it in your
browser A.
10. If you want, add another record to the
blog using the add_entry.php page
(Script 12.6), and run this page again B.
11. Check the source code of the page to
see the dynamically generated links C.
The mysqli_fetch_array() function
takes another argument, which is a constant indicating what kind of array should be
returned. MYSQLI_ASSOC returns an associative array, whereas MYSQLI_NUM returns a
numerically indexed array.
The mysqli_num_rows() function
returns the number of records returned by a
SELECT query.
It’s possible to paginate returned records
so that 10 or 20 appear on each page (like the
way Google works). Doing so requires more
advanced coding than can be taught in this
book, though. See my book PHP and MySQL
for Dynamic Web Sites: Visual QuickPro Guide
(Peachpit Press, 2012), or look online for code
examples and tutorials.
C Part of the HTML source of the page. Note that the two links have ?id=X
appended to each URL.
Intro to Databases
375
Deleting Data in
a Database
Sometimes you might also want to run a
DELETE query on a database. Such a query
removes records from the database. The
syntax for a delete query is
DELETE FROM tablename WHERE
➝ column=value
The WHERE clause isn’t required, but if it’s
omitted, you’ll remove every record from
the table. You should also understand that
once you delete a record, there’s no way
to recover it (unless you have a backup of
the database).
As a safeguard, if you want to delete only
a single record from a table, add the LIMIT
clause to the query:
A When the user arrives at this page, the
blog entry is shown, and the user must confirm
deleting it.
DELETE FROM tablename WHERE
➝ column=value LIMIT 1
This clause ensures that only one record
is deleted at most. Once you’ve defined
your query, it’s again executed using the
mysqli_query() function, like any other
query.
To see if a DELETE query worked, you can
use the mysqli_affected_rows() function. This function returns the number of
rows affected by an INSERT, DELETE, or
UPDATE query. It takes the database connection as an argument.
As an example, let’s write the delete_
entry.php script, which is linked from the
view_blog.php page. This page receives
the database record ID in the URL. It then
displays the entry to confirm that the user
wants to delete it A. If the user clicks the
button, the record will be deleted B.
376
Chapter 12
B If the delete query worked properly, the
user sees this result.
To delete data from a database:
1. Begin a new PHP document in your
text editor or IDE, to be named
delete_entry.php (Script 12.7):
Delete a Blog Entry
➝
Delete an Entry
2. Start the PHP code, and connect to the
database:
Delete a Blog Entry
Delete an Entry
Are you sure you want to delete this entry?
' . $row['title'] . '
' .
$row['entry'] . '
';
} else { // Couldn't get the information.
print '
Could not retrieve the blog entry because: ' . mysqli_
error($dbc) . '.
The query being run was: ' . $query . '
';
}
} elseif (isset($_POST['id']) && is_numeric($_POST['id'])) { // Handle the form.
// Define the query:
query = "DELETE FROM entries WHERE id={$_POST['id']} LIMIT 1";
$
$r = mysqli_query($dbc, $query); // Execute the query.
// Report on the result:
f (mysqli_affected_rows($dbc) == 1) {
i
print '
The blog entry has been deleted.
';
} else {
print '
Could not delete the blog entry because: ' .
mysqli_error($dbc) . '.
The query being run was: ' . $query . '
';
}
} else { // No ID received.
print '
This page has been accessed in error.
';
} // End of main IF.
mysqli_close($dbc); // Close the connection.
?>
Chapter 12
3. If the page received a valid entry ID in
the URL, define and execute a SELECT
query:
if (isset($_GET['id']) && is_
➝ numeric ($_GET['id']) ) {
$query
= "SELECT title,
➝ entry FROM entries WHERE
➝ id={$_GET['id']}";
if ($r = mysqli_query($dbc,
➝ $query)) {
To display the blog entry, the page must
confirm that a numeric ID is received
by the page. Because that value should
first come in the URL (when the user
clicks the link in view_blog.php, see C
in the previous section, “Retrieving
Data from a Database”), you reference
$_GET['id']. The use of is_numeric()
here does more than just ensure a
record can be retrieved; it’s also an
important security measure. Because
the $_GET['id'] value is used directly
in the query—without quotes—testing
that value against is_numeric() prevents the query from breaking or being
used in an attack.
The query is like the SELECT query used
in the preceding example, except that
the WHERE clause has been added to
retrieve a specific record. Also, because
only the two stored values are necessary—the title and the entry itself—only
those are being selected.
This query is then executed using the
mysqli_query() function.
4. Retrieve the record, and display the
entry in a form:
$row = mysqli_fetch_array($r);
print '
Are you sure you want to
➝ delete this entry?
' . $row['title'] .
➝ '
' .
$row['entry'] . '
';
Instead of retrieving all the records
using a while loop, as you did in the
previous example, use one call to the
mysqli_fetch_array() function to
assign the returned record to the $row
variable. Using this array, the record to
be deleted can be displayed.
The form first shows the blog entry
details, much as it did in the
view_entries.php script. When the
user clicks the button, the form will be
submitted back to this page, at which
point the record should be deleted. In
order to do so, the blog identification
number, which is passed to the script
as $_GET['id'], must be stored in
a hidden input so that it exists in the
$_POST array upon submission (because
$_GET['id'] won’t have a value at
that point).
continues on next page
Intro to Databases
379
5. Report an error if the query failed:
} else { // Couldn't get the
➝ information.
print '
➝ Could not retrieve the blog
➝ entry because: ' . mysqli_
➝ error($dbc) . '.
The
➝ query being run was: ' .
$query . '
';
}
If the SELECT query failed to run, the
MySQL error and the query itself are
printed out.
6. Check for the submission of the form:
} elseif (isset($_POST['id']) &&
➝ is_numeric($_POST['id'])) { //
➝ Handle the form.
This elseif clause is part of the conditional begun in Step 3. It corresponds
to the second usage of this same
script (the form being submitted). If this
conditional is TRUE, the record should
be deleted.
7. Define and execute the query:
$query = "DELETE FROM entries
➝ WHERE id={$_POST['id']} LIMIT
➝ 1";
$r = mysqli_query($dbc, $query);
This query deletes the record whose
id has a value of $_POST['id']. The ID
value comes from the form, where it’s
stored as a hidden input. By adding the
LIMIT 1 clause to the query, you can
guarantee that only one record, at most,
is removed.
380 Chapter 12
8. Check the result of the query:
if (mysqli_affected_rows($dbc)
➝ == 1) {
print
'
The blog entry has
➝ been deleted.
';
} else {
print '
➝ Could not delete the blog
➝ entry because: ' . mysqli_
➝ error($dbc) . '.
The
➝ query being run was: ' .
➝ $query . '
';
}
The mysqli_affected_rows() function
returns the number of rows altered by
the most recent query. If the query ran
properly, one row was deleted, so this
function should return 1. If so, a message is printed. Otherwise, the MySQL
error and query are printed for debugging purposes.
9. Complete the main conditional:
} else { // No ID received.
print '
➝ This page has been accessed
➝ in error.
';
} // End of main IF.
If no numeric ID value was passed to
this page using either the GET method
or the POST method, then this else
clause takes effect C.
10. Close the database connection, and
complete the page:
mysqli_close($dbc);
?>
C If the script does not receive an id
value in the URL, an error is reported.
11. Save the script as delete_entry.php,
place it in the proper directory for your
PHP-enabled server, and test it in your
browser A and B.
To test this script, you must first run
view_entries.php. Then, click one
of the Delete links to access
delete_entry.php.
You can empty a table of all of its records
by running the query TRUNCATE TABLE
tablename. This approach is preferred over
using DELETE FROM tablename. TRUNCATE
will completely drop and rebuild the table,
which is better for the database.
It’s a fairly common error to try to run
the query DELETE * FROM tablename, like a
SELECT query. Remember that DELETE doesn’t
use the same syntax as SELECT, because you
aren’t deleting specific columns.
Intro to Databases
381
Updating Data
in a Database
The final type of query this chapter will
cover is UPDATE. It’s used to alter the values of a record’s columns. The syntax is
UPDATE tablename SET
➝ column1_name=value,
➝ column2_name=value2 WHERE
➝ some_column=value
As with any other query, if the values are
strings, they should be placed within single
quotation marks:
UPDATE users SET first_name=
➝ 'Eleanor', age=7 WHERE user_id=142
A When the user arrives at the edit page, the
form is shown with the existing values.
As with a DELETE query, you should use
a WHERE clause to limit the rows that are
affected. If you don’t do this, every record
in the database will be updated.
To test that an update worked, you can
again use the mysqli_affected_rows()
function to return the number of
records altered.
To demonstrate, let’s write a page for
editing a blog entry. It will let the user
alter an entry’s title and text, but not the
date entered or the blog ID number (as a
primary key, the ID number should never
be changed). This script will use a structure
like that in delete_entry.php (Script 12.7),
first showing the entry A and then handling
the submission of that form B.
382
Chapter 12
B Upon submitting the form, the user
sees a message like this.
To update data in a database:
1. Begin a new PHP document in
your text editor or IDE, to be named
edit_entry.php (Script 12.8).
Edit a Blog Entry
➝ title>
Edit an Entry
2. Start your PHP code and connect to the
database:
Edit a Blog Entry
Edit an Entry
Entry Title:
Entry Text:
';
} else { // Couldn't get the information.
print '
Could not retrieve the blog entry because: ' .
mysqli_error($dbc) . '.
The query being run was: ' . $query . '
';
}
} elseif (isset($_POST['id']) && is_numeric($_POST['id'])) { // Handle the form.
// Validate and secure the form data:
$problem = FALSE;
if (!empty($_POST['title']) && !empty($_POST['entry'])) {
$title = mysqli_real_escape_string($dbc, trim(strip_tags($_POST['title'])));
$entry = mysqli_real_escape_string($dbc, trim(strip_tags($_POST['entry'])));
} else {
print '
Please submit both a title and an entry.
';
$problem = TRUE;
}
if (!$problem) {
// Define the query.
query = "UPDATE entries SET title='$title', entry='$entry' WHERE
$
id={$_POST['id']}";
$r = mysqli_query($dbc, $query); // Execute the query.
// Report on the result:
if (mysqli_affected_rows($dbc) == 1) {
print '
The blog entry has been updated.
';
} else {
print '
Could not update the entry because: ' .
mysqli_error($dbc) . '.
The query being run was: ' . $query . '
';
}
} // No problem!
} else { // No ID set.
print '
This page has been accessed in error.
';
} // End of main IF.
mysqli_close($dbc); // Close the connection.
?>
384 Chapter 12
3. If the page received a valid entry ID in
the URL, define and execute a SELECT
query:
if (isset($_GET['id']) &&
➝ is_numeric($_GET['id']) ) {
$query
= "SELECT title,
➝ entry FROM entries WHERE
➝ id={$_GET['id']}";
if ($r = mysqli_query($dbc,
➝ $query)) {
This code is exactly the same as that
in the delete page; it selects the two
column values from the database for
the provided ID value.
4. Retrieve the record, and display the
entry in a form:
$row = mysqli_fetch_array($r);
print '
Entry Title:
Entry Text:
';
Again, this is almost exactly the same
as in the preceding script, including
the most important step of storing the
ID value in a hidden form input. Here,
though, the stored data isn’t just printed
but is actually used as the values for
form elements. For security and to
avoid potential conflicts, each value is
run through htmlentities() first.
5. Report an error if the query failed:
} else { // Couldn't get the
➝ information.
print
'
➝ Could not retrieve the blog
➝ entry because: ' .
➝ mysqli_error($dbc) . '.
➝
The query being run
➝ was: ' . $query . '
';
}
6. Check for the submission of the form:
} elseif (isset($_POST['id']) &&
➝ is_numeric($_POST['id'])) {
This conditional will be TRUE when the
form is submitted.
7. Validate and secure the form data:
$problem = FALSE;
if (!empty($_POST['title']) &&
➝ !empty($_POST['entry'])) {
$title
= mysqli_real_escape_
➝ string($dbc, trim(strip_tags
➝ ($_POST ['title'])));
$entry = mysqli_real_escape_
➝ string($dbc, trim(strip_tags
➝ ($_POST ['entry'])));
} else {
print '
➝ Please submit both a title
➝ and an entry.
';
$problem = TRUE;
}
This code comes from the page used to
add blog postings. It performs minimal
validation on the submitted data and
then runs it through the mysqli_real_
escape_string() function to be safe.
Because the form data can be edited,
the form should be validated as if it
were a new record being created.
continues on next page
Intro to Databases
385
8. Define and execute the query:
if (!$problem) {
$query = "UPDATE entries
➝ SET title='$title',
➝ entry='$entry' WHERE id=
➝ {$_POST['id']}";
$r = mysqli_query($dbc,
➝ $query);
The UPDATE query sets the title
column equal to the value entered
in the form’s title input and sets the
entry column equal to the value
entered in the form’s entry text area.
Only the record whose id is equal
to $_POST['id'], which comes from
a hidden form input, is updated.
9. Report on the success of the query:
if (mysqli_affected_rows($dbc)
➝ == 1) {
print '
The blog entry has
➝ been updated.
';
} else {
print '
➝ Could not update the entry
➝ because: ' . mysqli_ error
➝ ($dbc) . '.
The query
➝ being run was: ' . $query .
➝ '
';
}
If one row was affected, then a success
message is returned. Otherwise, the
386
Chapter 12
MySQL error and the query are sent to
the browser.
10. Complete the conditionals:
} // No problem!
} else { // No ID set.
print '
➝ This page has been accessed
➝ in error.
';
} // End of main IF.
If no numeric ID value was passed to
this page using either the GET method
or the POST method, then this else
clause takes effect.
11. Close the database connection, and
complete the page:
mysqli_close($dbc);
?>
12. Save the file as edit_entry.php,
place it in the proper directory for your
PHP-enabled server, and test it in your
browser A and B.
As in the preceding example, to edit an
entry, you must click its Edit link in the
view_blog.php page.
13. Revisit view_blog.php to confirm that
the changes were made C.
C Reloading the view_blog.php script reflects
the changes made to the entries.
The id is a primary key, meaning that its
value should never change. By using a primary
key in your table, you can change every other
value in the record but still refer to the row
using that column.
The mysqli_real_escape_string()
function does not need to be applied to the ID
values used in the queries, because the is_
numeric() test confirms they don’t contain
apostrophes or other problematic characters.
More thorough edit and delete pages
would use the mysqli_num_rows() function
in a conditional to confirm that the SELECT
query returned a row prior to fetching it:
if (mysqli_num_rows($r) == 1) {...
If you run an update on a table but
don’t change a record’s values, mysqli_
affected_rows() will return 0.
It can’t hurt to add a LIMIT 1 clause to
an UPDATE query, to ensure that only one row,
at most, is affected.
A common beginner’s mistake is to use
the following erroneous syntax:
UPDATE tablename SET column1_name=
WHERE
➝ value AND column2_name=value2
➝ some_column=value
Note the improper AND in that example!
Intro to Databases
387
Review and Pursue
If you have any problems with the
review questions or the pursue prompts,
turn to the book’s supporting forum
(www.LarryUllman.com/forums/).
Pursue
n
n
Review
n
n
n
n
n
n
n
What version of MySQL are you using?
What values do you personally use to
connect to MySQL?
How does a PHP script connect to a
MySQL server? How does it disconnect?
What is the error suppression operator?
What does it do?
What function returns MySQLreported errors?
What debugging techniques should
you use when having problems with a
PHP script that interacts with MySQL?
What SQL command is used to create
a table? To add new records? To
retrieve records? To modify records?
To remove records?
What function should string values
be run through to prevent SQL
injection attacks?
388
Chapter 12
n
n
Find the version of the MySQL manual
that corresponds to your version of
MySQL. Start reading!
Move the code for connecting to the
database to a separate script, then
include that script in the PHP pages that
interact with the database. Don’t forget
about setting the character set.
Make the add_entry.php form sticky.
Change the code in view_entries.php
so that it converts newline characters in
each entry into HTML break tags.
13
Putting It
All Together
The 12 chapters to this point have covered
all the fundamentals of using PHP for web
development. In this chapter, you’ll use
your accumulated knowledge to create
a complete and functional website. And
even though the focus of this chapter is on
applying your newfound knowledge, you’ll
still learn a few new tricks. In particular,
you’ll see how to develop a full-scale web
application from scratch.
In This Chapter
Getting Started
390
Connecting to the Database
392
Writing the User-Defined Function
393
Creating the Template
396
Logging In
400
Logging Out
404
Adding Quotes
405
Listing Quotes
409
Editing Quotes
412
Deleting Quotes
418
Creating the Home Page
422
Review and Pursue
426
Getting Started
The first step when starting any project is
identifying the site’s goals. The primary goal
of this chapter is to apply everything taught
in the book thus far (a lofty aim, to be sure).
The example for doing so combines ideas
from the previous two chapters, creating
a site that will store and display quotations. Instead of using a file to do so, as in
Chapter 11, “Files and Directories,” this site
will use a MySQL database as the storage
repository. But as with the blog example
from Chapter 12, “Intro to Databases,” the
ability to create, edit, and delete quotations
will be implemented. Further, the public
user will be able to view the most recent
quotation by default A, or a random one,
or a random quotation previously marked
as a favorite.
For improved security, the site will have an
administrator who can log in and log out.
And only the logged-in administrator will
be allowed to create, edit, or delete quotations B.
A The site’s simple home page.
390
Chapter 13
The site will use a simple template to give
every page a consistent look, with CSS
handling all the formatting and layout. The
site will also use one user-defined function,
stored in an included file.
As in Chapter 12, you must first create the
database and its one table. You can do
so using the instructions in Appendix A,
“Installation and Configuration.”
The database will be named myquotes (or
something else if you’d rather). You create
its one table with this SQL command:
CREATE TABLE quotes (
id
INT UNSIGNED NOT NULL
➝ AUTO_INCREMENT,
quote TEXT NOT NULL,
source VARCHAR(100) NOT NULL,
favorite TINYINT(1) UNSIGNED NOT
➝ NULL,
date_entered TIMESTAMP NOT NULL
➝ DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) CHARACTER SET utf8
B Nonadministrators are denied access to certain
pages.
The id is the primary key, and it will
automatically be incremented to the next
logical value with each new submission.
The quote field stores the quote itself,
with the source field storing the attribution (unlike in Chapter 11, where the quote
and the source were stored together). The
favorite field stores a 1 or a 0, marking
the quote as a favorite or not. Finally, the
date_entered column is a timestamp,
automatically set to the current timestamp
when a new record is created.
Finally, a word about how the site should
be organized on the server C. Ideally the
mysqli_connect.php script, which establishes a database connection, would be
stored outside the web root directory. If that
is not possible in your case, you can place
it in the includes folder, then change the
code in the other scripts accordingly.
You can create this table using a PHP
script, such as Script 12.3, or a third-party
application (like the MySQL client or
phpMyAdmin).
If you’d rather, you could move the
templates and includes folders outside the
web root directory as well. If so, you’ll need to
change all the references to them in the code
to reflect the alternative structure.
Once you’ve created the database, the
database table, and the necessary folders,
you can begin coding.
web root
add_quote.php
css
style.css
delete_quote.php
mysql_connect.php
edit_quote.php
includes
functions.php
index.php
login.php
logout.php
templates
footer.html
header.html
view_quotes.php
C The structure and organization
of the files on the server.
Putting It All Together
391
Connecting to
the Database
Unlike the scripts in Chapter 12, which
connected to the database using code
repeated in each script, this site will use
the more common practice of placing the
repeated code in a stand-alone file. Every
script that interacts with the database—
which will be most but not all of them—will
then include this file. As you can see in C
in the previous section, “Getting Started,”
this file should be stored outside the web
root directory or, if that’s not possible,
within the includes folder.
To create mysqli_connect.php:
1. B
egin a new PHP script in your
text editor or IDE, to be named
mysqli_connect.php (Script 13.1):
The header will start with a PHP section
in order to include the functions.php
script, which will be required by multiple
pages on the site. The reference to the
script is relative to the pages that will
be including the header: files in the
main directory.
396 Chapter 13
A If the person viewing any page is an
administrator, additional links appear.
2. Begin the HTML document:
Again, the style sheet needs to be downloaded from the book’s corresponding
website. And the reference to that
style sheet is relative to the scripts that
include the header, all found within the
main directory.
3. Print the page’s title:
This code also comes from Chapter 8,
printing either the default title or a
custom one, if set as a constant.
4. Complete the head:
5. Begin the page’s body:
My Site of Quotes
6. S
ave the file as header.html, stored in
the templates directory.
Script 13.3 The header file includes the functions.php script and begins the HTML page.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
My Site of Quotes
Putting It All Together
397
To create footer.html:
1. B
egin a new HTML document in
your text editor or IDE, to be named
footer.html (Script 13.4):
2. C
heck if it’s appropriate to display
general administration links:
';
}
?>
</div>
398 Chapter 13
The second part of the conditional, after
the OR, checks if the $loggedin variable
is set and has a TRUE value. This will be
the case on the login.php page, after
the user successfully logged in. The
is_administrator() function won’t
return a TRUE value at that juncture,
because the cookie will have been just
sent by the script and therefore won’t
be available to be read.
3. Create the links:
print '
';
Three links are created: to a page for
adding new quotes, to a page for viewing every quote, and to the logout page.
omplete the conditional and the
4. C
PHP section:
}
?>
5. Complete the HTML page:
6. S
ave the file as footer.html, stored in
the templates directory.
Putting It All Together
399
Logging In
Next, it’s time to create the script through
which the administrator can log in. The
result will be very similar to the scripts in
Chapter 9, “Cookies and Sessions,” with
one structural difference: That chapter used
output buffering, allowing you to lay out
your script however you want. This site
does not use output buffering, so the handling of the form must be written in such
a way that the cookie can be sent without
generating headers already sent errors
(see Chapter 9 if this isn’t ringing a bell for
you). In other words, the script must check
for a form submission prior to including the
header. To still be able to reflect errors and
other messages within the context of the
page, you must use variables.
To create login.php:
1. B
egin a new PHP document in your text
editor or IDE, to be named login.php
(Script 13.5):
' . $error . '';
}
// Indicate the user is logged in, or show the form:
if ($loggedin) {
print '
You are now logged in!
';
} else {
print '
Login Form
';
}
include('templates/footer.html'); // Need the footer.
?>
Putting It All Together
401
7. C
reate error messages for the two
other conditions:
} else { // Incorrect!
$error
= 'The submitted
➝ email address and
➝ password do not match
➝ those on file!';
}
} else { // Forgot a field.
$error = 'Please make sure
➝ you enter both an email
➝ address and a password!';
}
}
The first else clause applies if an email
address and password were provided
but were wrong. The second else
clause applies if no email address or
password was submitted. In both cases,
the message is assigned to a variable
so that it may be used later in the script.
et the page title, and include the
8. S
header file:
define('TITLE', 'Login');
include('templates/header.html');
9. Print an error if one exists:
if ($error) {
print '
' .
➝ $error . '
';
}
The error itself will be determined in
Step 7, but it can’t be printed at that
point because the HTML header will not
have been included. The solution is to
have this code check for a non-FALSE
$error value and then print $error
within some HTML and CSS A.
402
Chapter 13
A Error messages are displayed after the header
is included but before the HTML form.
10. Indicate that the user is logged in, or
display the form:
B The result upon successfully logging in.
C The basic login form.
if ($loggedin) {
print '
You are now logged
➝ in!
';
} else {
print '
Login Form
';
}
If the $loggedin variable has a TRUE
value—its value is FALSE by default—
then the user just successfully logged in
to the site and a message saying so is
displayed B. If the $loggedin variable
still has its default value, then the form
should be shown C.
11. Include the footer, and complete the
page:
include('templates/footer.html');
?>
12. S
ave the file as login.php.
13. Test the file in your browser
(A, B, and C).
I purposefully omitted creating a link to
the login section (as a security measure), so you’ll need to enter the correct
URL in your browser’s address bar.
Note that, as written, the script requires
administrators to log back in after an hour,
whether or not they continue to be active in
the site.
Putting It All Together
403
Logging Out
If you write a login process, there must
be a logout process too. In this case, just
using cookies, it’s a very simple script.
To create logout.php:
1. B
egin a new PHP document in your text
editor or IDE, to be named logout.php
(Script 13.6):
You are now logged out.';
// Include the footer:
include('templates/footer.html');
?>
To delete the existing login cookie,
another cookie is sent with the same
name, a value of FALSE, and an expiration time in the past.
3. D
efine a page title, and include the
header:
define('TITLE', 'Logout');
include('templates/header.html');
4. Print a message:
print '
You are now logged
➝ out.
';
5. Include the footer:
include('templates/footer.html');
?>
6. Save the file as logout.php.
7. Test the file in your browser A.
404
Chapter 13
A The resulting logout page.
Adding Quotes
Now that the administrator has the ability
to log in, she or he should be able to start
adding quotations. The script for doing so
is a lot like the one for adding blog postings (from Chapter 12), but the form will
have an additional checkbox for marking
the quotation as a favorite A.
A The form for adding quotations to the
database.
Script 13.7 The add_quote.php script allows
only administrators to add new quotations to the
database.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Add a Quotation';
// Restrict access to administrators
only:
if (!is_administrator()) {
print '
Access Denied!
You do not have permission
to access this page.
';
include('templates/footer.html');
exit();
}
// Check for a form submission:
if ($_SERVER['REQUEST_METHOD'] ==
'POST') { // Handle the form.
if ( !empty($_POST['quote']) &&
!empty($_POST['source']) ) {
Because this script creates records in the
database, security must be a primary concern. As an initial precaution, the script will
make sure that only the administrator can
use the page. Second, values to be used
in the SQL command will be sanctified to
prevent invalid queries.
To create add_quote.php:
1. B
egin a new PHP document in
your text editor or IDE, to be named
add_quote.php (Script 13.7):
Add a Quotation';
2. D
eny access to the page if the user is
not an administrator:
if (!is_administrator()) {
print '
Access Denied!
➝
➝ You do not have permission to
➝ access this page.
';
include('templates/
➝ footer.html');
exit();
}
continues on next page
21
code continues on next page
Putting It All Together
405
By invoking the is_administrator()
function, the script can quickly test
for that condition. If the user is not an
administrator, an Access Denied error
is displayed, the footer is included, and
the script is terminated B.
3. Check for a form submission:
if ($_SERVER['REQUEST_METHOD'] ==
➝ 'POST') {
B Any user not logged in as an administrator is
denied access to the form.
Note that this check comes after confirming that the user is an administrator.
Script 13.7 continued
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
406
// Need the database connection:
include('../mysqli_connect.php');
// Prepare the values for storing:
$quote = mysqli_real_escape_string($dbc, trim(strip_tags($_POST['quote'])));
$source = mysqli_real_escape_string($dbc, trim(strip_tags($_POST['source'])));
// Create the "favorite" value:
if (isset($_POST['favorite'])) {
$favorite = 1;
} else {
$favorite = 0;
}
$query = "INSERT INTO quotes (quote, source, favorite) VALUES ('$quote', '$source',
$favorite)";
mysqli_query($dbc, $query);
if (mysqli_affected_rows($dbc) == 1){
// Print a message:
print '
Your quotation has been stored.
';
} else {
print '
Could not store the quote because: ' . mysqli_error($dbc)
. '.
The query being run was: ' . $query . '
';
}
// Close the connection:
mysqli_close($dbc);
} else { // Failed to enter a quotation.
print '
Please enter a quotation and a source!
';
}
} // End of submitted IF.
Chapter 13
э
4. Check for values:
if ( !empty($_POST['quote']) &&
➝ !empty($_POST['source']) ) {
This script performs a minimum of validation, checking that the two variables
aren’t empty. With large blocks of text,
such as a quotation, there’s not much
more that can be done in terms of
validation.
5. Prepare the values for use in the query:
include('../mysqli_connect.php');
$quote = mysqli_real_escape_string
➝ ($dbc, trim(strip_tags($_POST
➝ ['quote'])));
$source = mysqli_real_escape_string
➝ ($dbc, trim(strip_tags($_POST
➝ ['source'])));
To make the two textual values safe to
use in the query, they’re run through
the mysqil_real_escape_string()
function (see Chapter 12). Because this
function requires a database connection, that file must first be included.
To make the values safe to later display
in the web page, the strip_tags()
function is applied too (see Chapter 5,
“Using Strings”).
6. Create the favorite value:
if (isset($_POST['favorite'])) {
$favorite = 1;
} else {
$favorite = 0;
}
In the database, a quotation’s status
as a favorite is indicated by a 1. Nonfavorites are represented by a 0. To
determine which number to use, all
the PHP script has to do is check for
a $_POST['favorite'] value. If that
variable is set, regardless of what its
value is, it means the user checked the
favorite checkbox. If the user didn’t do
that, then the variable won’t be set, and
the $favorite variable will be assigned
the value 0.
7. Define and execute the query:
$query = "INSERT INTO quotes
➝ (quote, source, favorite)
➝ VALUES ('$quote', '$source',
➝ $favorite)";
mysqli_query($dbc, $query);
The query specifies values for three
fields and uses the variables already
defined. The remaining two table
columns—id and date_entered—will
automatically be assigned values, thanks
to the table’s definition.
continues on next page
Script 13.7 continued
55
56
57
58
59
60
61
62
63
64
65
// Leave PHP and display the form:
?>
Putting It All Together
407
8. Print a message based on the results:
if (mysqli_affected_rows($dbc)
➝ == 1){
// Print a message:
print '
Your quotation has
➝ been stored.
';
} else {
print '
➝ Could not store the quote
➝ because: ' .
➝ mysqli_error($dbc) . '.
➝
The query being run
➝ was: ' . $query . '
';
}
If the INSERT query created one new row
in the database, a message indicating
that is displayed. Otherwise, debugging
information is shown so that you can try
to figure out what went wrong.
9. Complete the validation conditional:
} else { // Failed to enter a
➝ quotation.
print '
➝ Please enter a quotation and
➝ a source!
';
}
10. Complete the submission conditional
and the PHP block:
} // End of submitted IF.
?>
11. Create the form:
➝
The form has one text area, one text
input, and a checkbox (plus the submit
button, of course). It is not designed to
be sticky—that’s a feature you could
add later, if you wanted.
12. Include the footer:
13. Save the file as add_quote.php, and
test in your browser C.
The ability to create (INSERT), retrieve
(SELECT), update, and delete database records
is collectively referred to as CRUD.
C The result after
adding a quotation.
408
Chapter 13
Listing Quotes
The administrative side of the site will have
a page that lists every quote stored in the
database A. Although the same script
could easily be adapted for the public side,
its primary purpose is to provide quick links
for the administrator to edit or delete any
quote (as opposed to searching randomly
through the public side for the right quote
to manage).
A The full list of stored quotations, with links to
edit or delete each.
To create view_quotes.php:
Script 13.8 This script lists every quotation currently
stored, providing links for the administrator to edit
or delete them.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Like the add_quote.php script, this page
will restrict access to just administrators.
All Quotes';
// Restrict access to administrators
only:
if (!is_administrator()) {
print '
Access Denied!
You do not have permission
to access this page.
';
include('templates/footer.html');
exit();
}
// Need the database connection:
include('../mysqli_connect.php');
// Define the query:
$query = 'SELECT id, quote, source,
favorite FROM quotes ORDER BY date_
entered DESC';
22
code continues on next page
1. B
egin a new PHP document in
your text editor or IDE, to be named
view_quotes.php (Script 13.8):
All Quotes';
2. T
erminate the script if the user isn’t an
administrator:
if (!is_administrator()) {
print '
Access Denied!
➝
You do
➝ not have permission to access
➝ this page.
';
include('templates/
➝ footer.html');
exit();
}
This is the exact same code as that in
add_quote.php. Except for the browser’s
title, the result for nonadministrators will
be the same as in B in the previous
section, “Adding Quotes.”
continues on next page
Putting It All Together
409
3. Include the database connection, and
define the query:
include('../mysqli_connect.php');
$query = 'SELECT id, quote,
➝ source, favorite FROM quotes
ORDER BY date_entered DESC';
The query returns four columns—all but
the date entered—from the database
for every record. The results will be
returned in order by the date they
were entered.
4. E
xecute the query, and begin retrieving
the results:
if ($r = mysqli_query
➝ ($dbc, $query)) {
while ($row =
➝ mysqli_fetch_array($r)) {
The while loop code was explained
in Chapter 12, even though it wasn’t
used in that chapter. This construct is
how you fetch every record returned
by a query.
5. Begin printing out the record:
print "
➝ {$row['quote']}
➝ {$row['source']}\n";
This code starts a DIV, places the
quotation itself within blockquote tags,
and then shows the quote’s attribution.
Script 13.8 continued
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
410
Chapter 13
// Run the query:
if ($result = mysqli_query($dbc,
$query)) {
// Retrieve the returned records:
while ($row = mysqli_fetch_
array($result)) {
// Print the record:
print "
{$row['quote']}
blockquote>- {$row['source']}\n";
// Is this a favorite?
if ($row['favorite'] == 1) {
print ' Favorite!
strong>';
}
// Add administrative links:
print "
\n";
} // End of while loop.
} else { // Query didn't run.
print '
Could not
retrieve the data because: ' .
mysqli_error($dbc) . '.
The
query being run was: ' . $query . '
p>';
} // End of query IF.
mysqli_close($dbc); // Close the
connection.
include('templates/footer.html'); //
Include the footer.
?>
6. Indicate that the quotation is a favorite,
if applicable:
if ($row['favorite'] == 1) {
print ' Favorite!
➝ ';
}
The value of $row['favorite'] will be
either 1 or 0. If it’s 1, the word Favorite!,
emphasized, is displayed along with
the record.
7. A
dd administrative links for editing and
deleting the quote:
print "
\n";
For each quote, two links must be
created. The first is to edit_quote.php
and the second to delete_quote.php.
Each link must also pass the id value
along in the URL, as the code in
Chapter 12 does B.
8. Complete the while loop and the
mysqli_query() conditional:
} // End of while loop.
} else { // Query didn't run.
print '
➝ Could not retrieve the
➝ data because: ' .
➝ mysqli_error($dbc) . '.
➝
The query being run
➝ was: ' . $query . '
';
} // End of query IF.
9. Close the database connection:
mysqli_close($dbc);
10. Complete the page:
include('templates/footer.html');
?>
11. S
ave the view as view_quotes.php,
and test in your browser.
As some of the queries in this chapter
demonstrate, you can use a column or value in
an ORDER BY clause even if it’s not selected by
the query.
The end of the print statement closes
the DIV for the specific quotation
(begun in Step 5).
B The HTML source code for the page shows how the id value is passed in the URL to the linked pages.
Putting It All Together
411
Editing Quotes
The view_quotes.php page (and later,
index.php) has links to edit_quote.php,
where the administrator can update a
quote. Functionally, this script will be very
similar to edit_entry.php from Chapter 12:
1. T
he script needs to receive an ID value
in the URL.
2. U
sing the ID, the record is retrieved and
used to populate a form A.
3. U
pon form submission, the form data
will be validated (even if only slightly).
4. If the form data passes validation, the
record will be updated in the database.
For the most part, this script is just another
application of what you’ve already seen.
But one new thing you’ll learn here is how
to select or not select a form’s checkbox
element based on a preexisting value.
To create edit_quote.php:
1. B
egin a new PHP document in
your text editor or IDE, to be named
edit_quote.php (Script 13.9):
Edit a Quotation ';
2. T
erminate the script if the user isn’t
an administrator:
if (!is_administrator()) {
print '
Access Denied!
➝
You do
➝ not have permission to access
➝ this page.
';
include('templates/
➝ footer.html');
exit();
}
412
Chapter 13
A The form’s elements are prepopulated, and
preselected, using the record’s existing values.
Script 13.9 The edit_quote.php script gives the
administrator a way to update an existing record.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Edit a Quotation';
// Restrict access to administrators
only:
if (!is_administrator()) {
print '
Access Denied!
You do not have permission
to access this page.
';
include('templates/footer.html');
exit();
}
// Need the database connection:
include('../mysqli_connect.php');
if (isset($_GET['id']) && is_numeric($_
GET['id']) && ($_GET['id'] > 0) ) { //
Display the entry in a form:
21
code continues on next page
3. Include the database connection:
include('../mysqli_connect.php');
Both phases of the script—displaying
the form and handling the form—require
a database connection, so the included
file is incorporated at this point.
alidate that a numeric ID value was
4. V
received in the URL:
if (isset($_GET['id']) &&
➝ is_numeric($_GET['id']) &&
➝ ($_GET['id'] > 0) ) {
This conditional is like one from
Chapter 12, with the addition of checking that the ID value is greater than 0.
Adding that clause doesn’t do anything
for the security of the script—the
is_numeric() test confirms that the
value is safe to use in a query, but
prevents the query from being executed
if the ID has an unusable value.
5. Define and execute the query:
$query = "SELECT quote, source,
➝ favorite FROM quotes WHERE
➝ id={$_GET['id']}";
if ($result = mysqli_query($dbc,
➝ $query)) {
The query returns three columns for a
specific record.
continues on page 415
Script 13.9 continued
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// Define the query.
$query = "SELECT quote, source, favorite FROM quotes WHERE id={$_GET['id']}";
if ($result = mysqli_query($dbc, $query)) { // Run the query.
$row = mysqli_fetch_array($result); // Retrieve the information.
// Make the form:
print '
';
code continues on next page
Putting It All Together
413
Script 13.9 continued
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
414
} else { // Couldn't get the information.
print '
Could not retrieve the quotation because: ' . mysqli_
error($dbc) . '.
The query being run was: ' . $query . '
';
}
} elseif (isset($_POST['id']) && is_numeric($_POST['id']) && ($_POST['id'] > 0)) { // Handle
the form.
// Validate and secure the form data:
$problem = FALSE;
if ( !empty($_POST['quote']) && !empty($_POST['source']) ) {
// Prepare the values for storing:
$quote = mysqli_real_escape_string($dbc, trim(strip_tags($_POST['quote'])));
$source = mysqli_real_escape_string($dbc, trim(strip_tags($_POST['source'])));
// Create the "favorite" value:
if (isset($_POST['favorite'])) {
$favorite = 1;
} else {
$favorite = 0;
}
} else {
print '
Please submit both a quotation and a source.
';
$problem = TRUE;
}
if (!$problem) {
// Define the query.
$query = "UPDATE quotes SET quote='$quote', source='$source', favorite=$favorite WHERE
id={$_POST['id']}";
if ($result = mysqli_query($dbc, $query)) {
print '
The quotation has been updated.
';
} else {
print '
Could not update the quotation because: ' . mysqli_
error($dbc) . '.
The query being run was: ' . $query . '
';
}
} // No problem!
} else { // No ID set.
print '
This page has been accessed in error.
';
} // End of main IF.
mysqli_close($dbc); // Close the connection.
include('templates/footer.html'); // Include the footer.
?>
Chapter 13
6. Begin creating the form:
print '
';
The print statement starts by closing
the checkbox. Then the form must also
store the ID value in a hidden input, so
that it’s available to the script upon the
form submission.
Note that it’s safe to print out
$_GET['id'] here without using
htmlentities() because the
is_numeric() function already confirmed that it has a numeric value.
reate an error if the record could not
9. C
be retrieved:
} else { // Couldn't get the
➝ information.
print '
Could
➝ not retrieve the quotation
➝ because: ' . mysqli_error
➝ ($dbc) . '.
The query
➝ being run was: ' . $query .
➝ '
';
}
10. Check for a form submission:
} elseif (isset($_POST['id']) &&
➝ is_numeric($_POST['id']) &&
➝ ($_POST['id'] > 0)) {
This conditional begins the second
phase of the script: handling the
submission of the form. The validation is the same as in Step 4, but now
$_POST['id'] is referenced instead of
$_GET['id'].
416
Chapter 13
11. Validate the form data:
$problem = FALSE;
if (!empty($_POST['quote']) &&
➝ !empty($_POST['source']) ) {
The form validation for the edit page
mirrors that in the add_quote.php script
(Script 13.7).
12. Prepare the values for use in the query:
$quote = mysqli_real_escape_string
➝ ($dbc, trim(strip_tags($_POST
➝ ['quote'])));
$source = mysqli_real_escape_string
➝ ($dbc, trim(strip_tags($_POST
➝ ['source'])));
if (isset($_POST['favorite'])) {
$favorite = 1;
} else {
$favorite
= 0;
}
This code is also taken straight from
add_quote.php.
13. Indicate a problem if the form wasn’t
completed:
} else {
print '
➝ Please submit both a
➝ quotation and a source.
';
$problem = TRUE;
}
14. If no problem occurred, update the
database:
if (!$problem) {
$query = "UPDATE quotes
➝ SET quote='$quote',
➝ source=$source',
➝ favorite=$favorite WHERE
➝ id={$_POST['id']}";
if ($r = mysqli_query($dbc,
➝ $query)) {
print '
The quotation has
➝ been updated.
';
The UPDATE query updates the values
of three of the record’s columns. The
two string values are enclosed in single
quotation marks (within the query); the
numeric $favorite value is not.
C The result upon successfully editing a record.
The WHERE clause, which dictates the
record to be updated, is the critical piece.
Finally, a simple message indicates the
success of the operation C.
15. Indicate a problem if the query failed:
} else {
print '
➝ Could not update the
➝ quotation because: ' .
➝ mysqli_error($dbc) . '.
➝
The query being run
➝ was: ' . $query . '
';
}
16. C
omplete the conditionals:
} // No problem!
} else { // No ID set.
print '
➝ This page has been accessed
➝ in error.
';
} // End of main IF.
The else clause applies if no valid ID
value is received by the page via either
GET or POST.
lose the database connection, and
17. C
complete the page:
mysqli_close($dbc);
include('templates/footer.html');
?>
18. S
ave the file, and test in your browser
(by clicking a link on view_quotes.php).
Putting It All Together
417
Deleting Quotes
The script for deleting existing quotations
mimics delete_entry.php from Chapter 12.
Upon first arriving, assuming that a valid
record ID was passed along in the URL, the
quote to be deleted is displayed A. If the
administrator clicks the submit button, the
form will be submitted back to this same
page, at which point the record will be
removed from the database B.
A The first step for deleting a record is confirming
the record to be removed.
To create delete_quote.php:
1. B
egin a new PHP document in
your text editor or IDE, to be named
delete_quote.php (Script 13.10):
Delete a Quotation
➝ ';
B Upon submission of the form,
the quotation is deleted and a
message is printed.
Script 13.10 The delete_quote.php script provides the administrator with a way to delete an existing record.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Delete a Quotation';
// Restrict access to administrators only:
if (!is_administrator()) {
print '
Access Denied!
You do not have permission to access this
page.
';
include('templates/footer.html');
exit();
}
code continues on next page
418
Chapter 13
2. T
erminate the script if the user isn’t
an administrator:
if (!is_administrator()) {
print '
Access Denied!
➝
You do
➝ not have permission to access
➝ this page.
';
include('templates/
➝ footer.html');
exit();
}
continues on next page
Script 13.10 continued
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// Need the database connection:
include('../mysqli_connect.php');
if (isset($_GET['id']) && is_numeric($_GET['id']) && ($_GET['id'] > 0) ) { // Display the
quote in a form:
// Define the query:
$query = "SELECT quote, source, favorite FROM quotes WHERE id={$_GET['id']}";
if ($result = mysqli_query($dbc, $query)) { // Run the query.
$row = mysqli_fetch_array($result); // Retrieve the information.
// Make the form:
print '
Are you sure you want to delete this quote?
' . $row['quote'] . '
- ' . $row['source'];
// Is this a favorite?
if ($row['favorite'] == 1) {
print ' Favorite!';
}
print '
';
} else { // Couldn't get the information.
print '
Could not retrieve the quote because: ' . mysqli_error($dbc)
. '.
The query being run was: ' . $query . '
';
}
} elseif (isset($_POST['id']) && is_numeric($_POST['id']) && ($_POST['id'] > 0) ) { // Handle
the form.
47
code continues on next page
Putting It All Together
419
3. Include the database connection:
include('../mysqli_connect.php');
4. V
alidate that a numeric ID value was
received in the URL:
if (isset($_GET['id']) &&
➝ is_numeric($_GET['id']) &&
➝ ($_GET['id'] > 0) ) {
This is the same conditional used in
edit_quote.php.
5. Retrieve the record to be deleted:
$query = "SELECT quote, source,
➝ favorite FROM quotes WHERE
➝ id={$_GET['id']}";
if ($r = mysqli_query($dbc,
➝ $query)) {$row =
➝ mysqli_fetch_array($r);
The standard three fields are
retrieved from the database for the
record. Because only one record is
being addressed in this script, the
mysqli_fetch_array() function is
called once, outside of any loop.
6. Begin creating the form:
print '
Are you sure you want to
➝ delete this quote?
' . $row
➝ ['quote'] . '
- ' .
➝ $row['source'];
The form, for the most part, just displays
the quotation.
7. Indicate if the quotation is a favorite:
if ($row['favorite'] == 1) {
print ' Favorite!
➝ ';
}
This code is the same as that on the
view_quotes.php page, indicating that
the quote is, in fact, a favorite.
Script 13.10 continued
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
420
// Define the query:
$query = "DELETE FROM quotes WHERE id={$_POST['id']} LIMIT 1";
$result = mysqli_query($dbc, $query); // Execute the query.
// Report on the result:
if (mysqli_affected_rows($dbc) == 1) {
print '
The quote entry has been deleted.
';
} else {
print '
Could not delete the blog entry because: ' . mysqli_
error($dbc) . '.
The query being run was: ' . $query . '
';
}
} else { // No ID received.
print '
This page has been accessed in error.
';
} // End of main IF.
mysqli_close($dbc); // Close the connection.
include('templates/footer.html');
?>
Chapter 13
8. Complete the form:
print '
';
The form must contain a hidden input
that will pass the quote ID back to the
page upon form submission.
9. C
omplete the mysqli_query()
conditional:
} else { // Couldn't get the
➝ information.
print '
➝ Could not retrieve the quote
because: ' .
➝ mysqli_error($dbc) . '.
➝
The query being run
➝ was: ' . $query . '
';
}
If the query failed, the MySQL error
and the query itself are displayed for
debugging purposes.
10. Check for a form submission:
} elseif (isset($_POST['id']) &&
➝ is_numeric($_POST['id']) &&
➝ ($_POST['id'] > 0) ) {
This conditional begins the second
phase of the script: handling the
submission of the form. The validation is the same as in Step 4, but now
$_POST['id'] is referenced instead of
$_GET['id'].
11. Delete the record:
$query = "DELETE FROM quotes
➝ WHERE id={$_POST['id']} LIMIT
➝ 1";
$r = mysqli_query($dbc, $query);
The DELETE query will remove the
record. The WHERE conditional indicates
which specific record is to be removed,
and the LIMIT 1 clause is applied as an
extra precaution.
12. Report on the result:
if (mysqli_affected_rows($dbc)
➝ == 1) {
print
'
The quote entry has
➝ been deleted.
';
} else {
print '
➝ Could not delete the blog
➝ entry because: ' .
➝ mysqli_error($dbc) . '.
➝
The query being run
➝ was: ' . $query . '
';
}
If the query succeeded, then one
record will have been affected and a
message is displayed to the user B.
13. Complete the conditionals:
} else { // No ID received.
print '
➝ This page has been accessed
➝ in error.
';
} // End of main IF.
The else clause applies if no valid ID
value is received by the page via either
GET or POST.
lose the database connection, and
14. C
complete the page:
mysqli_close($dbc);
include('templates/footer.html');
?>
15. S
ave the file, and test in your browser
(by clicking a link on view_quotes.php).
Putting It All Together
421
Creating the
Home Page
Last, but certainly not least, there’s the
home page. For this site, the home page
will be the only page used by the public at
large. The home page will show a single
quotation, but the specific quotation can
be one of the following:
n
The most recent (the default)
n
A random quotation
n
A random favorite quotation
To achieve this effect, links will pass different values in the URL back to this same
page A.
The script should also display administrative
links—edit and delete—for the currently
displayed quote, if the user is an
administrator B.
A Values passed in the URL trigger the execution
of different queries.
B When an administrator views the home page,
extra links are displayed.
Script 13.11 The home page of the site shows a single quotation at a time, plus administrative links (when
appropriate).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{$row['quote']}
- {$row['source']}";
// Is this a favorite?
if ($row['favorite'] == 1) {
print ' Favorite!';
}
// Complete the DIV:
print '
';
// If the admin is logged in, display admin links for this record:
if (is_administrator()) {
print "
\n";
}
code continues on next page
Putting It All Together
423
To select a random row in MySQL, use
the ORDER BY RAND() clause. This code
uses MySQL’s RAND() function, short
for random, to return the records in a
random order. So this query first selects
every record in random order, and then
returns only the first in that set.
efine the query that selects a random
5. D
favorite record:
} elseif (isset
➝ ($_GET['favorite'])) {
$query = 'SELECT id, quote,
➝ source, favorite FROM quotes
➝ WHERE favorite=1 ORDER BY
➝ RAND() DESC LIMIT 1';
This query is similar to that in Step 4,
but it uses a WHERE clause to restrict the
pool of possible quotations to just those
whose favorite value equals 1.
6. Define the default query:
} else {
$query = 'SELECT id, quote,
➝ source, favorite FROM quotes
➝ ORDER BY date_entered DESC
➝ LIMIT 1';
}
If no value was passed in the URL, then
the home page should display the most
recently added quotation. To do that, the
query orders all the quotes in descending order of date entered and then limits
the results to just a single record.
xecute the query, and fetch the
7. E
returned record:
if ($r = mysqli_query($dbc,
➝ $query)) {
$row
= mysqli_fetch_array($r);
8. Print the quotation:
print "
➝ {$row ['quote']}
➝ {$row['source']} ";
This code is similar to that in
view_quotes.php, but needs to be
used only once.
9. Indicate if the quotation is a favorite,
and complete the DIV:
if ($row['favorite'] == 1) {
print ' Favorite!
➝ ';
}
print '
';
The conditional is the same as in
delete_quote.php and view_quotes.php.
Script 13.11 continued
47
48
49
50
51
52
53
54
55
56
424
} else { // Query didn't run.
print '
Could not retrieve the data because: ' . mysqli_error($dbc) .
'.
The query being run was: ' . $query . '
';
} // End of query IF.
mysqli_close($dbc); // Close the connection.
print '
';
include('templates/footer.html'); // Include the footer.
?>
Chapter 13
10. If the user is an administrator, create
links to edit or delete this record:
if (is_administrator()) {
print "
\n";
}
If the user is an administrator, links
to the edit and delete scripts will be
added to the page. The links themselves have values just like those in
view_quotes.php.
11. If the query didn’t run, print out an error
message:
} else { // Query didn't run.
print '
➝ Could not retrieve the data
because: ' .
➝ mysqli_error($dbc) . '.
➝
The query being run
➝ was: ' . $query . '
';
} // End of query IF.
This code is for your own debugging
purposes. You would not display a
MySQL error, or the query that caused
it, to the general public.
13. Create links to other pages:
print '
';
Three public links are added to the page,
each back to this same script. The first
link, which passes no values in the
URL, will always show the most recent
quotation. The second, which passes
a random value in the URL, will trigger
the query in Step 4, thereby retrieving
a random record. The third link, which
passes a favorite value in the URL, will
trigger the query in Step 5, thereby
retrieving a random favorite record.
14. Include the footer, and complete
the page:
include('templates/footer.html');
?>
15. S
ave the file, and test in your
browser C.
Normally the home page is one of the
first scripts written, not the last. But in this
case I wanted to build up to this point in
the example.
As a precaution, you could only show the
MySQL error if is_administrator()
returns TRUE.
lose the database connection:
12. C
mysqli_close($dbc);
The database connection will no
longer be needed, so it can be closed
at this point.
C The latest quotation (note the URL).
Putting It All Together
425
Review and Pursue
If you have any problems with the
review questions or the pursue prompts,
turn to the book’s supporting forum
(www.LarryUllman.com/forums/).
Pursue
n
n
Review
n
n
n
n
How would the is_administrator()
function be called to check for the
same cookie—named Samuel—with a
different value? A different cookie—not
named Samuel—with a different value?
hy is the reference to the style sheet in
W
the header file css/style.css instead
of ../css/style.css? How else could
the style sheet be referenced?
n
n
n
n
Why is the login.php script structured
the way it is? How could that script be
organized more linearly?
hat would be some other good ideas
W
for user-defined functions with this site?
Hint: Look for repeated code.
n
n
426
Chapter 13
Make the login form sticky.
efine the login credentials—the cookie
D
name and value—as constants in a configuration file. Then include that configuration file on every page, and use
those constants for creating, deleting,
and confirming the value of the cookie.
L imit the cookie’s expiration to only
15 minutes, and then re-send the cookie
on each page, if appropriate (i.e., if the
cookie exists).
Use sessions instead of a cookie.
Make the add_quote.php and
edit_quote.php forms sticky.
Change view_quotes.php so that the
administrator can list the quotes in
different order. Hint: Create links back
to the page like those on index.php,
and change the query accordingly.
efore putting this site on a live server
B
(should you do that), update all the
code so that no MySQL error is ever
shown to a nonadministrative user.
ee what other repetitive code could
S
also be moved into your own functions.
A
Installation and
Configuration
The three technical requirements for executing all of this book’s examples are PHP,
the scripting language; the web server application that PHP runs through; and MySQL,
the database application. This appendix
describes the installation of these tools
on two different platforms—Windows 10
and Mac OS X. If you are using a hosted
website, all of this will already be provided
for you, but these products are all free and
easy enough to install, so putting them on
your own computer still makes sense.
After the installation section, this appendix
demonstrates some basics for working
with MySQL and configuring PHP. The PHP
and MySQL manuals cover installation and
configuration in a reasonable amount of
detail. You may want to also peruse them,
particularly if you encounter problems.
Installation on
Windows
Although you can certainly install a web
server (such as Apache, Nginx, or IIS), PHP,
and MySQL individually on a Windows
computer, I strongly recommend you use
an all-in-one installer instead. It’s simply
easier and more reliable to do so.
Several all-in-one installers are out there
for Windows. The four that I see mentioned
most frequently are
n
XAMPP (www.apachefriends.org)
n
WAMP (www.wampserver.com)
n
AMPPS (www.ampps.com)
n
itnami (www.bitnami.com), which also
B
partners with XAMPP
For this appendix, I’ll use XAMPP, which
runs on Windows 2008, 2012, Vista, 7, and
8. (The XAMPP site makes no mention of
Windows 10, but you should be able to use
XAMPP on that version of Windows too.)
428
Appendix A
On Firewalls
A firewall prevents communications in
many ways, the most common of which
being over ports: an access point to a
computer. Versions of Windows starting with Service Pack 2 of XP include a
built-in firewall. You can also download
and install third-party firewalls. Firewalls
improve the security of your computer,
but they may also interfere with your ability to run Apache, MySQL, and some of
the other tools used by XAMPP because
they all use ports.
When running XAMPP for the first time,
or during the installation process, if you
see a security prompt indicating that
the firewall is blocking Apache, MySQL,
or the like, choose Unblock or Allow
access. Otherwise, you can configure
your firewall manually through the operating system settings.
The ports that need to be open are as
follows: 80 for Apache, 3306 for MySQL,
and 25 for the Mercury mail server. If you
have any problems starting or accessing
one of these, disable your firewall and
see if it works then. If so, you’ll know the
firewall is the problem and that it needs
to be reconfigured.
Just to be clear, firewalls aren’t found just
on Windows, but in terms of the instructions in this appendix, the presence of a
firewall will more likely trip up a Windows
user than any other.
Along with Apache, PHP, and MySQL,
XAMPP also installs the following:
n
hpMyAdmin, the web-based interface
p
to a MySQL server
n
OpenSSL, for secure connections
n
A mail server (for sending email)
n
Several useful extensions
As of this writing, XAMPP (Version 7.0.6)
installs PHP 7.0.6, Apache 2.4.18, and
phpMyAdmin 4.5.1. There is one catch,
however!
As of XAMPP 5.5.30, the installer includes
MariaDB (www.mariadb.com) instead of
MySQL. MariaDB is an open source fork
of MySQL that is functionally equivalent.
Despite the fact that XAMPP installs
MariaDB instead of MySQL, you shouldn’t
have any problems following all the MySQLspecific instructions or code in this book.
I’ll run through the installation process in
these next steps. Note that if you have any
problems, you can use the book’s supporting forum (www.LarryUllman.com/forums/),
but you’ll probably have more luck turning
to the XAMPP site (it is their product, after
all). Also, the installer works really well and
isn’t that hard to use, so rather than detail
every single step in the process, I’ll highlight the most important considerations.
Installation and Configuration
429
To install XAMPP on Windows:
1. D
ownload the latest release of
XAMPP for Windows from
www.apachefriends.org A.
I suggest that you grab the latest
version of PHP available, although you’ll
be fine with this book’s content if you
use a PHP 5 version instead.
n your computer, double-click the
2. O
downloaded file to begin the installation
process.
3. When prompted B, install all the
components.
A From the Apache Friends website, grab the
latest installer for Windows.
Admittedly, you don’t need Tomcat—
a Java server—or Perl, but it’s fine to
install them too.
4. W
hen prompted C, install XAMPP
somewhere other than in the Program
Files directory.
You shouldn’t install it in the Program
Files directory because of a permissions issue in Windows. I recommend
installing XAMPP in your root directory
(e.g., C:\).
Wherever you decide to install the
program, make note of that location,
because you’ll need to know it
several other times as you work
through this appendix.
B The XAMPP components that can be installed.
C Select where XAMPP should be installed.
430
Appendix A
5. A
fter the installation process has done
its thing D, opt to start the XAMPP
Control Panel.
o start, stop, and configure XAMPP,
6. T
use the XAMPP Control Panel E.
D The installation of XAMPP is complete!
Apache has to be running for every
chapter in this book. MySQL must
be running for Chapter 12, “Intro to
Databases,” and Chapter 13, “Putting
It All Together.” Mercury is the mail
server that XAMPP installs. It needs to
be running in order to send email using
PHP (see Chapter 8, “Creating Web
Applications”).
7. Immediately set a password for the root
MySQL user.
How you do this is explained in the
“Managing MySQL Users” section later
in this appendix.
continues on next page
E The XAMPP Control Panel, used to manage the
software.
Installation and Configuration
431
The XAMPP Control Panel’s various
admin links will take you to different web
pages (on your server) and other resources F.
See the “Configuring PHP” section to
learn how to configure PHP by editing the
php.ini file.
Whenever you restart your computer,
you’ll need to restart the XAMPP services.
Your web root directory—where your PHP
scripts should be placed in order to test them—
is the htdocs folder in the directory where
XAMPP was installed. Following my installation
instructions, this would be C:\xampp\htdocs.
432
Appendix A
F The web-based splash page for XAMPP, linked
from its Control Panel.
Installation on
Mac OS X
Mac OS X is at its heart a version of Unix,
and because PHP and MySQL were originally written for Unix-like systems, numerous
options are available for installing them
on Mac OS X. In fact, Mac OS X already
comes with Apache installed, saving you
that step.
Seasoned developers and those at home
in the Terminal will likely want to install PHP
and MySQL using package installers such
as http://php-osx.liip.ch/ and Homebrew
(http://brew.sh/). But for beginners, I recommend using an all-in-one installer such as
n
XAMPP (www.apachefriends.org)
n
AMPPS (www.ampps.com)
n
n
itnami (www.bitnami.com), which also
B
partners with XAMPP
MAMP (www.mamp.info)
Not only are these installers relatively
foolproof, but they also won’t leave you
scrambling when an operating system
update overwrites your Apache configuration file. For this appendix, I’ll use XAMPP,
which runs on Mac OS X 10.6 and later.
Along with Apache, PHP, and MySQL,
XAMPP also installs the following:
n
hpMyAdmin, the web-based interface
p
to a MySQL server
n
OpenSSL, for secure connections
n
Several useful extensions
As of this writing, XAMPP (Version 7.0.6)
installs PHP 7.0.6, Apache 2.4.18, and
phpMyAdmin 4.5.1. There is one catch,
however!
As of XAMPP 5.5.30, the installer includes
MariaDB (www.mariadb.com) instead of
MySQL. MariaDB is an open source fork
of MySQL that is functionally equivalent.
Despite the fact that XAMPP installs
MariaDB instead of MySQL, you shouldn’t
have any problems following all the MySQLspecific instructions or code in this book.
I’ll run through the installation process in
these next steps. Note that if you have any
problems, you can use the book’s supporting forum (www.LarryUllman.com/forums/),
but you’ll probably have more luck turning
to the XAMPP site (it is their product, after
all). Also, the installer works really well and
isn’t that hard to use, so rather than detail
every single step in the process, I’ll highlight the most important considerations.
Installation and Configuration
433
To install XAMPP on Mac OS X:
1. D
ownload the latest release of
XAMPP for Mac OS X from
www.apachefriends.org A.
I suggest you grab the latest version
of PHP available, although you’ll be
fine with this book’s content if you use
a PHP 5 version instead.
n your computer, double-click the
2. O
downloaded file to mount the disc image.
A From the Apache Friends website, grab the
latest installer for Mac OS X.
3. In the mounted disk image, doubleclick the package installer to begin the
installation process.
4. When prompted B, install all the
components.
You’ll see only two, broad options;
install both.
5. A
fter the installation process has done
its thing C, opt to launch XAMPP.
6. T
o start, stop, and configure XAMPP,
use the XAMPP Control Panel D.
Apache has to be running for every
chapter in this book. MySQL must be
running for Chapters 12 and 13. You
probably won’t ever need the FTP
application, because you can just move
your files directly.
B The XAMPP components that can be installed.
7. Immediately set a password for the root
MySQL user.
How you do this is explained in the
“Managing MySQL Users” section later
in this appendix.
C The installation of XAMPP is complete!
434 Appendix A
See the “Configuring PHP” section to
learn how to configure PHP by editing the
php.ini file.
Whenever you restart your computer,
you’ll need to restart the XAMPP services.
Your web root directory—where your
PHP scripts should be placed in order to test
them—is the htdocs folder in the directory
where XAMPP was installed. This would be
/Applications/XAMPP/xamppfiles/
htdocs.
D The XAMPP Control Panel, used to manage the
software.
Installation and Configuration
435
Configuring PHP
2. In the browser’s output, search for
Loaded Configuration File.
One of the benefits of installing PHP on
your own computer is that you can configure it however you prefer. How PHP runs
is determined by the php.ini file, which is
normally created when PHP is installed.
The value next to this text is the location of the active configuration file. This
will be something like C:\xampp\php\
php.ini or /Applications/XAMPP/
xamppfiles/etc/php.ini.
Two of the most important settings you
may want to consider adjusting are
display_errors and error_reporting
(both are discussed in Chapter 3, “HTML
Forms and PHP”). To change any setting,
open the PHP configuration file, edit it
as needed, then save it and restart the web
server.
If there is no value for the Loaded
Configuration File, your server has no
active php.ini file. This is highly
uncommon, but you’d need to download
the PHP source code, from www.php.net,
to find a sample configuration file.
3. Open the php.ini file in any text editor.
4. Change the settings as you wish.
To alter PHP’s configuration:
Depending on your operating system,
you may need to be an administrator or
enter a password to make changes to
this file.
1. In your browser, execute a script that
invokes the phpinfo() function A.
The phpinfo() function, discussed in
Chapter 1, “Getting Started with PHP,”
reveals oodles of information about the
PHP installation.
Many instructions are included in the file.
Lines are commented out (made inactive)
by preceding them with a semicolon.
5. Save the php.ini file.
A Some of the output from calling the phpinfo() function.
436 Appendix A
Enabling Mail
The mail() function works only if the
computer running PHP has access to
sendmail or another mail server. One
way to enable the mail() function is
to set the smtp value in the php.ini
file (for Windows only). This approach
works if, for example, your Internet
provider has an SMTP address you can
use. Unfortunately, you can’t use this
value if your ISP’s SMTP server requires
authentication.
For Windows, a number of free SMTP
servers, such as Mercury, are available.
It’s installed along with XAMPP, or you
can install it yourself if you’re not using
XAMPP.
6. Restart your web server.
You don’t need to restart the entire
computer, just the web server (e.g.,
Apache). In XAMPP, simply click Stop
and then Start for Apache.
You can also use the phpinfo() function
to confirm that your configuration changes
have taken effect.
If you edit the php.ini file and restart
the web server but your changes don’t take
effect, make sure you’re editing the proper
php.ini file (you may have more than one on
your computer).
Mac OS X comes with a mail server
installed—postfix and/or sendmail—that
needs to be enabled. Search Google for
instructions on manually enabling your
mail server on Mac OS X.
Alternatively, you can search some of
the PHP code libraries to learn how
to use an SMTP server that requires
authentication.
Installation and Configuration
437
MySQL Interfaces
In Chapters 12 and 13, a PHP script will be
used to interact with a MySQL database.
As I explain in Chapter 12, being able to
interact with MySQL independent of your
PHP scripts is the most valuable debugging
tool there is. Knowing how to use a separate MySQL interface is therefore critical
information. I’ll quickly introduce the two
most common options.
Using the MySQL client
The MySQL software comes with an important tool known as the MySQL client. This
application provides a simple interface for
communicating with the MySQL server. It’s a
command-line tool that must be accessed
using the Terminal application on Linux and
Mac OS X or through the command (DOS)
prompt on Windows.
To use the MySQL client:
1. Make sure the MySQL server is running.
If you’re using XAMPP on Windows, you
can start MySQL there and then skip
ahead to Step 3.
2. Find the MySQL bin directory.
To connect to the client, you’ll need
to know where it’s located. The MySQL
client is found within the bin directory for
your installation (bin is short for “binary,”
which is to say an executable). I’ll run
through the common possibilities.
If you installed MySQL yourself, the
client’s location depends on where you
installed the software, but it’s most likely
C:\mysql\bin\mysql (Windows)
or
/usr/local/mysql/bin/mysql (Mac
OS X and Unix)
438 Appendix A
Using Semicolons
Within the MySQL client, a semicolon
indicates the completion of a statement
to be executed. This allows you to write
a complicated command or SQL query
over multiply lines, and MySQL won’t
attempt to run that command until it
meets a semicolon. This is only a requirement within the MySQL client, though.
Queries run through PHP scripts or phpMyAdmin do not need to be terminated
by semicolons. And you don’t need to
use a semicolon after exit to leave the
MySQL client.
If you used XAMPP on Windows, it’s
C:\xampp\mysql\bin\mysql (assuming you installed XAMPP in C:\). If you
installed XAMPP on Mac OS X, it’s
/Applications/XAMPP/xamppfiles/bin.
3. Access a command prompt.
A Use the Run dialog to access a console
window on Windows.
On Mac OS X and Unix, you can accomplish this by running the Terminal application. On Mac OS X, it’s found within
the /Applications/Utilities folder.
On Windows, press Command+R to
open the Run dialog, and at the prompt,
type cmd and press Enter or click OK A.
If you’re using XAMPP on Windows,
click the Shell button in the Control
Panel B to access a command prompt.
4. Attempt to connect to the MySQL server.
B The Shell button in the XAMPP Control Panel
takes you straight to a command prompt.
To connect, enter the pathname identified in Step 2 plus -u username -p.
So, the command might be
C:\mysql\bin\mysql -u username -p
(Windows)
or
/usr/local/mysql/bin/mysql
➝ -u username -p (Unix and Mac OS X)
or
/Applications/XAMPP/xamppfiles/
➝ bin/mysql -u username -p (Mac OS X)
For XAMPP on Windows, you can just
use mysql -u username -p (assuming
you clicked the Shell button in Step 3).
Replace username with the username
you want to use. If you haven’t yet
created any other users, this will be
root (root is the supreme MySQL user).
If you haven’t yet established a root
user password (the default behavior for
XAMPP), you can omit the -p flag.
continues on next page
Installation and Configuration
439
5. Enter the password at the prompt C.
The password requested is the MySQL
password for the user named during the
connection. You’ll see this prompt only
if you used the -p option in Step 4.
If you installed MAMP on Mac OS X, the
password for the root user will be root.
If you installed XAMPP on Windows, no
password is set initially.
6. List the available databases D:
7. Exit the MySQL client.
To do so, type exit or quit.
If you see a Can’t connect to local MySQL
server through socket… error message, it normally means MySQL isn’t running.
The MySQL client is one of the best tools
for debugging PHP scripts that work with
MySQL. You can use the MySQL client to check
user permissions and to run queries outside of
the PHP script.
SHOW DATABASES;
The SHOW DATABASES command is a
SQL query that lists every database
hosted on that MySQL installation that
the connected user can see.
C Successfully accessing the MySQL client on Windows.
D After a fresh MySQL installation, there
will only be a couple of databases.
440
Appendix A
Using phpMyAdmin
To use phpMyAdmin:
phpMyAdmin (www.phpmyadmin.net) is a
web-based interface for interacting with
a MySQL server, allowing you to create
tables, import and export records, and much
more, without having to use a commandline interface. It is arguably the most popular
web software written in PHP, as every
PHP hosting company provides it. In fact,
the all-in-one XAMPP installer includes it
too. phpMyAdmin is well documented and
easy to use, but I’ll highlight a couple of
quick points.
1. A
ccess phpMyAdmin in your
browser E.
When using XAMPP, phpMyAdmin is
available at http://localhost/phpmyadmin/.
On Windows, you can also get to this
page by clicking the MySQL admin link
in the Control Panel.
2. C
lick a database name in the left
column to select that database.
continues on next page
E The phpMyAdmin front page.
Installation and Configuration
441
3. C
lick a table name in the left column to
select that table F.
You don’t always have to select a table,
but by doing so you can simplify some
tasks.
4. U
se the tabs and links (on the right side
of the page) to perform common tasks.
For the most part, the tabs and links are
shortcuts to common SQL commands.
For example, the Browse tab performs a
SELECT query and the Insert tab creates
a form for adding new records.
5. U
se the SQL tab to execute any
SQL command.
You can alternatively use the SQL
Query Window, linked just above the
list of database or table names. Using
either interface, you can test queries
that your PHP scripts are using,
without the added complication of
the script itself.
Many other clients are available for interacting with a MySQL database, but the MySQL
command-line client and phpMyAdmin are the
two most common.
F Selecting a database or a table, from the left column, changes the options on the right side of the page.
442
Appendix A
Managing
MySQL Users
Once you’ve successfully installed MySQL,
you can begin creating MySQL users. A
MySQL user is a fundamental security concept, limiting access to, and influence over,
stored data. Just to clarify, your databases
can have several different users, just as
your operating system might. But MySQL
users are different from operating system
users. While learning PHP and MySQL on
your own computer, you don’t necessarily
need to create new users, but live production sites need to have dedicated MySQL
users with appropriate permissions.
The initial MySQL installation comes with
one user (named root) with no password
set. At the very least, you should create
a new, secure password for the root user
after installing MySQL.
After that, you can create other users with
more limited permissions. As a rule, you
shouldn’t use the root user for normal,
day-to-day operations.
While you’re creating new users, you’ll also
see how to create new databases, which
will be necessary for Chapters 12 and 13.
Setting the root user password
You can set any user’s password using
either phpMyAdmin or the MySQL client,
as long as the MySQL server is running.
If MySQL isn’t currently running, start it now
using the steps outlined earlier in
this appendix.
You must be connected to MySQL as the
root user in order to be able to change the
root user’s password.
To assign a password to the root
user via the MySQL client:
1. C
onnect to the MySQL client.
See the set of steps in “To use the
MySQL client” for detailed instructions.
nter the following command, replacing
2. E
thepassword with the password you
want to use A:
SET PASSWORD FOR
➝ 'root'@'localhost' =
➝ PASSWORD('thepassword');
Keep in mind that passwords in
MySQL are case-sensitive, so Kazan
and kazan aren’t interchangeable.
The term PASSWORD that precedes the
actual quoted password tells MySQL
to encrypt that string using the MySQL
PASSWORD() function. You cannot have
a space between PASSWORD and the
opening parenthesis.
When you install MySQL, no value—or no
secure password—is established for the
root user. This is certainly a security risk
that should be remedied before you begin
to use the server (because the root user
has unlimited powers).
continues on next page
A Updating the root user’s password using SQL within the MySQL client.
Installation and Configuration
443
3. Exit the MySQL client:
exit
4. T
est the new password by logging in to
the MySQL client again.
Now that a password has been established, you need to add the -p flag to
the connection command. You’ll see
an Enter password prompt, where you
enter the just-created password.
B The list of MySQL users, as shown in
phpMyAdmin.
To assign a password to the
root user via phpMyAdmin:
1. Open phpMyAdmin in your browser.
See the set of steps in the section
“To use phpMyAdmin” for detailed
instructions.
n the home page, click the User
2. O
accounts tab.
You can always click the home icon,
in the upper-left corner, to get to the
phpMyAdmin home page.
3. In the list of users, click the Edit
Privileges icon on the root user’s
row B.
4. O
n the next page, click Change
Password.
5. U
se the Change Password form C,
found further down the resulting page,
to change the password.
444
Appendix A
C The form for updating a MySQL user’s
password within phpMyAdmin.
6. C
hange the root user’s password in
phpMyAdmin’s configuration file, if
necessary.
The result of changing the root user’s
password will likely be that phpMyAdmin
is denied access to the MySQL server.
This is because phpMyAdmin, on a local
server, normally connects to MySQL as
the root user, with the root user’s password hard-coded into a configuration
file. After following Steps 1–4, find the
config.inc.php file in the phpMyAdmin
directory—likely /Applications/XAMPP/
xamppfiles/phpmyadmin (Mac OS X
with XAMPP) or C:\xampp\phpMyAdmin
(Windows with XAMPP). Open that file
in any text editor or IDE and change this
next line to use the new password:
$cfg['Servers'][$i]['password'] =
➝ 'thepassword';
Then save the file, and reload phpMyAdmin in your browser.
Creating a database, users,
and privileges
After you have MySQL successfully up
and running, and after you’ve established
a password for the root user, you can add
other users. This is commonly done as part
of creating new databases: To improve
the security of your databases, you should
always create new users to access your
databases rather than using the root user
at all times.
To create a database, simply run a
CREATE DATABASE command:
CREATE DATABASE database_name
The database name can contain numbers,
letters, a dollar sign, and an underscore,
but not spaces. You can run this command
only if you are connected as a user with
CREATE DATABASE permissions.
The MySQL privileges system was
designed to ensure proper authority for
certain commands on specific databases.
This technology is how a web host, for
example, can let several users access several databases without concern. Each user
in the MySQL system can have specific
capabilities on specific databases from
specific hosts (computers). The root user—
the MySQL root user, not the system’s—has
the most power and is used to create
subusers, although subusers can be given
rootlike powers (inadvisably so).
Installation and Configuration
445
When a user attempts to do something
with the MySQL server, MySQL first
checks to see if the user has permission
to connect to the server at all (based on
the username, the user’s host, the user’s
password, and the information in the mysql
database’s user table). Second, MySQL
checks to see if the user has permission
to run the specific SQL statement on the
specific databases—for example, to select
data, insert data, or create a new table.
Table A.1 lists most of the various privileges
you can set on a user-by-user basis.
You can set users and privileges in MySQL
in a handful of ways, but I’ll start by discussing the GRANT command. The syntax
goes like this:
GRANT privileges ON database.*
➝ TO 'username'@'hostname'
➝ IDENTIFIED BY 'password'
For the privileges aspect of this statement, you can list specific privileges from
Table A.1, or you can allow for all of them
by using ALL (which isn’t prudent). The
database.* part of the statement specifies which database and tables the user
can work on. You can name specific tables
using the database.tablename syntax or
allow for every database with *.* (again,
not prudent). Finally, you can specify the
username, hostname, and a password.
The username has a maximum length of
32 characters (as of MySQL 5.7.8; it was 16
in earlier versions). When you’re creating
a username, be sure to avoid spaces—use
the underscore instead, and note that usernames are case-sensitive.
446
Appendix A
TABLE A.1 MySQL Privileges
PRIVILEGE
ALLOWS
SELECT
Read rows from tables.
INSERT
Add new rows of data
to tables.
UPDATE
Alter existing data in tables.
DELETE
Remove existing data from
tables.
INDEX
Create and drop indexes
in tables.
ALTER
Modify the structure of
a table.
CREATE
Create new tables or
databases.
DROP
Delete existing tables
or databases.
RELOAD
Reload the grant tables
(and therefore enact user
changes).
SHUTDOWN
Stop the MySQL server.
PROCESS
View and stop existing
MySQL processes.
FILE
Import data into tables from
text files.
GRANT
Create new users.
REVOKE
Remove users’ permissions.
The hostname is the computer from which
the user is allowed to connect. This could be
a domain name, such as www.example.com,
or an IP address. Normally, localhost is
specified as the hostname, meaning that
the MySQL user must be connecting from
the same computer that the MySQL database is running on. To allow for any host,
use the hostname wildcard character (%):
To create new users using GRANT:
1. L og in to the MySQL client as a
root user.
Use the steps already explained to do
this. You must be logged in as a user
capable of creating databases and
other users.
2. Create a new database D:
GRANT privileges ON database.* TO
➝ 'username'@'%' IDENTIFIED BY
➝ 'password'
But that is also not recommended. When
it comes to creating users, it’s best to be
explicit and confining.
CREATE DATABASE myblog;
This particular database will be used
in Chapter 12.
3. C
reate a user with administrative-level
privileges on the myblog database E:
GRANT SELECT, INSERT, UPDATE,
➝ DELETE, CREATE, DROP, ALTER,
➝ INDEX ON myblog.* TO 'llama'@
➝ 'localhost' IDENTIFIED BY
➝ 'camel';
The password has no length limit but is
also case-sensitive. The passwords are
encrypted in the MySQL database, meaning they can’t be recovered in a plain
text format. Omitting the IDENTIFIED BY
'password' clause results in that user not
being required to enter a password (which,
once again, should be avoided).
This user, llama, can create tables, alter
tables, insert data, update data, and
so forth, on the temp database. This
essentially includes every administrativelevel capability aside from creating new
users. Be certain to use a password—
perhaps more clever than the one used
here.
As an example of this process, you’ll
create two new users with specific privileges on a new database named myblog.
Keep in mind that you can grant permissions only to users on existing databases.
This next sequence will also show how to
create a database.
continues on next page
D Creating a new database.
E Creating an administrative-level user for a single database.
Installation and Configuration
447
4. C
reate a user with basic access to the
database F:
The changes just made won’t take effect
until you’ve told MySQL to reset the list
of acceptable users and privileges, which
is what this command does. Forgetting
this step and then being unable to
access the database using the newly
created users is a common mistake.
GRANT SELECT, INSERT, UPDATE,
➝ DELETE ON myblog.* TO 'webuser'@
➝ 'localhost' IDENTIFIED BY
➝ 'BroWs1ng';
Now the generic webuser can browse
through records (SELECT from tables)
as well as add, edit, and delete them,
but this user can’t alter the structure of
the database. When you’re establishing users and privileges, work your way
from the bottom up, allowing the bare
minimum of access at all times.
Any database whose name begins with
test_ can be modified by any user who has
permission to connect to MySQL. Therefore,
be careful not to create a database named this
way unless it truly is experimental.
The REVOKE command removes users
and permissions.
5. Apply the changes G:
FLUSH PRIVILEGES;
F This user has more restricted rights to the same database.
G Don’t forget this step before you try to access
MySQL using the newly created users.
448
Appendix A
B
Resources
and Next Steps
This book was written to give beginning
PHP programmers a good foundation on
which to base their learning. A few topics
have been either omitted or glossed over,
because the book focuses on covering
the absolute fundamentals. This appendix
lists a number of useful resources, briefly
discusses where to obtain more information for databases and some uncovered
topics, and includes a few tables, both old
and new.
Along with those sites included here, you
should check out the book’s companion
website at www.LarryUllman.com. There
you’ll find all of the book’s code, a support
forum, an errata page, and more.
The PHP Manual
All PHP programmers should familiarize
themselves with, and possibly acquire,
some version of the PHP manual before
beginning to work with the language. The
manual is available from the official PHP
site—www.php.net/docs.php—as well as
from a number of other locations.
You can download the manual in nearly
a dozen languages in different formats.
The official website also has an annotated version of the manual available at
www.php.net/manual/en/ (in English),
where users have added helpful notes
and comments. If you’re having problems
with a particular function, reading the
manual’s page for that function will likely
provide an answer.
A trick pointed out in Chapter 1, “Getting
Started with PHP,” is that you can quickly
access the documentation page for
any specific function by going to
www.php.net/functionname. For example,
the page for the number_format()
function is www.php.net/number_format.
Database Resources
Which database resources will be most
useful to you depends, obviously, on
which database management system
(DBMS) you’re using. The most common
database used with PHP is probably
MySQL, but PHP supports all the standard
database applications.
To learn more about using MySQL,
begin with the official MySQL website
(www.mysql.com). You can download the
MySQL manual to use as a reference
while you work.
If you’re using MySQL, don’t forget to
download and install phpMyAdmin
(www.phpmyadmin.net). Written in PHP,
this is an invaluable tool for working with
a database and much more approachable
for beginners than some other interfaces.
Another area of database resources you
should delve into is SQL. Websites discussing SQL, the language used by every
database application, include the following:
n
n
n
n
SQL Course (www.sqlcourse.com)
Gentle Introduction to SQL
A
(www.sqlzoo.net)
3Schools’ SQL Tutorial
W
(www.w3schools.com/sql/)
SQL.org (www.sql.org)
(All of the above are a bit dated in appearance, but the content still applies.)
My PHP and MySQL for Dynamic Web
Sites: Visual QuickPro Guide (Peachpit
Press, 2012) also discusses SQL and MySQL
in much greater detail than this book.
450 Appendix B
Top 10 Frequently
Asked Questions
(or Problems)
Debugging is a valuable skill that takes
time and experience to fully develop. But
rather than send you off on that journey
ill-equipped, I’ve included the 10 most
frequently seen problems in PHP scripts,
along with the most likely causes. First,
though, here are five of my best pieces
of advice when it comes to debugging a
problem:
n
Run all PHP scripts through a URL.
Trust the error message!
Many beginners have more difficulty
than they should in solving a problem
because they don’t pay attention to
the error message they see. Although
some of PHP’s error messages are cryptic
and a few can even be misleading, if
PHP says there’s a problem on line 22,
the problem is probably on line 22. With
a parse error, maybe the actual problem
was a missing semicolon on line 21.
n
void “trying” things to fix
A
a problem!
If you’re not sure what’s causing the
problem and what the proper fix is,
avoid trying random things as a solution. You’ll likely create new issues
this way and only further confuse the
original problem.
now what version of PHP
K
you’re running.
Some problems are specific to a version
of PHP. Use the phpinfo() function
to test the version in use whenever
you use a server for the first time. Also
make sure you know what version of
MySQL you’re using, if applicable; the
operating system; and the web server
(e.g., Apache 2.4).
n
n
n
Take a break!
The best piece of advice I can offer is
to step away from the computer and
take a break. I’ve solved many, many
problems this way. Sometimes a clear
head is what you need.
If you don’t run a PHP script through a
URL—and this includes the submission of
a form to a PHP script—the web server
will not handle the request, meaning
that PHP will never execute the code.
Resources and Next Steps
451
Moving on, here are the top 10 likely problems you’ll encounter in PHP:
n
ndefined variable or undefined index
U
error A
These errors occur when error reporting is set on its highest level, and they
may or may not indicate a problem.
Check the spelling of each variable or
array index to make sure it’s correct.
Then make sure you initialize variables
prior to referring to them. Also make
sure, of course, that variables that
should have a value actually do!
Variables that don’t have a value
Perhaps you referred to a variable by
the wrong name. Double-check your
capitalization and spelling of variable
names, and then be certain to use
$_GET, $_POST, $_COOKIE, and
$_SESSION as appropriate. If need be,
use the print_r() function to see the
value of any variable.
Blank pages
If you see a blank screen in your browser
after submitting a form or loading a PHP
script, it’s most likely because an error
occurred that terminated the execution of the page. First check the HTML
source code to see if it’s an HTML problem. Then turn on display_errors in
your php.ini configuration file or PHP
script to see what PHP problem could
be occurring.
n
n
n
Call to undefined function… error
Such an error message means you’re
attempting to use a function that PHP
doesn’t have. This problem can be
caused by a misspelling of a function
name, failure to define your own function before calling it, or using a function
that’s not available in your version of
PHP. Check your spelling and the PHP
manual for a non-user-defined function
to find the problem.
A Errors complaining about undefined variables or
indexes often come from spelling or capitalization
mistakes.
452
Appendix B
n
This error message indicates that
you’ve used an HTTP header-related
function—header(), setcookie(), or
session_start()—after the browser
has already received HTML or even
a blank space. Double-check what
occurs in a script before you call any
of these functions. You can also use
output buffering to prevent these errors
from occurring.
n
the database using a different interface
(such as the MySQL client).
Headers already sent error B
Access denied error C
If you see this message while attempting
to work with a database, then the username, password, and host combination
you’re using doesn’t have permission to
access the database. This isn’t normally
a PHP issue. Confirm the values that are
being used, and attempt to connect to
n
upplied argument is not a valid
S
MySQL result resource error
This is another database-related error
message. The message means that a
query result is being used inappropriately. Most frequently, this is because
you’re trying to fetch rows from a
query that didn’t return any records,
commonly due to badly formed SQL.
To solve this problem, print out the
query being run, and test it using
another tool (such as the MySQL
client or phpMyAdmin). Also check that
you’ve been consistent with your variable names.
continues on next page
B Some functions create headers already sent errors if called at the wrong time.
C If the MySQL access information is incorrect, you’ll see a message saying that database access has been
denied.
Resources and Next Steps
453
n
Preset HTML form values are cut off
You must put the value attribute of an
HTML form input within double quotation marks. If you fail to do so, only the
part of the value up to the first space
will be set as that input’s value.
n
onditionals or loops behave
C
unpredictably
These logical errors are quite common.
Check that you haven’t used the wrong
operator (such as = instead of ==) and
that you refer to the proper variables.
Then use print statements to let you
know what the script is doing.
n
Parse errors D
Parse errors are the most ubiquitous
problems you’ll deal with. Even the
most seasoned PHP programmer sees
them occasionally. Check that every
statement concludes with a semicolon
and that all quotation marks, parentheses, braces, and brackets are evenly
paired. If you still can’t find the parse
error, comment out large sections of the
script using the /* and */ characters.
Uncomment a section at a time until you
see the parse error again. Then you’ll
know where in the script the problem is
(or most likely is).
454
Appendix B
D Parse errors are all too common and prevent
scripts from executing.
Next Steps
This book will get you started using PHP,
but you might want to investigate a few
topics further. Before taking on more topics,
however, you should get more experience.
If you need a good library of problems
to work through, check out Project Euler
(https://projecteuler.net/archives).
Security
Web servers, operating systems, databases, and PHP security are all topics that
merit their own books. Although this book
demonstrates writing secure web applications, there’s always room for you to learn
more in this area. Start by checking out
these sites:
n
Study in Scarlett
A
(www.securereality.com.au/
studyinscarlett/)
This is an article about writing secure
PHP code. It’s old but still has fundamental concepts.
Object-oriented programming
The subject of objects and object-oriented
programming (OOP) is not covered in this
book for two reasons:
n
n
It’s well beyond the scope of a beginner’s guide.
ou won’t be restricted as to what
Y
you can do in PHP by not understanding objects.
When you decide you want to learn the
subject, you can search the PHP sites for
tutorials, check out a framework (see the
next section of this appendix), or read
my PHP Advanced and Object-Oriented
Programming: Visual QuickPro Guide
(Peachpit Press, 2013). I dedicate around
150 pages of that book just to OOP (and
there are still aspects of OOP that I didn’t
get to)!
Frameworks
he Open Web Application Security
T
Project (www.owasp.org)
A framework is an established library of
code that you can use to develop sophisticated web applications. By reusing someone else’s proven code, you can quickly
build parts or all of a website.
This is a standard resource for
web security, and its Top Ten
list (www.owasp.org/index.php/
Category:OWASP_Top_Ten_Project)
is a must-read.
There are many PHP frameworks available,
starting with the Zend Framework (http://
framework.zend.com). This framework was
created by some of the key people behind
PHP and is well documented.
You should also read the relevant sections
of the PHP manual and the manual for the
database you’re using. Searching the Internet for PHP and security will turn up many
interesting articles as well. Pay attention to
the dates of articles you read, though, so
you do not pick up outdated habits!
My personal favorite PHP framework, as of
this writing, is Yii (www.yiiframework.com).
I write about Yii extensively on my site.
Many developers are fans of Laravel (https://
laravel.com/), which you ought to consider.
n
Resources and Next Steps
455
This book’s esteemed technical
editor, Paul Reinheimer, is a big fan of
microframeworks, such as Slim
(www.slimframework.com).
Many people love frameworks and what
they offer. On the other hand, it does take
some time to learn how to use a framework, and customizing the framework’s
behavior can be daunting.
JavaScript
JavaScript is a client-side technology that
runs in the browser. It can be used to add
various dynamic features to a website, from
simple eye candy to interactive menus and
forms. Because it runs within the browser,
JavaScript provides some functionality that
PHP cannot. And, like PHP, JavaScript is
relatively easy to learn and use. For more,
see
n
n
n
JavaScript.com (www.javascript.com)
ozilla Developer Network
M
(https://developer.mozilla.org/en-US/
docs/Web/JavaScript)
3School’s JavaScript pages
W
(www.w3schools.com/js/)
I highly recommend you consider learning
jQuery (www.jquery.com) to help you with
your JavaScript needs. jQuery is a JavaScript
framework that’s easy to use, powerful, and
pretty well documented. It’s on the verge
of being overly used, but it’s a great and
reliable way to get started with JavaScript.
Other books
It is my hope that after reading this book
you’ll be interested in learning more about
PHP and web development in general.
Although I could recommend books by
other writers, there’s an inherent conflict
456 Appendix B
there and my opinion as a rival writer
would not be the same as yours as a
reader. So, instead, I’ll just quickly highlight
a couple of my other books and how they
compare to this one.
PHP and MySQL for Dynamic Web Sites:
Visual QuickPro Guide, Fourth Edition
(Peachpit Press, 2012) is kind of a companion to this book. There is some overlap in
content, particularly in the early chapters,
but the examples are different, and it
goes at a faster pace. MySQL and SQL in
particular get a lot more coverage, and
there are three different example chapters:
a multilingual forum, a user registration and
login system, and an e-commerce setup.
My PHP Advanced and Object-Oriented
Programming: Visual QuickPro Guide,
Third Edition (Peachpit Press, 2013) is kind
of a companion to the PHP and MySQL
book just mentioned. This book is much
more advanced, spending a lot of time on
topics such as OOP. It’s not intended to be
read as linearly as this one, but rather each
chapter focuses on a specific topic.
My book Effortless E-Commerce with PHP
and MySQL (New Riders, 2014) covers
everything you need to know to create
fully functioning e-commerce sites. The
book uses two specific examples for doing
so, and incorporates two different payment
systems. Complete comfort with PHP and
MySQL is assumed, however.
Finally, my Modern JavaScript: Develop
and Design (New Riders, 2012) teaches
you this very important programming language using today’s modern techniques.
There’s even a chapter dedicated to using
PHP and JavaScript together!
Tables
This book has a handful of tables scattered
about, the three most important of which
are reprinted here as a convenient reference. You’ll also find one new table that
lists operator precedence (Table B.1). This
partial list goes from highest to lowest (for
example, multiplication takes precedence
over addition).
TABLE B.2 PHP’s Operators
Operator
Usage
Type
+
Addition
Arithmetic
-
Subtraction
Arithmetic
*
Multiplication
Arithmetic
/
Division
Arithmetic
%
Modulus
(remainder of
a division)
Arithmetic
++
Incrementation
Arithmetic
--
Decrementation
Arithmetic
=
ssigns a value
A
to a variable
Assignment
==
Equality
Comparison
!=
Inequality
Comparison
<
Less than
Comparison
>
Greater than
Comparison
<=
L ess than or
equal to
Comparison
>=
Greater than
or equal to
Comparison
!
Negation
Logical
AND
And
Logical
&&
And
Logical
OR
Or
Logical
||
Or
Logical
XOR
Exclusive or
Logical
<=>
Null coalescing
Logical
+ - .
.
Concatenation
String
< <= > >=
.=
Concatenates
to the value of
a variable
Combined
concatenation
and assignment
+=
dds to the
A
value of a
variable
Combined
arithmetic and
assignment
-=
Subtracts from
the value of
a variable
Combined
arithmetic and
assignment
Table B.2 lists PHP’s main operators and
their types. It’s most important to remember that a single equals sign (=) assigns
a value to a variable, whereas two equals
signs (= =) are used together to check
for equality.
TABLE B.1 Operator Precedence
++ -!
* / %
== != === !== <=>
&&
||
= += -= *= /= .= %=
and
xor
or
Resources and Next Steps
457
The various formats for the date()
function may be one of the hardest things
to remember. Keep Table B.3 nearby when
you’re using the date() function.
TABLE B.3 Date( ) Function Formatting
Character
Meaning
Example
Y
Year as 4 digits
2017
y
Year as 2 digits
17
L
Is it a leap year?
1 (for yes)
n
Month as 1 or 2 digits
2
m
Month as 2 digits
02
F
Month
February
M
Month as 3 letters
Feb
j
Day of the month as 1 or 2 digits
8
d
Day of the month as 2 digits
08
l (lowercase L)
Day of the week
Monday
D
Day of the week as 3 letters
Mon
w
Day of the week as a single digit
0 (Sunday)
z
Day of the year: 0 to 365
189
t
Number of days in the month
31
S
English ordinal suffix for a day, as 2 characters
rd as in 3rd
g
Hour; 12-hour format as 1 or 2 digits
6
G
Hour; 24-hour format as 1 or 2 digits
18
h
Hour; 12-hour format as 2 digits
06
H
Hour; 24-hour format as 2 digits
18
i
Minutes
45
s
Seconds
18
u
Microseconds
1234
a
am or pm
am
A
AM or PM
PM
U
Seconds since the epoch
1154523600
e
Timezone
UTC
I (capital i)
Is it daylight savings?
1 (for yes)
O
Difference from GMT
+0600
458 Appendix B
Index
Numbers
0666, explained, 302
0777 permissions, 330
Symbols
//, using with comments, 24
/* and */, using with comments, 24, 26
/= assignment operator, 89
+= assignment operator, 89, 457
-= assignment operator, 89, 457
*= assignment operator, 89
#, using with comments, 24
?> tag, 9
and ?> short tags, 9
, using with comments, 25
+ (addition) operator, 79, 135, 457
& (ampersand), using with forms, 68
&& (and) logical operator, 135, 139, 457
* (assignment) operator, 89, 135
\ (backslash), using with strings, 39
& (bitwise) operator, 310
[] (brackets), using with keys in arrays, 161
{} (braces)
versus parentheses (()), 172
using with conditionals, 143
using with if conditional, 125
. (concatenation) operator, 97, 135, 457
-- (decrement) operator, 88–89, 135, 457
/ (division) operator, 79, 135, 457
$ (dollar sign)
preceding variables with, 36, 58
printing, 82
\\ (double backslashes), using with absolute
paths, 329
" (double quotation marks)
effect of, 44–47
parse error generated by, 170
versus single quotation marks ('), 169
using with constants, 207
using with print, 17, 21
using with strings, 39
' ' (empty string), using with functions, 284
/ (equality) operator, 135
== (equality) operator, 135, 457
= (equals sign), using with variables, 41
> (greater than) operator, 135, 457
>= (greater than or equal to) operator,
135, 457
++ (increment) operator, 88–89, 135, 457
!= (inequality) operator, 457
% (inequality) operator, 135
< (less than) operator, 135, 457
<= (less than or equal to) operator, 135, 457
% (modulus) operator, 135, 457
* (multiplication) operator, 79, 135, 457
! (negation) logical operator, 135, 457
?? (null coalescing) logical operator,
135, 143
<=> (null coalescing) logical operator,
135, 143
| | (or) logical operator, 135, 139, 457
.. (parent folder), 303
() (parentheses)
versus braces ({}), 172
using in calculations, 86–87
using with conditionals, 143
| (pipe), explained, 67
; (semicolon)
error related to, 65
using in MySQL client, 438
using with print command, 15
Index
459
' (single quotation marks)
using, 44
versus double quotation marks ("), 169
<=> (spaceship) operator, 135, 138, 457
- (subtraction) operator, 79, 135, 457
_ (underscore)
using with forms, 51
using with functions, 270
using with variables, 37
A
absolute paths, 203, 303, 329
access to pages, denying and
troubleshooting, 405, 453
action attribute, including in forms, 50,
53, 57
add_entry.php document
creating, 361–365
opening, 368
add_quote.php document
creating, 306–309, 405–408
opening, 311–312
addition (+) operator, 79, 135, 457
addslashes() function, 370
administrator. See is_administrator()
function
Adobe Dreamweaver, 4
alphabetical sort, performing on
arrays, 184
ALTER privileges, 446
ALTER SQL command, 346
AM or PM, formatting with date() function,
211, 458
am or pm, formatting with date() function,
211, 458
ampersand (&), using with forms, 68
AMPPS website, 428, 433
And (&&) logical operator, 135, 139, 457
AND logical operator, 135, 139, 457
Apache, 10
Aptana Studio, 4
arguments
passing, 277
setting default values, 282–284
using with functions, 276–281
arithmetic, performing, 79–82
460 Index
arithmetic operators, 89, 135, 457
array elements
accessing, 161, 163, 170–172, 177
adding, 167–168
deleting, 166
entering, 165
pointing to, 173
array() function, 162–163
array values, printing, 171–172
arrays. See also multidimensional arrays
adding items to, 166–169
creating, 162–165
creating from HTML forms, 186–190
deleting, 166
explained, 160
indexes and keys in, 161
merging, 169
parse errors, 170
printing, 164
versus scalar variable types, 160
sorting, 178–181
syntactical rules, 161
transforming between strings, 182–185
using, 40
asort() functions, using with arrays,
178–180
.aspx extension, 9
assignment operator, 89, 135
associative arrays, 40
Atom, 4
B
backslash (\), using with strings, 39
basename() function, 329
binary digits, 310
birth year, creating input for, 123
Bitnami website, 428, 433
bitwise (&), 310
blank pages, troubleshooting, 452
section, creating, 5
$books multidimensional array, 174–176
books.php document, creating, 174–176,
208–209
bool type, 281
Boolean TRUE and FALSE, 121, 125, 131, 139,
395. See also false value
braces ({})
versus parentheses (()), 172
using with conditionals, 143
using with if conditional, 125
brackets ([]), using with keys in arrays, 161
break language construct, 148
buffer size, setting, 236
C
calculations, performing, 76–78
calculator1.php document
creating, 286–289
opening, 293
calculator.html script, creating, 76–78
camel-hump and camel-case
conventions, 37
case-sensitive searches, performing, 117
character set, setting for database, 392
characters, escaping, 62
checkboxes
confirming, 142
creating for HTML form, 124
presetting status of, 227
closing tag, adding, 5
combined operators, 457
comments, adding to scripts, 24–26
comparison operators, 135–138, 457
concatenating strings, 97–100
concatenation (,) operator, 97, 135, 457
conditionals. See also nesting conditionals
best practices, 143
explained, 121
nesting, 139
troubleshooting, 454
using functions in, 131
configuration changes, confirming, 437
configuring PHP, 436–437
constants. See also predefined constants
benefits, 210
header.html file, 209
naming, 210
printing, 209–210
and superglobal arrays, 294
using, 207–210
control panel
creating for directory, 326–329
viewing file permissions in, 301
control structures
comparison operators, 135–138
default action, 132
die language construct, 150
else statement, 132–134
elseif statement, 144–147
HTML form for, 122–124
if conditional, 125–127
logical operators, 138–143
for loop, 152–156
switch conditional, 148–151
validation functions, 128–131
while loop, 156
$_COOKIE array, 251
cookie data, retrieving with PHP, 251–253
cookies
adding parameters to, 254–256
checking for presence of, 395
comparing to sessions, 260–261
creating, 246–250
data limitation, 250
debugging, 244
deleting, 257–259
encoding values of, 253
expiration value, 254–255
explained, 244–245
httponly argument, 255
path and domain arguments, 254–256
reading from, 251–253
security issues, 245, 252, 255
sending, 247–250
setting expiration date, 255–256
testing safety of, 250
transmitting and receiving, 245
using tabs and newlines with, 252
using to identify administrators, 393
copying files on servers, 324
count() function, using with arrays, 167
CREATE DATABASE command, 445, 447
CREATE privileges, 446
CREATE SQL command, 346
CREATE TABLE SQL command, 356–357
create_table.php document, creating,
357–359
creating documents, 4
CSS (Cascading Style Sheets)
basics, 3
font size and color, 251
Index
461
css folder, creating, 204
CSS templates, 200. See also templates
CSV (comma-separated values) format, 338
customize.php document
creating, 247–250
opening, 255
Cut and Paste, using with templates, 199
D
database connections, making, 348–351
database information, best practices, 351
databases. See also MySQL databases;
query data
connection code, 359, 392
defined, 346
deleting data in, 376–381
inserting data into, 360–365
permissions, 352
resources, 450
retrieving data from, 371–375
updating data in, 382–387
date and time functions
table, 458
working with, 211–213
date() and time() functions
table, 458
using, 211–213, 254
using with sessions, 265
DateTime class, 213
day pull-down menu, creating, 272
daylight savings, formatting with date()
function, 211, 458
days, formatting with date() function,
211, 458
$dbc conditional, 348, 359
DBMS (database management system),
345, 347
debugging
PHP scripts, 440
steps, 27–28
decrement (--) operator, 88–89, 135, 457
decrementing numbers, 88–89
decrypting data, 112
default argument values, 282–284
default case, using with switch
conditional, 151
DELETE FROM tablename query, 381
462
Index
DELETE privileges, 446
DELETE query, running on databases,
376–381
DELETE SQL command, 346
delete_entry.php script, writing, 376–381
delete_quote.php document, creating,
418–421
deleting
arrays and array elements, 166
cookies, 257–259
data in databases, 376–381
files, 324
quotes, 418–421
sessions, 266–267
delineated format, explained, 338
denying access to pages, 405
deprecated function, explained, 20
die() and exit() functions, 354
directories. See also web root directory
creating, 330–337
displaying contents of, 326–327
navigating, 325–329
permissions, 302
directory control panel, creating,
326–329
dirname() function, 329
display_errors setting
using, 63–64
using with cost calculator, 80
using in debugging, 28
division (/) operator, 79, 135, 457
documents, creating, 4
dollar sign ($)
preceding variables with, 36, 58
printing, 82
double backslashes ( \\), using with absolute
paths, 329
double quotation marks (")
effect of, 44–47
parse error generated by, 170
versus single quotation marks ('), 169
using with print, 17, 21
using with strings, 39
double-precision floating-point numbers, 38
doubles, 38
DROP SQL command, 346, 446
drop-down menu, creating for HTML
form, 124
E
Edit menu, accessing for templates, 199
edit_entry.php document, creating,
383–387
edit_quote.php document, creating,
412–417
else statement, 132–134
elseif statement, 144–147
email, sending, 228–232
email address
creating inputs for, 123
validating, 129
empty() function, 128, 131
empty string (' '), using with functions, 284.
See also strings
encoding
explained, 5
external files, 206
encrypting
data, 112
passwords, 337
ENTRIES table, columns in, 356
equality (/ and ==) operator, 135, 457
equals sign (=), using with variables, 41
error codes for files, 317
Error level, 65
error messages. See also parse errors;
troubleshooting
Add a Blog Entry, 364
arguments, 277
connection attempt refused, 10
Could not connect to the database, 350
Could not create the table, 358
Delete an Entry, 381
displaying in scripts, 63–64
double quotation marks ("), 21
email address and password, 402
foreach loop, 176
functions, 275
header() call, 233
include() function, 201
nonexisting variables, 61
Not Found, 14
output buffering, 233
permission denied, 299
for registration results, 142
related to color selection, 147
related to external files, 201, 206
related to header() call, 233
require() function, 201
setcookie() function, 246
trusting, 28, 451
unassigned value, 72
undefined function call, 275
Undefined variable, 43
error reporting, 65–67
error suppression operator, 354
error_reporting levels and constants,
65–67
event.html document, creating, 186–187
event.php document, creating, 188–190
everyone permission, 298, 301
exclusive or (XOR) logical operator, 139
execute permission, 298
exit() and die() functions, 237, 354
explode() function
and fgets(), 338
using with arrays, 182, 184
external files. See also file extensions
benefits, 206
closing PHP tag, 206
using, 201–206
writing to, 306–309
F
FALSE and TRUE, 121
false value, 19. See also Boolean TRUE
and FALSE
fclose() function, 305
feedback.html document
creating, 51
opening, 56
feof() function, 338
fgetcsv() function, 338, 342
fgets() function, 338, 348
file error codes, 317
file extensions. See also external files
being aware of, 9
and included files, 206
file() function, 313, 338
file navigation, 203
file paths, 303
file permissions, 298–302, 352
FILE privileges, 446
file uploads, handling, 316–324
Index
463
FILE_APPEND constant, 303–304
file_exists() function, 300
file_get_contents() function, 313
fileatime() function, 329
filemtime() function, 328
filename() function, 325
fileperms() function, 329
files. See also saving documents and scripts
copying on servers, 324
deleting, 324
locking, 310–312
organizing, 204
reading from, 313–315
reading incrementally, 338–342
writing to, 303–309
$_FILES array, elements of, 317
filesize() function, 328
filter() function, 131
finfo_file() function, 329
firewalls, 429
first name, checking entry of, 223
flag variable, creating for sticky form, 222
float type, 281
floating-point numbers, 38
flock() lock types, 310
folders and files, organizing, 204
font size and color, setting in CSS, 251
footer, adding to template, 197
footer file, creating for template, 200
footer.html document
creating, 398–399
opening, 212
fopen() function, 305, 348
for loop, 152–156
using with functions, 272
using with numerically indexed arrays, 172
foreach loop
error generated by, 176, 189
using with array elements, 170–172
using with directory control panel, 328
using with functions, 272
using with multidimensional arrays, 177
form data. See also HTML forms; sticky
forms
accessing, 62
displaying, 62
processing, 217
receiving in PHP, 58–62
464
Index
sending to pages manually, 68–72
validating, 128–131
form methods, choosing, 54–57
form submission, determining, 214–215
form tags, 50
creating, 122
using with functions, 274
formatting numbers, 83–85
forms. See HTML forms
forums, 96
frameworks, 455–456
function keyword, 271
function_exists() function, 275
functions. See also PHP functions;
undefined functions; user-defined
functions
accessing, 281
arguments, 276–281
with arguments and value, 287
best practice, 275
calling without arguments, 282
creating and calling, 272–275
default argument values, 282–285
defining with parameters, 276–277
design theory, 295
error related to, 65
invoking, 271
looking up definitions of, 18–20
naming conventions, 270
return statement, 285
returning values, 285–289
syntax, 275–276
user-defined syntax, 270–271, 275
using spaces with, 85
using within conditionals, 131
functions.php script
code, 397
creating, 394–395
fwrite() function, 305, 348
G
garbage collection, 267
A Gentle Introduction to SQL website, 450
$_GET and $_POST, 55–62, 68
$_GET array, 161
GET method, using with HTTP headers, 240
getrandmax() function, explained, 91
Git version control software, 11
glob() function, 329
global statement, 290–294
GMT difference, formatting with date()
function, 211–212, 458
GRANT privileges, 446–448
greater than (>) operator, 135, 457
greater than or equal to (>=) operator,
135, 457
$greeting variable, 97
grocery list array, 160
H
handle_form.php document
creating, 59
opening, 66
handle_post.php document
creating, 79–82, 98–99
opening, 84, 86, 88, 101, 106, 109, 115, 118
handle_reg.php document
creating, 126–127
opening, 129, 132, 136, 140, 145, 149
hash, 40
tag, creating, 5
header file, creating for template, 198–199,
203
header() function
and HTTP headers, 237–240
and output buffering, 233
using exit with, 150
header lines, creating, 4
header.html document
creating, 396–397
opening, 209, 234
headers already sent error, troubleshooting,
453
headers_sent() function, 240
Hello, World! greeting, sending to browser,
2, 16–17
hello1.php document
creating, 16–17
opening, 21
hello2.php document
creating, 21-22
opening, 25
hello.html script, creating, 69–70
hidden extensions, being aware of, 9
hidden input, checking for, 219
home page, creating, 422–425
hours, formatting with date() function,
211, 458
HTML (Hypertext Markup Language)
current version, 2
resources, 6
sending to browsers, 21–23
syntax, 2
HTML comments, accessing, 26
.html extension, 9
HTML forms. See also form data; sticky
forms
control structures, 122–124
for cookies, 249
creating, 50–53
creating arrays from, 186–190
displaying and handling, 214, 216–219
event.php page, 187–190
handling, 59–61
handling with PHP, 214–219
hidden type of input in, 62
making sticky, 220–227
for numbers, 76–78
radio-button value, 62
re-displaying, 219
for strings, 94–96
for strings and arrays, 183–185
HTML pages
creating, 4–6
example, 6
versus PHP scripts, 7
viewing source, 23
HTML source code, checking, 28
HTML tags
addressing in PHP, 106–107
using PHP functions with, 104–107
tag, adding, 5
HTML5, 2
htmlentities() function, 384–385
htmlspecialchars() function, 328
HTTP (Hypertext Transfer Protocol), 237
HTTP headers, manipulating, 237–240
I
id primary key, 387, 391
if conditional, 121, 125–127, 140
Index
465
if-else conditional, 132–134, 143
if-elseif conditionals, simplifying,
148–150
if-elseif-else conditional, 144–147
IIS (Internet Information Server), 10
implode() function, using with arrays,
182, 184
K
keyboard shortcuts
Cut and Paste, 199
Edit menu, 199
ksort() functions, using with arrays,
178–180
include() function
failure of, 201
and parentheses (()), 206
using with constants, 207
using with external files, 202
increment (++) operator, 88–89,
135, 457
index errors, troubleshooting, 452
INDEX privileges, 446
indexed arrays, 40, 165
index.php document, creating,
202–205, 423–425
inequality ( % ) operator, 135
inequality (!=) operator, 457
ini_set() function, 263
INSERT INTO tablename SQL command,
360, 363
INSERT privileges, 446
INSERT SQL command, 346
installation
on Mac OS X, 433–435
on Windows, 428–432
int type, 281
integers, 38
invalid MySQL argument error,
troubleshooting, 453
is_administrator() function,
394, 406
is_array conditional, 189
is_dir() function, 325
is_file() function, 325
is_numeric() function, 128, 131
is_readable() function, 315
isset() function, 128, 131
J
JavaScript, 105, 456
join() function, 185
JQuery website, 456
466 Index
L
language constructs, 150
languages. See multilingual
web pages
Laravel PHP framework, 455
leap year, formatting, 458
legacy file writing, 305
less than (<) operator, 135, 457
less than or equal to (<=) operator,
135, 457
linking strings, 100
links
using to pass values, 68–69
using with multiple values, 72
list() function
using with array elements, 189
using with functions, 288
list_dir.php document, creating,
326–329
list_dir.php script, 325
list.html document, creating, 183
list.php document, creating,
184–185
local variables, 97, 290
locking files, 310–312
$loggedin variable, 339, 341
logical operators, 135, 138–143, 457
login form, displaying, 218–219
login page
HTTP headers added to, 240
purpose of, 216–217
login.php document
creating, 216–219, 266–267,
338–342, 400–404
opening, 238, 262
loops
nesting, 156
troubleshooting, 454
ltrim() function, 119
M
Mac OS X
Get Info panel, 302
installation on, 433–435
installing XAMPP on, 434–435
Magic Quotes, 62
mail() function, 228–230, 232, 437
make_date_menus() function, 274
make_text_input() function, 279, 295
MAMP website, 433
MariaDB, installation by XAMPP, 429
math. See arithmetic
memory allocation, error related to, 65
menus.php document, creating, 272–274
merging arrays, 169
messages, printing, 16
meta tags, using for encoding, 5
method attribute, using with forms, 54–57
microseconds, formatting with date()
function, 211
microseconds parameters, formatting with
date() function, 458
minutes, formatting with date() function, 211
modulus ( % ) operator, 135, 457
money_format() function, using with
numbers, 85
month pull-down menu, creating, 272
month values, formatting, 458
monthly payment, calculating, 81
months, formatting with date() function, 211
move_uploaded_file() function, 317,
319–320
Mozilla Developer Network website, 456
mtrand() function, using, 90–91
multidimensional arrays, creating, 40,
173–177. See also arrays
multilingual forums, 96
multilingual web pages, creating, 5
multiplication ( * ) operator, 79, 135, 457
myblog database, 349
myquotes database, 390
MySQL client
debugging PHP scripts, 440
using, 438–440
using semicolon (;) in, 438
on Windows, 440
MySQL database management system
(DBMS), 345
MySQL databases. See also databases;
tables
apostrophes (') in form data, 370
connecting to, 348–351
creating, 445, 447
creating tables, 355–359
error handling, 352–354
inserting records into, 365
localhost value, 351
myblog, 349
queries and query results, 347
sending SQL statements to, 346
support in PHP, 346
username and password values, 349
MySQL users
creating, 445–448
privileges, 445–448
root user password, 443–445
mysqli_affected_rows() function, 380, 387
mysqli_connect.php document
creating, 348–350, 392
opening, 353
mysqli_error() function, 352–354
mysqli_fetch_array() function, 371–372,
375
mysqli_num_rows() function, 375, 387
mysqli_query() function, 346, 357, 371, 379
mysqli_real_escape_string() function,
367–370, 383, 385, 387
N
name value, using to print greetings, 70–72
$name variable, creating via concatenation, 99
names, concatenating, 100
natsort() functions, using with strings, 181
navigating
directories, 325–329
files, 203
negation (!) logical operator, 135, 457
nesting conditionals, 139, 217–218. See also
conditionals
nesting loops, 156
newlines (\n)
converting to breaks, 101–103, 107
using, 22
using with cookies, 22, 252
Nginx, 10
Index
467
nl2br() function
looking up, 19
using concatenation with, 100
using with newlines, 102
nobody permission, 302
Not Found response, receiving, 14
Notice error level, 65
NULL, using with functions, 284
null coalescing (??) logical operator, 135, 143
null coalescing (<=>) logical operator, 457
number_format() function, using, 83–85
numbers. See also random numbers
creating HTML form for, 76–78
formatting, 83–85
incrementing and decrementing, 88–89
types of, 38
valid and invalid, 38
numeric indexes
setting, 165
using for loop with, 172
O
ob_clean() function, 234, 236
ob_end_flush() function, 234–237
ob_flush() function, 236
ob_get_contents() function, 236
ob_get_length() function, 236
ob_start() function, invoking, 233–234
octal format, 302
$okay variable, using with control structures,
126–127, 129–130
OOP (object-oriented programming), 455
The Open Web Application Security Project
website, 455
operator precedence table, 457
operators
for arithmetic, 79
table, 457
or (| |) logical operator, 135, 139, 457
OR logical operator, 135, 139, 457
ORDER BY RAND() clause, 424
ordinal suffix, 458
organizing files and folders, 204
others permission, 301
output buffering, 233–236, 250
owner of file, explained, 298
468 Index
P
pages. See HTML pages
parameters, defining functions with,
276–277
parent folder (..), 303
parentheses (())
versus braces ({}), 172
using in calculations, 86–87
using with conditionals, 143
Parse error level, 65
parse errors. See also error messages;
troubleshooting
avoiding, 170
double quotation marks ("), 58
receiving, 43
troubleshooting, 454
password values, validating, 136–137
password_hash() function, 112, 337
password_verify() function, 337
passwords
encrypting, 337
entering in HTML form, 123
managing, 124
validating, 130, 224
permissions, 298–302, 309, 352
PHP
configuring, 436–437
configuring for file uploads, 318–319
PHP code, storing, 236
.php extension, 9
PHP functions, using with HTML tags,
104–107. See also functions
PHP manual, using, 18–20, 449
PHP scripts
accessing, 14
adding comments to, 24–26
creating, 8, 70–71
debugging, 28, 440
executing, 9
versus HTML pages, 7
requesting, 215
running through URLs, 451
testing, 12–14
testing in browsers, 12–14
) operator, 135, 138, 457
spacing of HTML code, displaying, 22
sprintf() function, using with numbers, 85
SQL (Structured Query Language), features
of, 346–347
SQL commands, 346
SQL Course website, 450
SQL statements, sending to MySQL, 346
SQL.org website, 450
square brackets ([]), using with keys in
arrays, 161
sticky forms, 220–221. See also form data;
HTML forms
sticky text inputs, creating, 278–281
sticky1.php document
creating, 278–281
opening, 283
str_ireplace(), using with trim(), 118–119
string case, adjusting, 117
string type, 281
strings. See also empty string (' ');
substrings
checking formats of, 116
comparing, 113
concatenating, 97–100
counting backward in, 114
creating HTML form for, 94–96
encoding and decoding, 108–112
encrypting and decrypting, 112
indexed position of characters in, 114
linking, 100
performing case-sensitive searches, 117
replacing parts of, 117–119
transforming between arrays, 182–185
using, 39
strip_tags() function, 104, 107
stripslashes() function, using with Magic
Quotes, 62
strtok() function, 113
strtolower() function, 218
A Study in Scarlett website, 455
Index
471
Sublime Text, 4
submit button, creating for HTML
form, 124
substrings, finding, 113–116. See also strings
subtraction (-) operator, 79, 135, 457
superglobals and constants, 161, 294
switch conditional, 121, 148–151
T
tab (\t), using with cookies, 252
tables. See also MySQL databases
creating, 355–360
primary keys, 355
using primary keys in, 387
tags. See HTML tags
tax rate, calculating, 81
$tax variable, 293
template.html document
creating, 195–197
opening, 198, 200
templates. See also CSS templates
creating, 194
footer file, 200
header file, 198–199
layout model, 195–197
website project, 396–399
testing
PHP scripts, 12–14
safety of sending cookies, 250
text, sending to browsers, 15–17
text area, presetting value of, 227
text file, creating for file permissions,
299–300
text input type, checking, 138
textarea form element
adding to forms, 53
using with newlines, 101–102
time() and date() functions
table, 458
using, 211–213, 254
using with sessions, 265
time zones
formatting with date() function,
211–212, 458
setting for servers, 213
tokens, substrings as, 113
Transmit FTP application, 301
472
Index
trim() function
using in comparisons, 138
using with strings, 117–119
troubleshooting. See also error messages;
parse errors
access denied, 453
advice, 451
blank pages, 452
calls to undefined functions, 452
conditionals and loops, 454
headers already sent, 453
invalid MySQL argument, 453
parse errors, 454
preset HTML form values cut off, 454
undefined variable and index
errors, 452
variables without values, 452
TRUE and FALSE, 121, 395
true value, 19. See also Boolean TRUE and
FALSE
TRUNCATE TABLE tablename query, 381
types, declaring, 289
U
uasort() functions, using with arrays, 181
undefined functions, troubleshooting calls
to, 452. See also functions
Undefined index notice, 170
Undefined offset notice, 170
Undefined variable error, 43
underscore ( _ )
forms, 51
functions, 270
variables, 37
unlink() function, 324
UPDATE privileges, 446
UPDATE SQL command, 346, 382–387
upload_file.php document, creating,
319–324
uploaded files, renaming, 324
uploads folder, creating, 318
urlencode() function, 108–112
“user,” defining, 299
user-defined functions, 270–271, 275, 278,
288, 393–395. See also functions
username, using on registration
pages, 124
users folder, creating, 330
users.txt script, 339–340
UTF-8 encoding, 5–6
V
validating, passwords, 224
validation functions, 128–131
value types, declaring, 289
values, assigning to variables, 135
$var variable, 291
var_dump() function, using with
arrays, 165
variable errors, troubleshooting, 452
variable names, case sensitivity of, 36
variable scope
explained, 290–292
global statement, 293–294
variables. See also predefined variables
accessing, 42–43
arrays, 40
assigning values to, 135
avoiding referring to, 131
documenting purpose of, 37
error related to, 65
explained, 32
incrementing values of, 88–89
minimizing bugs, 37
naming conventions, 37
numbers, 38
referring to, 37
scalar and nonscalar, 41
strings, 39
syntax, 36–37
types of, 38–40
valid and invalid, 37
validating, 147
values, 41–43
warnings related to, 37
variables.php document, creating, 42–43
version control software, 11
view_blog.php document, 386–387
view_entries.php document, creating,
372–375
view_quotes.php document, creating,
314–315, 409–411
view_settings.php document, creating,
251–253
W
W3Schools
JavaScript pages, 456
SQL Tutorial website, 450
WAMP website, 428
Warning error level
web pages. See HTML pages
web root directory, 298. See also directories
web server applications, 10. See also servers
website project. See also site structure
adding quotes, 405–408
administrator, 390
creating home page, 422–425
database connection, 392
deleting quotes, 418–421
denying access, 405
editing quotes, 412–417
file organization and structure, 391
footer.html document, 398
identifying goals of, 390
listing quotes, 409–411
logging in, 400–403
logging out, 404
myquotes database, 390
security, 390
template, 396–399
user-defined function, 393–395
websites
Adobe Dreamweaver, 4
AMPPS, 428, 433
Apache, 10
Aptana Studio, 4
Atom, 4
Bitnami, 428, 433
Git version control software, 11
IIS (Internet Information Server), 10
JavaScript resources, 456
MAMP, 433
Nginx, 10
PHP frameworks, 455–456
PHP manual, 18
PhpStorm, 4
Project Euler, 455
security resources, 455
SQL resources, 450
Sublime Text, 4
WAMP, 428
Windows installers, 428
XAMPP, 428, 433
Index
473
welcome.html file, saving, 6
welcome.php document, creating, 238–240,
264–265
while loop, 152, 156, 338
white space, using, 22
whole numbers, 38
Windows
installation on, 428–432
installing XAMPP on, 430–432
wordwrap() function, 107
write permission, 298, 301–302
writeable directory, creating, 318–319
writing to files, 303–309
X
XAMPP
command prompt, 439
files installed by, 429, 433
and firewalls, 429
installing on Mac OS X, 434–435
installing on Windows, 430–432
MariaDB, 429
website, 428, 433
XOR (exclusive or) logical operator, 135, 139,
457
XSS (cross-site scripting) attacks, 105
Y
year pull-down menu, creating, 272
year values
formatting, 211, 458
validating, 136–137, 141
Yii PHP framework, 455
474
Index
Source Exif Data:
File Type : PDF
File Type Extension : pdf
MIME Type : application/pdf
Linearized : No
Has XFA : No
Language : en-US
XMP Toolkit : Adobe XMP Core 5.6-c015 84.158975, 2016/02/13-02:40:29
Trapped : False
Keywords :
PDF Version : 1.6
Producer : 3-Heights(TM) PDF Security Shell 4.5.24.6 (http://www.pdf-tools.com)
Code Mantra 002 C0020 LLC : http://www.codemantra.com
Universal 0020 PDF : The process that creates this PDF constitutes a trade secret of codeMantra, LLC and is protected by the copyright laws of the United States
Create Date : 2016:05:31 04:35:58-06:00
Metadata Date : 2016:11:08 13:45:26+02:00
Creator Tool : Adobe InDesign CC 2015 (Macintosh)
Modify Date : 2016:11:08 13:45:26+02:00
Instance ID : uuid:8921d919-afa1-4513-877e-514069788af3
Document ID : xmp.id:ac2de5b3-6ce8-4ef2-b553-eac18645dded
Rendition Class : proof:pdf
Original Document ID : adobe:docid:indd:9cfe0242-9082-11dd-90b8-f68ac584c7a4
Derived From Instance ID : xmp.iid:7befc07b-4fb9-4cd1-b706-869420c897d0
Derived From Document ID : xmp.did:ac9c8662-314a-45ed-892a-c06604153ea3
Derived From Original Document ID: adobe:docid:indd:9cfe0242-9082-11dd-90b8-f68ac584c7a4
Derived From Rendition Class : default
History :
Format : application/pdf
Title : PHP for the Web: Visual QuickStart Guide
Creator : Larry Ullman
Subject :
Description :
Page Layout : SinglePage
Page Mode : UseOutlines
Page Count : 497
Author : Larry Ullman
Universal PDF : The process that creates this PDF constitutes a trade secret of codeMantra, LLC and is protected by the copyright laws of the United States
Code Mantra LLC : http://www.codemantra.com