PHP - The Complete Reference - Steven Holzner Curvebreakers
PHP - The Complete Reference - Steven Holzner Curvebreakers
Covers
PHP 5.2
Holzner, Steven.
PHP: the complete reference/Steven Holzner.
p. cm.
ISBN 0-07-150854-6 (alk. paper)
1. PHP (Computer program language) I. Title.
QA76.73.P224H64 2007 ( ,
005.2762—dc22
2007044733
McGraw-Hill books are available at special quantity discounts to use as premiums and sales
promotions, or for use in corporate training programs. For more information, please write
to the Director of Special Sales, Professional Publishing, McGraw-Hill, Two Penn Plaza,
New York, NY 10121-2298. Or contact your local bookstore.
Copyright © 2008 by The McGraw-Hill Companies. All rights reserved. Printed in the
United States of America. Except as permitted under the Copyright Act of 1976, no part of
this publication may be reproduced or distributed in any form or by any means, or stored
in a database or retrieval system, without the prior written permission of publisher.
ISBN 978-0-07-150854-4
MHID 0-07-150854-6
Information has been obtained by McGraw-Hill from sources believed to be reliable. However, because of the possibility of
human or mechanical error by our sources, McGraw-Hill, or others, McGraw-Hill does not guarantee the accuracy, adequacy,
or completeness of any information and is not responsible for any errors or omissions or the results obtained from the use of
such information.
I
Contents at a Glance
1 Essential PHP . 1
2 Operators and Flow Control . 41
3 Strings and Arrays . 81
4 Creating Functions . 123
5 Reading Data in Web Pages . 161
6 PHP Browser-Handling Power . 203
7 Object-Oriented Programming . 245
8 Advanced Object-Oriented Programming . 281
9 File Handling . 319
10 Working with Databases .. 361
11 Sessions, Cookies, and FTP . 395
12 Ajax . 433
13 Advanced Ajax . 467
14 Drawing Images on the Server . 501
15 XML and RSS . 537
Index . 575
VI!
V
' ' ‘
'
Contents
Introduction. xvii
1 Essential PHP . 1
Enter PHP . 1
Getting PHP . 3
PHP on the Internet . 4
PHP on Your Local Machine . 5
Creating Your Development Environment . 6
Creating a First PHP Page ..... 8
Running Your First PHP Page . . 9
Some Troubleshooting . 9
Mixing HTML and PHP . 10
Printing Some Text . 14
Printing Some HTML . 16
More Echo Power . 17
Using PHP "Here" Documents . 19
Command-Line PHP . 20
Adding Comments to PHP Code . 24
Working with Variables . 26
Storing Data in Variables . 27
Interpolating Strings . 31
Creating Variable Variables . 33
Creating Constants . 35
Understanding PHP's Internal Data Types . 37
IX
X PHP: The Complete Reference
12 Ajax . 433
Getting Started with Ajax . 433
Writing Ajax . 435
Creating the XMLHttpRequest Object . 436
Opening the XMLHttpRequest Object .•.. 440
Handling Downloaded Data . 441
Starting the Download . 445
Creating XMLHttpRequest Objects . 446
Ajax with Some PHP . 448
Passing Data to the Server with GET . 449
Passing Data to the Server with POST . 453
Handling XML . 456
Handling XML with PHP . 464
Index . 575
•
■V.
«
#
Introduction
T his book is your guide to PHP, and it was written to be as complete and comprehensive
as possible. It puts the power of PHP to work for you, emphasizing seeing example
after example. We push the PHP envelope here, in more than a hundred examples,
ready to run.
PHP is a hot topic—it's become the most popular server-side language by far. A Google
search for “PHP" results in a hefty 2,890,000,000 hits. That's two billion, eight hundred and
ninety million hits, far more than any other server-side language can boast.
What's behind this incredible popularity? PHP is fast and easy to use, fast and easy to
develop in. You can mingle it with HTML in your Web pages. You can write it easier than
other languages—PHP has learned from their mistakes. You don't need to compile it, as you
do with other languages, before running it. But more than all that, developing with PHP is
just plain fun. It's just a terrific language that people who write server-side code really enjoy.
And this book is all about bringing you that experience.
People who have Web sites are requiring more and more power these days, and
increasingly, they're finding their answer in PHP. No longer content to be limited to
working with JavaScript in the browser, they want to have the power of writing code to
be executed on the server. Guest books, interactive calendars, databases, autoresponder
e-mailers, blogs, chat rooms—the things you can do with PHP are unlimited. Using PHP,
you have total control over your Web applications and the good part is that they re not
much harder to write than the typical Web page. You can do a lot with a little.
You're getting into PHP at the right time. Excitement is soaring, and PHP is flying high.
This book tries to stay as true to the spirit of that excitement as possible, giving you the full
PHP experience. You're going to find more PHP in this book than in any similar book as you
get the complete details on the PHP story.
. -.^
XVII
xviii PHP: The Complete Reference
And this book was written so that you don't need a lot of background to use it. In fact,
the only thing you need to know before reading through and working with this book is a
knowledge of HTML. You won't need to be an HTML wizard, but you'll need to know some
HTML in this book. If you don't have any clue when it comes to HTML, now's the time to
look up an online tutorial on the subject.
We use PHP 5.2 in this book—and you may already have it on your server. If not, you'll
see where to get it for free in this book, and how to install it. In fact, you won't even need a
Internet server that supports PHP to read this book—if you wish, you can develop and test
your PHP pages all on the same computer. On the other hand, if'you want to put your PHP
code on the Internet, you'll need to use an ISP that supports PHP. Check with your ISP to
find if they support PHP—more and more ISPs are doing so every day.
This book has been written to be as complete as possible, and to be at the top of its field.
If you have questions or comments, please drop me a line—I'd love to hear from you.
Enter PHP
Welcome to the world of PHP. Officially, PHP stands for "PHP: Hypertext Preprocessor,"
but it's also still known around the world by its original name, Personal Home Page. It s the
server-side programming language that's taken the Web world by storm PHP is far and
away the most popular programming language for use on Web servers. That's the idea
behind PHP: being able to do some easy programming on the Web server, creating
everything from online databases to guest books, from customer schedulers to chat rooms,
from file uploading tools to shopping carts. It's all possible with PHP.
Where did PHP come from? PHP users are sometimes startled to learn that PHP has been
around for quite some time; it was created by Rasmus Lerdorf in 1994 (Rasmus wanted a
way of logging who was looking at his online resume). PHP got such a good reputation that
by 1995 it was available for use by other people, and the PHP revolution was underway.
PHP at that time was called Personal Home Page, or Personal Home Page Tools. At that
time, as you might expect, PHP was very simple, and could be used to cieate Web page hit
counters, guest books, and the like. The 1995 version of PHP was called PHP/FI Version 2
(FI was an HTML form reader package, also written by Rasmus).
In time, Rasmus added support for interfacing with Mini SQL (mSQL), and PHP/FI
started growing at an astonishing rate as more people contributed code to it. There was a
real need for an easy Web server programming language then, and the number of PHP
pages just kept growing. In 1996, PHP/FI was already being used by about 15,000 Web
pages. In 1997, that number grew to more than 50,000.
1
2 PHP: The Complete Reference
Things started happening fast at that point. In 1997, PHP/FI became just PHP, and more
people got involved as PHP teams started appearing. Much core work was redone by Zeev
Suraski and Andi Gutmans, and PHP Version 3 appeared—much of it totally rewritten.
Today, PHP is everywhere you look on the Web, with an estimated 100 million PHP
pages (it's hard to get accurate statistics—if you do a search on Google for PHP, for
example, you get an astounding estimated 2,740,000,000 hits). PHP is still true to its original
name: Personal Home Page, because it gives you the easiest way to make your Web pages
come alive on the server. But PHP has also become a very professional language, suitable
for top-notch sites.
You're going to see it all in this book. This is where your Web pages and applications
come alive.
The lid is off the box when you start to work with PHP now. Just about anything you
can do on the Web, you can do with PHP. No longer do Web pages have to be static,
unchanging things—you're going to be able to interact with users in a safe and secure way,
sending them back Web pages tailored to their input. And it all happens in real time.
You can handle button clicks, radio button selections, and list box choices with ease
using PHP. You can code simple Web applications such as guest books, or do anything
advanced that's possible on the Web: create database applications, client/server
applications, and multilayer data processors; create graphics interactively on the server
and send them back to the browser; register students for your online school; create Web-
based classrooms; and more.
Chapter 1: Essential PHP 3
Static Web pages are, well, static. They can display data just fine, as well as text and
images. But there's nothing really going on there—the user can't interact with anything.
PHP changes all that by making those Web pages come alive—things start happening on the
server side. Unlike languages like JavaScript, which work in the browser and don't create
any lasting effects (JavaScript can't write files, and it can't work with data on the server),
languages that execute on the server can be used as the basis of true Web applications. Users
will be able to open your pages, seeing everything they'd expect from a full-fledged
application, including everything from text fields they can enter text in to tables full of data
you create on the fly, from retrieving data from databases to fluidly creating graphics—
everything you might see on the most professional interactive Web application is now
within your grasp. That's the name of the PHP game—being able to respond to the user
dynamically, on the fly.
Getting PHP
This book will use PHP 5.2.0, whose official Web site is www.php.net (PHP missed its
chance for php.com—that's now the Parents Helping Parents Web site). You're going to
need PHP to work with this book, and that's going to mean getting access to a Web server
that runs it.
4 PHP: The Complete Reference
As of this writing, PHP 6 is in the works. There are many minor changes coming up in
PHP 6—none of which should stop your PHP 5 code from running—and a major change:
support for Unicode. Unicode (www.unicode.org) is a character set that's designed to
encompass many of the world's languages, unlike PHP today. As I'm writing this, support
for Unicode in PHP 6 is transparent—that is, your PHP 5 code will run fine. At most, you'll
be required to place a directive at the beginning of your scripts indicating whether you
want Unicode support turned on or off. And then you'll have the full Unicode character
set—everything from Arabic to Cherokee to Tibetan.
I m going to use % as a generic command prompt in this book, standing for the command
prompt in Windows, Linux, and so forth):
• /
%php -v
If PHP is installed and accessible, you'll see the PHP version and date displayed like this:
%php -v
PHP 5.2.0 (cli) (built: Nov 2 2006 11:57:36)
Copyright (c) 1997-2006 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2006 Zend Technologies
The other way to test if you have PHP installed is to upload a PHP script and see if it
runs. To do that, check out the sample scripts you'll see in this chapter. Upload such a test
script to your ISP, and see if you can access it in your browser.
Note that on Unix-based systems, you have to first explicitly set the permission of the
script to executable, and most FTP utilities (File Transfer Protocol utilities, including the one
built into Windows and accessible by typing ftp at a DOS command prompt) will let you set
that permission. If you have a PHP script on a Unix-based server, you should set its
permissions to Owner: Execute, Read, and Write; Group: Execute and Read; and Public:
Execute and Read. Numerically, that works out to a permission setting of 755 for PHP
scripts on Unix-based servers.
Tip If you want a list of ISPs that already run PHP, take a look at www.php.net/links.phptthosts.
The most popular Web server for use with local installations of PHP is the Apache Web
server, which you can get at http://httpd.apache.org/. In Windows, however, it's even
easier to use Microsoft Internet Information Server (IIS), which comes already built in to
most versions of Windows. If you want to check if you've got IIS, look for the directory
C:\inetpub—if you've got it, you've got IIS.
You'll also be asked what extensions you want to install (an extension is a PHP add-on,
adding functionality). To handle the material this book is going to cover, select the MySQL,
GD2, and SMTP extensions. ' 1
Tip If you get stuck during the installation process, you can download the PHP documentation
from www.php.net/download-docs.php—there's a special section for help with installation, and
that section is extensive, covering an enormous array of issues.
Downloading the PHP documentation is an excellent idea in any case—that's the official
PHP manual, the one that can give you the answers you need if you want the official word
on a PHP point.
(which means that items like PHP keywords appear in various colors, making it easy to pick
out what's going on at a glance); and automatic deployment, where the IDE can send your
PHP pages up to your ISP when you click a button or select a menu item.
Here's a starter list of IDEs available online that can handle PHP. Note, however, that
most of them are going to cost money, and although they have some features that are nice to
have, we won't rely on those features in this book:
If you're running PHP on an ISP, you're also going to need some way of uploading your
PHP to your Web server. You can use the same method you use to upload standard HTML
pages to your ISP. For example, you can use a File Transfer Protocol (FTP) program to upload
your PHP pages. If you're using a Unix-based server, don't forget to change the permission
of your PHP page to executable, as mentioned earlier, under "PHP on the Internet." If you
don't have an FTP program, ask your ISP technical staff for recommendations.
S PHP: The Complete Reference
That's how you start a PHP page—with the markup <?php. That starts a PHP section as far
as the PHP engine on the server is concerned.
When the server sends a PHP page back to the browser, the PHP engine starts by opening
that page. When it sees the markup <?php, it begins interpreting what follows as PHP. At the
end of your PHP, you use the closing markup, which is ?>:
<?php
Okay, so far we've told the PHP engine on the server that we want to insert some PHP
code into the page. Now let's do just that, by adding this line:
<?php
phpinfo()
?>
This is a call to the PHP function phpinfoQ. A function is a grouping of PHP code that is
addressable using a single name, such as phpinfo(). PHP functions are coming up in
Chapter 5; all that's necessary to know at this point is that when you use the name of the
function, the code in that function is executed. In this case, the phpinfo() function creates a
table of information about your PHP installation—what's installed, when it was built, and
so on—and displays it in the Web page sent back to the browser.
So this first PHP page is just going to display information about the PHP installation
itself. In fact, this first line of PHP code is not quite complete—you also have to end every
PHP statement with a semicolon (;), so let's add that like this:
<?php
phpinfo();
?>
Okay, that's our first PHP page. Save it as phpinfo.php, and load it into your server. As
long as your Web server can handle and run PHP pages, you can place this page anywhere
you'd place an HTML page. Then just use the URL of the page to view it, something like
http:/ /www.yourisp/youraccount/phpinfo.php.
Chapter 1: Essential PHP 9
If you're using a local Web server, such as Windows IIS, that means placing phpinfo.php
in C;\Inetpub\wwwroot, or a subdirectory of wwwroot, and then opening your browser
using gjaURL like http://localhost/phpinfo.php or http://localhost/subdirname/phpinfo
.php if you've placed phpinfo.php in a subdirectory of wwwroot.
The code that accompanies this book is stored in the folders chOl for Chapter 1, ch02 for
Chapter 2, and so on. So you'll find phpinfo.php in the chOl folder.
Some Troubleshooting
What if it doesn't work? What if you don't see the display in Figure 1-5? Unfortunately,
there are many things that could go wrong, especially with a local installation of PHP. Don't
panic—the problem can be fixed. It'll just take a little time.
First, check if your PHP code was actually run by selecting View | Source in your
browser. If you see your original PHP there, it wasn't run by the server. Make sure you did
not open phpinfo.php directly in your browser, without running it through your Web
server. Do not, for example, just double-click phpinfo.php directly or use your browser's
File | Open menu item, because that would open it in your browser directly, without letting
your PHP-enabled Web server run it. And your browser is not going to have any idea how
to rim a function like phpinfo(). So enter the actual URL for phpinfo.php in your browser,
and run it that way. ' ' ‘
Next, check if PHP is actually running. If you're running PHP locally, that's easy to
check: open a command prompt window and try the php -v command. If you see PHP
version information, PHP is running. If your PHP installation isn't local, use Telnet or SSH/
SSH2 to check the php -v command on your server. If you don't get version information,
PHP might not be running, which would account for any problems with phpinfo.php.
The next most common trouble is that PHP may not have been installed correctly as far
as your server is concerned. This is the problem if you get a blank page, and when you do a
"view source" in the Web browser, you can see the source code of your PHP script. This
means that the Web server did not pass the script to the PHP engine to be run. This can be a
little finicky, which is why the instructions from www.php.net are so extensive. The best
idea is to go through those directions again, line by line, to make sure you did everything
just as it's listed.
Next, make sure that phpinfo.php is where your Web server expects to find it. In the
Apache Web server, that's the htdocs directory in the directory where Apache has been
installed. For IIS, it's inetpub/wwwroot. In Linux, it may be /var/www/html. The actual
directory may be different on various servers; on one PHP server I use, the correct directory is
/httpdocs/ROOT, so ask your ISP's tech support. If you've uploaded phpinfo.php to the usual
directory on your ISP for your HTML pages and it's not working, ask your ISP's tech support;
sometimes, they have to enable support on a directory-by-directory basis. For that matter, some
ISPs even demand that you use a different extension for PHP 5 scripts, like .php5.
Finally, take a look at the "Problems?" section in the PHP manual for a troubleshooting
guide. The PHP Frequently Asked Questions (FAQ), at www.php.net/FAQ.php, handles
many such problems. So does PHP installation Frequently Asked Questions (FAQ) at www
.php.net/manual/faq.installation, so take a look.
<?php
phpinfo();
?>
But there's more to PHP pages than that. One of the charms of PHP is that you can
intersperse your PHP code with HTML. That's very cool, because the HTML will be
displayed by your browser, and the PHP will be run on your server—and if that PHP
generates some HTML, that HTML will be displayed in your browser as well.
Chapter 1: Essential PHP 11
For example, take a look at a new page, phphtml.php. That page starts with a standard
HTML <head> section, just as any HTML page might:
<html>
<head>
<title>
Using PHP and HTML together
</title>
</head>
And then it continues with a <body> section, which contains an <hl> header and
some text:
<html>
<head>
<title>
Using PHP and HTML together
</title>
</head>
<body>
<hl>
Using PHP and HTML together
</hl>
Here is your PHP info:
<br>
</body>
</html>
And now here're the key—you can insert PHP anywhere in this page and the PHP
engine on the Web server will run it, as long as it's contained in the <?php...?> markup.
When that PHP is run, any HTML it generates will be inserted into the page at the location
of that PHP. So, for example, if you wanted to display the PHP configuration table returned
by the phpinfoQ function, you could call that function like this in the Web page.
<html>
<head>
<title>
Using PHP and HTML together
</title>
</head>
<body>
<hl>
Using PHP and HTML together
</hl>
12 PHP: The Complete Reference
Now when this page is run by the PHP engine on the server, the HTML will be passed
through to the browser unchanged—and the PHP part will be executed. Any HTML created
by the PHP will be inserted into the page sent to the browser as well.
This page is called phphtml.php, and you can see it in Figure 1-6.
Note that the HTML in the page appears where it should—and so does the HTML
generated by the PHP.
Want to give your pages a more professional appearance? You can use the PHP logos
you can find at www.php.net/download-logos.php. These downloadable images can be
used in your Web pages to give you that PHP look. For example, here's how you might use
PbP)
System Windows NT DM8400 5.1 build 2600
Build Date Nov 2 2006 11:50:55
Configure Command cscript/nologo conflgure.js "--enable-snapshot-build" “-with-gd=shared"
Server API COI/FastCGI
Virtual Directory Support enabled
Configuration File (php.ini) C:\Prograrn FilestPHPtphp.ini
Path
PHP API 20041225
PHP Extension 20060613
< &.
10 Done
the image php med-trans-light.gif in a page named phpimage.php (put the image file in the
same directory as phpimage.php on your server):
chtml^
<head>
<title>
Using PHP and HTML together
</title> *
</head>
<body>
<hl>
Using PHP and HTML together
</hl>
Here is your PHP info:
<br>
<br>
<?php
phpinfoO; *
?>
<img src='php-med-trans-light.gif 1>
</body>
</html>
And you can see the results—the logo is at the lower right—in Figure 1-7.
<html>
<head>
<title> v
Using PHP and HTML together
</title>
</head>
<body>
<hl>
Using PHP and HTML together
</hl>
Here is your PHP info:
That's fine, but obviously, that's also static. The displayed text isn't going to change, no
matter what's going on in the code part of your page, and that's clearly unacceptable. What
if you wanted to display the results of a database lookup, or a ticket reservation?
You need to be able to insert text into the page using PHP as well, and you can do that using
the PHP echo statement. For example, to echo the text "Welcome to PHP" to the Web page sent
back to the browser, you could add this line of code to a new page, phpdisplaytext.php:
<html>
<head>
<title>
Displaying text from PHP
</title>
</head>
<body>
<hl>
Displaying text from PHP
</hl>
Here's what PHP has to say:
<br>
<br>
<?php
echo "Welcome to PHP.";
?>
</body>
</html>
You can pass text to display to the echo statement using single or double quotes:
There's a subtle difference between these two ways of passing text, which you'll see in
the next chapter. You can also directly pass numbers to echo if you want, no quotation
marks needed:
echo 1234.5678;
Passing data to functions also works like this: you place the data you want the
function to operate on between parentheses. There are many functions built into
PHP; however, echo, technically speaking, is not a function—it's a built-in PHP
language construction.
16 PHP: The Complete Reference
<html>
<head>
<title>
Displaying text from PHP
</title>
</head>
<body>
<hl>
Displaying text from PHP
</hl>
Here's what PHP has to say:
<br>
<br>
<?php
echo "<i>Welcome</ixbr>" ;
echo " <u>to</uxbr>" ;
echo "<b>PHP</b>.";
?>
</body>
</html>
You can see this page in Figure 1-9—including the HTML formatting.
So if you want to skip to the next line in your displayed output, you have to insert the
correct HTML, <br>, into your displayed text.
%php phpdisplayhtml.php
<html>
<head>
<title>
Displaying text from PHP
</title>
</head>
<body>
<hl>
Displaying text from PHP
</hl>
Here's what PHP has to say:
<br>
<br>
<i>Welcome</i><br><u>to</uxbrxb>PHP</b>. </body>
</html>
Note that the HTML wasn't interpreted as HTML here; it was simply printed out as
plain text. If you want to skip to the next line in this case, you should use the \n control
character, which PHP will interpret as a newline character—this will display all three words
on their own lines:
echo "Welcome\n";
echo "to\n";
echo "PHP.";
• \n Newline character
• \r Carriage return
• \t Tab
• \\ Displays a \
• \$ Displays a $
• \" Displays a "
• \0 to \777 Displays a character corresponding to a hexadecimal (base 8) code
• \x0 to \xFF Displays a character corresponding to a hexadecimal (base 16) code
18 PHP: The Complete Reference
You can print a sensitive character like a quotation mark (") without telling PHP that
you're ending your text (which a " mark would otherwise do). To do this, use \" instead
this way:
This is called escaping the quotation mark so that PHP will display it instead of treating it
as marking the end of a text string.
If you want to, you can break a long quoted string up across various lines in your script,
and the line breaks will be preserved—if you're printing at the command line (if you're
printing to a Web page, the line breaks will be ignored):
<?php
echo "This text
spans
multiple
lines
when
printed
at
the
command
line.";
?>
You can also separate the items you want to print with commas, like this:
All the items you want printed this way are printed, one right after another:
WelcometoPHP.
If you want to include spaces between the words, do something like this:
Welcome to PHP.
You can also assemble text strings together into one string using a dot (.). Here's
an example:
In this case, PHP takes your expression "Welcome ". "to ". "PHP." and assembles it
together (this is called concatenation) into one single string, "Welcome to PHP"; it then
passes that string on to the echo statement.
Chapter 1: Essential PHP 19
In addition, there's another way of displaying text: you can also use the PHP print
statement using the same syntax, like this: print "Welcome to PHP";. What's the difference
between print and echo? Not much; print is more like a PHP function (see Chapter 5), so it
returns a value, which is always set to 1. For most purposes, echo and print work the same
way in PHP, so the one you use is up to you.
<html>
<head>
<title>
Displaying text from PHP
</title>
</head>
<body>
<hl>
Displaying text from PHP
</hl>
Here's what PHP has to say:
<br>
<br>
<?php
echo <<<END
This example uses
"here document" syntax to display all
the text until the ending token is reached.
END;
?>
</body>
</html>
And you can see what this produces in a browser in Figure 1-10. As the figure shows,
the text in the here document was displayed in the browser.
Using the token END is by no means necessary; here's the same here document with the
token FINISH:
echo <<<FINISH
This example uses
"here document" syntax to display all
the text until the ending token is reached.
FINISH;
20 PHP: The Complete Reference
Command-Line PHP
This book concentrates on running PHP on Web servers, and seeing the results in Web
browsers, but you can also run PHP on the command line. That can be great even if you're
doing Web development—using PHP on the command line can pinpoint errors that cause
Web servers to balk, and can also save you the time involved in uploading your PHP to the
server. When you run Web-specific PHP on the command line, you'll see the HTML your
page prints out, and you can debug that page more easily.
PHP is an interpreted language; the PHP engine just reads in the text of a PHP page and
interprets it, executing that PHP immediately, line by line. The command-line version of
PHP is called the command-line interpreter, or CLI, and is just given the name php. The
online PHP engine is actually called php-cgi ("cgi" stands for Common Gateway Interface,
a standard term for online programs that interface to Web servers). In fact, when you
execute the command php -v on the command line, you can see that you're executing the
CLI, because it tells you so:
%php -v
PHP 5.2.0 (cli) (built: Nov 2 2006 11:57:36)
Copyright (c) 1997-2006 The PHP Group
Zend Engine V2.2.0, Copyright (c) 1998-2006 Zend Technologies
Chapter 1: Essential PHP 21
It's easy to execute PHP files from the command line. For example, say you had a PHP
file named echoer.php:
<?php '
The <?php...?> is still*mandatory, even though you're only using straight PHP here. You can
run this file from the command line like this:
%php echoer.php
Hello, PHP here.";
o
~o
And you see the result—the CLI printed out the message your file echoed. Any non-PHP
text outside the <?php...?> section is interpreted as HTML and simply echoed to the output.
Executing PHP like this assumes that the CLI is in your computer's path, which it
should be if you've installed PHP. If this doesn't work, you can specify the exact location of
php. That might look like something this in Unix or Linux:
$/usr/local/bin/php echoer.php
C:\>C:\php\php echoer.php
The CLI has many command-line options, which you can use to customize its operation.
In fact, php can tell you all about its options if you enter php -h to get this list:
%php -h
Usage: php [options] [ f] <file> [--] [args...]
php [options] - <code> [--] [args...]
php [options] [ B <begin_code>] -R <code> [-E <end_code>] [--] [args...]
-a Run interactively
-c <path>|<file> Look for php.ini file in this directory
-h This help
-i PHP information
-1 Syntax check only (lint)
-E <end code> Run PHP <end code> after processing all input lines
22 PHP: The Complete Reference
< • ‘
--rf <name> Show information about function <name>.
--rc <name> Show information about class <name>.
--re <name> Show information about extension <name>.
Many of these options are useful. For example, php -a lets you run the CLI in interactive
mode, where you can execute PHP just by typing it. Here's an example—the CLI's response
is in bold:
%php -a
Interactive mode enabled
<?php
echo "Hello from PHP.";
Hello from PHP.
And you can keep typing PHP and the CLI will execute it, as here:
%php -a
Interactive mode enabled
<?php
echo "Hello from PHP.";
Hello from PHP.
echo "Hello again.";
Hello again.
The php -i command gives you an enormous amount of information from phpinfo()
about the way PHP was installed on the machine:
%php -i
phpinfo()
PHP Version => 5.2.0
Want to see the source code in your PHP file displayed using syntax highlighting, where
PHP keywords are in green and data items in red? Just use php -s. For example, if you wanted
to get a syntax-highlighted version of echoer.php and store it in an HTML document ready for
viewing in your browser, echoer.html, you could execute this command:
You can also use the CLI to check the syntax of a PHP file to see if that file has any
PHP errors in it. For example, say you omitted the opening quotation mark in this
statement in echoer.php:
<?php
echo Hello, PHP here.";
?>
Here's what you'd get when you tried to run this through the CLI using the -1 option:
%php -1 echoer.php
PHP Parse error: parse error, unexpected T_STRING, expecting 1 , 1 or 1 ; 1 in echo
er.php on line 2
Errors parsing echoer.php
That's the same error you'd get from PHP online (php-cgi).
You should know that the CLI output differs from the php-cgi output; for example, the
CLI output does not include the standard HTTP headers that the php-cgi prints out when it
sends output back to the browser. And error messages are printed out in plain text by the
CLI, not the HTML that php-cgi will give you.
24 PHP: The Complete Reference
It's also worth noticing that in Linux and Unix, you can run PHP scripts simply by typing
the name of the script on the command line, if you indicate where to find PHP with a line that
begins with #!:
#! /usr/bin/php
<?php
echo "Hello from PHP.";
?>
<?php
/* Begin by displaying a
message explaining what
we are doing to the user */
That's great if you have a substantial comment that will take multiple lines to display. One
thing that drives PHP crazy is nesting comments, however, so don't do something like this:
<?php
/* Begin by displaying an
/* English */
message explaining what
we are doing to the user */
PHP looks for */ to mark the end of the comment, and if you nest comments, it'll find * /
before the real end of the comment.
Both of the other types of comments are one-line comments. These types of comments
only last for one line, not like the multiline /*...*/ type. The first type of single-line comment
starts with //:
<?php
// Display a welcoming message.
And the second type of single-line comment works the same way, except that it starts
with a # sign instead:
f r. j
<?php
// Display a welcoming message.
# Display a welcoming message.
In fact, PHP ignores everything after the // or # mark, so you cap also put single-line
comments at the end of lines, following valid PHP code like this:
<?php
// Display a welcoming message.
# Display a welcoming message.
You can even use single-line comments to make comment blocks in your PHP code,
which look something like multiline comments, like this:
<?php
// Begin by displaying a
// message explaining what
// we are doing to the user
Want something that will really stand out, comment-wise? Try something like this:
<?php
##############################
# Begin by displaying a #
# message explaining what #
# we are doing to the user #
##############################
L a | L |M| [r |r| |
.;| ■■■■■■■ r.rrJri..„,---
<?php
echo "Welcome to PHP.";
?>
\ ' ‘
That's pretty static text. You can do some addition with the PHP addition operator, +, to add
numbers together like this:
<html>
<head>
<title>Here is the answer</title>
</head>
<body>
<hl>
The Answer
</hl>
<?php
echo "Here is the answer: " , 1+5+8 , ".";
?>
</body>
</html>
The first time you run this, it displays the message "Here is the answer: 14." And the second
time you run it, it displays the message "Here is the answer: 14." again. So it's the same
thing—you've got static text here once again.
That's fine as far as it goes, but that's not very far. If you just wanted static text, you
might as well stick with HTML. That's where variables come in. As in any other
programming language, PHP variables are named memory locations that hold data. Say for
example that you wanted to keep track of the number of users of your site in three cities—
Paris, London, and Boise—but the number of users in each location isn't known until your
program rims. Variables to the rescue.
With variables, you could store the number of users in each city's variable at run time.
In PHP, variable names begin with a $ sign, followed by a name—and that name must start
with a letter or an underscore, not a number. For example, to store the number of users in
Paris, you might have a variable named $paris; the number of users in London and Boise
might be in variables $london and $boise. You could place data in those variables at run
time, and add those three data items together, also at run time. Doing the addition might
look like this:
<html>
<head>
<title>Here is the answer</title>
</head>
<body>
<hl>
The Answer
</hl>
Chapter 1: Essential PHP 27
<?php
echo "Here is the answer: " , $paris + $london + $boise , ".";
?>
</bofly> '
</html>
At run time, the value inside each variable is substituted for that variable, so if Sparis = 1,
$london = 5, and $boiee = 8, the preceding line of PHP code would look like this to PHP:
<?php
echo "Here is the answer: " , 1+5+8 ,
?>
And so you get "Plere is the answer: 14."—the same answer as before. But now say that the
three variables held 2, 4, and 6 at run time, you'd get
<?php
echo "Here is the answer: " , 2 + 4 + 6 ,
So you'd get "Here is the answer: 12."—meaning our message is no longer static.
That's why they're called variables—fhe data inside them can vary. That's the first step to
working with data in PHP: using variables to store that data. So how exactly do you store
data in variables?
$pi = 3.1415926535;
$number_of_Jupiters = 1;
$name = "Egbert Stodge";
$fish = "haddock";
Unlike some other online languages, such as Java, PHP doesn't insist that you create
different types of variables for different types of data. Here's how these variables might be
created in Java:
double pi = 3.1415926535;
int number_of_Jupiters = 1;
String name = "Egbert Stodge";
String fish = "haddock";
PHP can store all types of data in variables, and you don't have to create different variable
types to store that data, which makes things a lot easier. On the other hand, due to the
internal architecture of computers, your data is stored internally by PHP in different
formats, and it's sometimes important to know what those internal formats are more
on that later.
28 PHP: The Complete Reference
Note the use of the = sign here, which you use to assign data to variables. The = sign is
the assignment operator in PHP, letting you assign data to variables. (In fact, there are other
assignment operators, as discussed in the next chapter, but the = sign is the primary one).
For example, to set the number of cheeseburgers in your code to 1, you'd do this:
<?php
echo "Setting the number of cheeseburgers to l.<br>";
$cheeseburgers = 1;
?>
Then you could echo the current number of cheeseburgers to the browser:
<?php
echo "Setting the number of cheeseburgers to l.<br>";
$cheeseburgers = 1;
echo "Current number of cheeseburgers: ", $cheeseburgers, "<br>";
?>
Now you might change the number stored in the variable Scheeseburgers as more
cheeseburgers came online. If you got three more cheeseburgers, for example, you could use
the PHP + operator to add them to the current number stored in Scheeseburgers like this:
<?php
echo "Setting the number of cheeseburgers to l.<br>";
$cheeseburgers = 1;
echo "Current number of cheeseburgers: ", $cheeseburgers, "<br>";
echo "Adding 3 more cheeseburgers.<br>";
$cheeseburgers = $cheeseburgers + 3;
?>
Now you can display the new number of cheeseburgers in this example, phpvariables.
php, like this:
<html>
<head>
<title>
Storing data in variables
</title>
</head>
<body>
<hl>
Storing data in variables
</hl>
Chapter 1: Essential PHP 29
<?php
echo "Setting the number of cheeseburgers to l.<br>";
$cheeseburgers = 1;
/fech© "Current number of cheeseburgers: ", $cheeseburgers, "<br>";
echo "Adding 3 more cheeseburgers.<br>";
$cheeseburgers = $cheeseburgers + 3 ;
echo "Number of cheeseburgers now: ", $cheeseburgers, "<br>";
?>
</body>
</html>
You can see phpvariables.php in Figure 1-11, where, as you see, the value stored in
Scheeseburgers was successfully changed.
In some languages, like Java, you have to declare variables, giving their type and name,
before using them, such as
double pi;
int number_of_Jupiters = 1;
»
You don't have to declare variables in PHP before using them—another way that PHP
saves you time and effort. All you have to do before using a variable in PHP is to assign a
value to it—when you do, PHP will create that variable for you, and store your data in it.
0Back * Q jV] yg] » ) Search Favorites > + & ' D & <9 4
Address http://localhost/ch01/phpvariables.php
gj Go Units
yj Local intranet
Si Done .— _
That means you have to assign data to a variable before attempting to read a variable's
value, however. For example, if you tried to read the number of cheeseburgers without first
setting them.
<?php
echo "Current number of cheeseburgers: ", $cheeseburgers, "<br>";
echo "Adding 3 more cheeseburgers.<br>";
$cheeseburgers = $cheeseburgers + 3;
echo "Number of cheeseburgers now: ", $cheeselpurgers, "<br>";
?>
Want to uncreate a variable? It's hard to think of occasions that you might no longer want
a variable around, but you can indeed uncreate variables in PHP. Just use code like this:
unset($cheeseburgers);
After you execute this PHP statement, the $cheeseburgers will no longer exist, and
you'd get an error if you tried to read the value in it.
Interpolating Strings
You can,display the value in a variable like this, of course:
<?php
$cheeseburgers = 1;
echo "Current number of cheeseburgers: ", $cheeseburgers, "<br>";
?> i ■ *
In this case, you're explicitly put Scheeseburgers in the list of items whose values you
want displayed. On the other hand, there's a shortcut way of doing this in PHP that you
should be aware of, called string interpolation.
When you use interpolation, you only have to place the variable whose value you want
to insert inside a double-quoted (not single-quoted) text string. For example, you could
convert the earlier phpvariables.php example to use string interpolation in a new example
named phpinterpolation.php like this:
<html>
<head>
<title>
Using string interpolation
</title>
</head>
<body>
<hl>
Using string interpolation
</hl>
<?php
echo "Setting the number of cheeseburgers to l.<br>";
$cheeseburgers = 1;
echo "Current number of cheeseburgers: $cheeseburgers <br>";
echo "Adding 3 more cheeseburgers.<br>";
$cheeseburgers = $cheeseburgers + 3;
echo "Number of cheeseburgers now: $cheeseburgers <br>";
?>
</body>
</html>
Note how this works: PHP sees the name of a variable, Scheeseburgers, inside a double-
quoted text string:
That means that PHP will immediately place the value held in Scheeseburgers into the
string, like this:
That's how string interpolation works; PHP will substitute the value of a variable for
that variable in a double-quoted text string. You can see phpinterpolation.php at work
in Figure 1-13.
32 PHP: The Complete Reference
String interpolation is a quick shortcut, allowing you to pop the value of a variable into
a double-quoted (not single-quoted) string, but there's something to know here: you need to
surround the variable name with spaces or simple punctuation. If you put the variable
name directly next to text, you could confuse PHP. For example, if the variable $type holds
the text "basket" and you want to insert the text "basketball" into double-quoted text, you
might be tempted to use the expression Stypeball. And that's not going to work; you'll see
The solution here is to enclose the name of the variable in curly braces like this: {$type},
making the expression ${type)ball, as you see in phpadjoininginterpolation.php:
<html>
<head>
<title>
Using variable interpolation with adjoining words
</title>
</head>
<body>
<hl>
Using variable interpolation with adjoining words
</hl>
<?php
$type = "basket";
echo "The name of the game is {$type}ball.<br>";
?>
</body>
</html>
/
Chapter 1: Essential PHP 33
Here's how it works. You might have a variable named $cheeseburgers, which you
might set to a value of 1:
<?php
$cheeseburgers = 1;
Then you might create a new variable, $burgertype, that holds the name of the first
variable, "cheeseburgers":
<?php
$cheeseburgers = 1;
$burgertype = "cheeseburgers";
■p >
You know that you can display the value in $cheeseburgers this way:
<?php
$cheeseburgers = 1;
$burgertype = "cheeseburgers";
echo "Number of cheeseburgers: ", $cheeseburgers, "<br>";
>
It turns out that you can also access the value in Scheeseburgers using the variable
variable, $burgertype, like this:
<?php
$cheeseburgers = 1;
$burgertype = "cheeseburgers";
echo "Number of cheeseburgers: ", $cheeseburgers, "<br>";
echo "That number again: ", $$burgertype, "<br>";
?>
Note the syntax here—because $burgertype contains the text "cheeseburgers", the
expression $$burgertype is the same as Scheeseburgers.
Want to use variable variables with string interpolation? PHP is going to have trouble
with an expression like $$burgertype inside double quotes, so the way to fix that is to use
the expression ${$burgertype). You can see this at work in this example,
phpvariablevariables.php:
Chapter 1: Essential PHP 35
<html>
<head>
<title>
f' ’ Using variable variables
</title>
</head>
<body>
<hl> ,
Using variable variables
</hl>
<?php
$cheeseburgers = 1;
$burgertype = "cheeseburgers";
echo "Number of cheeseburgers: ", $cheeseburgers, "<br>";
echo "That number again: ", $$burgertype, "<br>";
echo "Once again: ${$burgertype} <br>";
?>
</body>
</html>
If you hadn't used the curly braces in this example, you would have gotten this output:
Number of cheeseburgers: 1
That number again: 1
Once again: $cheeseburgers
Variable variables might not look like much more than a curiosity right now, but they
have their uses when you're working with loops and arrays, covered in Chapter 3.
Creating Constants
Sometimes, you don't want a data item to be a variable. For example, the value of pi,
3.1415926535, shouldn't change. If you created a variable named $pi, something in your
code might assign a new value to $pi by mistake. The thing to do here is to create a constant,
whose value can't be modified.
You create a constant in PHP with the define function, passing define the name of the
constant you want to create and the value you want to give it, such as define ("PI",
3.1415926535). That creates a constant named PI—and that's case-sensitive: PI is not the same
as pi (if you want to make a constant non-case-sensitive, you can pass a value of TRUE like
this: define ("PI", 3.1415926535, TRUE)). Note that this just creates a constant named pi—you
don't use a $ in front of the name because doing so would make it a variable.
Here's how creating a constant works in an example phpconstant.php:
<html>
<head>
<title>
Defining constants
</title>
</head>
36 PHP: The Complete Reference
<body>
<hl>
Defining constants
</hl>
<?php
define ("PI", 3.1415926535);
echo "The value of pi is ", PI, "<br>";
?>
</body> ( • t
</html>
And you can see the results in Figure 1-15, where the constant was indeed created.
So that's the idea behind constants—if you try to alter the value of this constant, pi
(like this pi = 3.14), PHP won't accept it and won't even start the script.
Here's one thing to note: because you don't prefix constants with a $, PHP can end up
confused if you use a constant with the same name as one of the reserved keywords in PHP.
These keywords appear in Table 1-1.
Also, there are a number of predefined constants available to your scripts. We'll use
these constants as we need them; here's a sample:
For example, using echo_LINE_at a specific location in a script will display the
current line that's executing.
PHP usually handles your data's types automatically. For example, this statement
creates a variable that holds a string:
$data = 123.456;
v ■ *
$data = TRUE;
That's all fine; the problem comes when you start mixing data types. For example, if you
start with a simple variable set to "0",
<?php
$variable = "0"; // $variable is a string set to "0"
?>
then that creates a variable that contains the string "0". Now what if you add 1 to that
variable's value:
<?php
$variable = "0"; // $variable is a string set to "0"
$variable = $variable +1; // $variable is now an integer set to 1
>
In this case, PHP does the best it can; adding the number 1 to the string "0" leaves
Svariable holding the integer 1. What if you add a floating-point value?
<?php
$variable " 0 " ; // $variable is a string set to "0"
$variable $variable + 1; // $variable is now an integer set to 1
$variable $variable + 1.2; // $variable is now a float set to 2.2
9 >
Now Svariable is left holding a float value of 2.2. What if you add 3 + "8 cheeseburgers"?
PHP will again do its best, adding 3 + 8 and leaving the result, an integer value of 11, as
the result:
Chapter 1: Essential PHP 39
<?php
$variable = " 0 " ; // $variable is a string set to "0"
$variable = $variable + 1; // $variable is now an integer set to 1
$variable'' = $Variable + 1.2; // $variable is now a float set to 3.2
$variable = 3 + "8 cheeseburgers"; // $variable is an integer set to 11
?>
You should avoicUreliance on these rules. They're built into PHP, but relying on them could
give you the wrong result. If you want to convert a value from one data type to another, you
can explicitly use a data type cast. Casts are data types you put in parentheses; for example:
explicitly converts the value in $data to an integer. This converts the value in $data to a $float:
When you're converting to the boolean type, these values are considered FALSE:
»
• A boolean FALSE will yield 0 (zero), and boolean TRUE will yield 1 (one).
• Values of type float will be rounded toward zero.
When you're converting data to the float type, PHP first converts the data to an integer
and then to a float. You can also convert from string to the numeric types, but that's a little
involved—see Chapter 3 for the details.
PHP also includes special functions to let you check the internal format of data—is_int(),
is_float(), is_array(), and so on—for example, if you pass a variable that PHP has stored as
an integer internally to is_int(), that function will return a value of TRUE—more on this
comes up in the next chapter.
«
v • I
f
/
i • *___
■Msscafta—M»saw»Bioam<nmipirrnfMi.i.T.mriip |rp-frvT^nn"-»"];nrninwiinirn— aniinrniili»TiniTinTnrt.r,inniTnriiiiriiTiiiiBniiiiTrriiiirTfii<iiirnnii8iwirr'ii~i'Tirminiririiiiii~i1rnnwmiiii! ji miwiwii in
CHAPTER
Operators and Flow Control
C hapter 1 was an introduction to PHP, and this chapter gets down to nuts and bolts.
Everything you see in this chapter is an essential skill for the rest of the book.
This chapter discusses the PHP operators that you use to manipulate your data;
this is the most basic part of the PHP foundation you'll need. For example, the expression
$variable + 8 adds 8 to the value in $variable. The expression Svariable * 4 multiplies the
value on Svariable by 4. Even if you've seen operators in other languages, at least skim this
material, because there's some PHP-specific material coming up.
You're also going to see all about flow control in this chapter. Flow control lets you make
decisions in your code. Are you going to have a picnic? You can make that decision based
on the current outside temperature in PHP code. Do you have enough inventory to handle
customer orders? Again, a matter of flow control. In PHP, as in other languages, the
primary flow control statement is the if statement, which allows you to make a decision
and execute some code if that decision goes one way, and alternate code if the decision
goes another.
Besides statements like the if statement, you're also going to see loops discussed here.
Loops are fundamental to PHP, as they are to many programming languages, and they
allow you to handle large sets of data by looping over those sets of data, one data item at
a time. Computers were built for repetitive tasks like these, so loops get a prominent place
in PHP.
41
42 PHP: The Complete Reference
These operators work as you'd expect: to add two values, you use the + operator like
this: a + b. To subtract b from a, it's a - b. Okay, it's time to get some code going. Here's an
example, phpmathoperators.php, that puts the math operators to work:
<html>
<head>
<title>
Using the math operators
</title> v • »
</head>
<body>
<hl>
Using the math operators
</hl>
<?php
echo "7 + 2 = " , 7 + 2;
echo "7 - 2 = ", 7 - 2;
echo "7 ★ 2 = ", 7 * 2;
echo "7 / 2 = ", 7 / 2;
o
echo "7 "o 2 = ", 7 *o 2;
?>
</body>
</html>
You can see the results in Figure 2-1, where the math operators are doing their thing.
This example showed the use of the math operators with two numbers, 7 and 2, but of
course you can use variables as well:
Besides the built-in math operators, PHP also supports a number of math functions, and
while discussing the math operators, it's worth taking a look at the math functions too. Here
they are:
<?php
echo "tan(deg2rad(45)) = ", tan(deg2rad(45)), "<br>";
9 >
How about calculating an exponent next? You can calculate 4 to the power 3, that is, 43,
using the pow function:
<?php
echo "tan(deg2rad(45)) = ", tan(deg2rad(45)), "<br>";
echo "pow(4, 3) = ", pow(4, 3), "<br>";
?>
Chapter 2: Operators and Flow Control 45
You can round numbers down using the floor function, or up using the ceil function.
Here's an example, rounding pi downward:
*'' <?php
echo "tan(deg2rad(45)) = ", tan(deg2rad(45)), "<br>";
echo "pow(4, 3) = ", pow(4, 3), "<br>";
echo "floor(3.14159) = ", floor(3.14159), "<br>";
i ■ *
How about a little hexadecimal math? The dechex function converts from decimal
values to hexadecimal like this:
<?php
echo "tan(deg2rad(45)) = ", tan(deg2rad(45)), "<br>";
echo "pow(4, 3) = ", pow(4, 3), "<br>";
echo "floor(3.14159)’= ", floor(3.14159), "<br>";
echo "dechex(16) = ", dechex(16), "<br>";
?>
And you can find the arc tangent of 1 with the atan function, converting the radians
answer into degrees this way in phpmathfunctions.php:
<html>
<head>
<title>
Using the math functions
</title>
</head>
<body>
<hl>
Using the math functions
</hl>
<?php
echo "tan(deg2rad(45)) = ", tan(deg2rad(45)), "<br>";
echo "pow(4, 3) = ", pow(4, 3), "<br>";
echo "floor(3.14159) = ", floor(3.14159), "<br>";
echo "dechex(16) = ", dechex(16), "<br>";
echo "rad2deg(atan(1)) = ", rad2deg(atan(1)), "<br>";
?>
</body>
</html>
You can see phpmathfunctions.php in Figure 2-2, where everything works as planned.
46 PHP: The Complete Reference
$bottles_of_beer_on_the_wall = 99;
Here's something else you should know about the = assignment operator: you can make
multiple assignments on the same line, like this:
<?php
$a = $b = $c = $d = 3;
This line of code assigns the value 3 to each of the variables $a, $b, $c, and $d. Pretty handy.
Now take a look at these lines of code:
<?php
$a = 3;
$a = $a + 6;
?>
Chapter 2: Operators and Flow Control 47
The idea here is we're assigning a value of 3 to the variable $a, and then adding 6 to that
value to end up with 9 in $a. PHP gives you a set of combination assignment operators, so
that if yop want to collapse a line like $a = $a = 6, you can do it using the combination
assignment operator +=. The += operator combines the + and = operators so that this line:
$a = $a + 6;
<?php
$a = 3;
$a += 6;
?>
So the combination assignment operators give you a shortcut way of performing two
operations, where one of them is an assignment; $a = $a + 6 becomes $a += 6;.
Similarly, the -= assignment operator combines subtraction with assignment; this code
leaves 1 in $a:
<?php
$a = 3;
$a ~ = 2 ;
?>
Here are the PHP combined assignment operators. Some of the operators here might not
be familiar yet, but they're coming up in this chapter:
• +=
/=
%=
&=
A—
«=
»=
48 PHP: The Complete Reference
Here's another example, using the PHP string concatenation operator (.) like this:
<?php
$a = "No
$a .= "worries.";
?>
<?php
$a = 1;
$a = $a + 1;
?>
In fact, you could even use the shortcut assignment operator += like this:
<?php
$a = 1;
$a += 1;
r> >
But PHP has an easier operator specially for incrementing values: the ++ operator,
which you use like this:
<?php
$a = 1;
$a++;
?>
After this code executes, $a is left with a value of 2. Similarly, the — operator decrements values
Here's something that's key to understand about ++ and If you use ++ or - after a
variable, as in $a++, the value in the variable is incremented after the rest of the statement is
executed. So, for example, this line of code finds and displays the square root of 4, displaying
a value of 2, and only then increments the value in $a:
Chapter 2: Operators and Flow Control 49
<?php
$a = 4;
echo sqrt($a++);
•p >
■ m
On the other hand, this code, where the -f + comes first, increments the value in $a first.
and then displays the square root of 5:
<?php
$a = 4;
echo sqrt(++$a);
? >
That's important to keep in mind—if you put ++ or - in front of a variable, the value in
that variable is incremented or decremented before the rest of the statement is executed; if
you put the ++ or — after the variable, the value in that variable is incremented or
decremented after the rest of the statement is executed.
Here's an example PHP page, showing how incrementing works in PHP, phpincrement.
php:
<html>
<head>
<title>
Incrementing and Decrementing
</title>
</head>
<body>
<hl>
Incrementing and Decrementing
</hl>
<?php
$a = $b = $c = $d = 1;
<html>
<head>
<title>The string operators</title>
</head>
<body>
<hl>The string operators</hl>
<?php
$a = "No ";
echo "\$a = ", $a, "<br>";
echo "\$b = \$a . \"worries \"<br>";
$b = $a . "worries ";
echo "Now \$b = ", $b, "<br>";
echo "\$b .= \"at all.\"<br>";
$b .= "at all.";
echo "Now \$b = ", $b, "<br>";
?>
</body>
</html>
Chapter 2: Operators and Flow Control 51
Note These operators are designed to work on the individual bits inside their operands; if you're
looking for the boolean operators that work on TRUE/FALSE values, that's coming up later in
this chapter.
For example, the Or operator, |, works on two operands like this: $a | $b. In the result,
bits that are set (that is, equal to 1, not 0) in either $a and $b are set in the result. So, for
example, if $a equals 1 (which has the 0th bit set) and $b = 2 (which has the 1st bit set),
then $a | $b will equal 1 | 2; both the 0th bit and the 1st bit set in the result, so it equals 3.
You can see the bitwise operators in Table 2-1.
52 PHP: The Complete Reference
Xor $a A $b Bits that are set in $a or $b but not both are set.
CD
~ $0 Not ~ $0 Bits that are set in $a are not set, and vice versa.
You might also notice the shift operators, « and », here. These operators let you shift
the bits inside their operands to the left («) or right (»). You give the number you want
shifted, and the number of places you want the bits in that number shifted. For example, 8
« 1 shifts the bits of the value 8 to the left one place, which multiplies 8 by 2 to give you 16.
Or, 8 » 2 shifts the bits in the value 8 to the right two places, which is the same as dividing
by 4, so 8 » 2 = 2.
<?php
$output = 'dir c:\\Inetpub\\wwwroot\\ch02';
echo $output;
?>
Here's what you get when you execute this example, phpdir.php:
%php phpdir.php
Volume in drive C has no label.
Directory of c:\lnetpub\wwwroot\ch02
<?php
$output = 'date';
echo $output;
?>
Here's the kind of result you might see under Unix, using the bash shell:
»
Since date is also a command in DOS, here's what you might see in a DOS window:
C:\php>php phpdate.php
The current date is: Fri 04/06/2007
Enter the new date: (mm-dd-yy)
4 + 3*9
What's going to happen here? Will the 4 + 3 be added and the result be multiplied by 9
to give you 63? Or will the 3 be multiplied by 9 to give you 27 and the 4 added to that to
give you 31? It turns out that PHP processes multiplications before additions, so you'll get
31 here, as you can verify with this script, phpprecedence.php:
<?php
echo 4+3*9;
?>
%php phpprecedence.php
31
54 PHP: The Complete Reference
How can you tell the precedence of the various operators? Take a look at Table 2-2,
which lists precedence of the various operators, from high at the top of the table to low at
the bottom.
Want to set the precedence yourself? Use parentheses. You can tell PHP what operations to
execute first by enclosing them in parentheses. Here's an example, phpsettingprecedence.php:
<html>
<head>
<title>Setting operator precedence</title>
</head>
<body>
<hl>Setting operator precedence</hl>
<?php
echo "4+3*9=", 4+3*9, "<br>";
echo "(4+3) * 9 = ", (4+3) * 9, "<br>";
?>
</body>
</html>
[
! ~ ++ - (int) (float) (string) (array) (object)
* /%
+ -.
« »
&
A
&&
II
? ;
= += -= *= /= .= %= &= 1= A= «= »=
print
and
xor
or
i
Chapter 2: Operators and Flow Control 55
You can see this page in a browser in Figure 2-5. As you can see, using parentheses sets
the precedence of operator execution.
if(expression)
statement
Here, expression is a PHP expression that evaluates to a TRUE or FALSE value. Just as in other
languages you may have come across, if expression is TRUE, the statement that follows is
executed; if it is FALSE, statement is not executed. You use conditional and logical operators,
coming up next, to create expressions of the kind that can be evaluated by if statements. For
example, you can use the greater-than operator, >, to form an expression such as 4 > 1, which
is TRUE, because 4 is indeed greater than 1.
It's also worth noting that although statement can be a single line of code, it's also
possible to use a compound PHP statement, which is made up of multiple single statements
enclosed in curly braces, ( and }. Here's a single statement:
{
echo "Here";
echo " is";
echo " the";
echo " answer.";
}
V * 1
The if statement is a terrific one because it allows you to make choices on the fly, and
have alternate code executed, depending on the results of that choice. For example, you
could check the value of a password to make sure it's correct, or check the user's response
to yes/no queries ("Do you want fries with that?").
For example, you might want to display some text if the outside temperature is above
65 degrees, which you could do like this:
<?php
$temperature = 66;
if ($temperature > 65)
echo "It's nice outside.";
?>
Although this way of doing things, with a single statement following the if statement,
works, it's more usual to put in the curly braces associated with compound statements like this:
<?php
$temperature = 66;
if ($temperature > 65) {
echo "It's nice outside.";
}
Because this is the way you'll usually see things done—even with single statements—
this is the way you'll see the if statement in this book—with the curly braces. You can, of
course, use compound statements here as well:
<?php
$temperature = 66;
if ($temperature >65) {
echo "It's ";
echo "nice ";
echo "outside.";
}
Here's an example, phpif.php, that checks how many minutes someone has been in the
pool—if it's more than 30 minutes, it's time to get out:
<html>
<head>
<title>Using the if statement</title>
</head>
Chapter 2: Operators and Flow Control 57
<body>
<hl>Using the if statement</hl>
<?php
*r‘ ' $minutes = 31;
if($minutes >30) {
?>
</body>
</html>
<html>
<head>
<title>Using the if statement</title>
</head> ,
<body>
<hl>Using the if statement</hl>
<?php
$minutes = 31;
if($minutes >30) {
echo "Your time is up!<br>";
echo "Please get out of the pool.";
}
?>
</body>
</html>
<html>
<head>
<title>Using the is_float function</title> v ‘ 1
</head>
<body>
<hl>Using the is_float function</hl>
<?php
$variable = 10.7;
if (is_float($variable)) {
$variable = $variable + 4.5;
var_dump($variable);
}
?>
</body>
</html>
You can see phpisfloat.php at work in Figure 2-7. As you see there, the vardump
function gives you the response float(15.2) here, indicating the variable's value and
internal type.
There's more to the if statement, and that's coming up. For example, the greater-than
operator (>) is just one of a set of PHP comparison operators, and they're coming up next.
<?php
$temperature = 66;
if ($temperature > 65) {
echo "It’s n-i€e outside . " ;
}
<?php
$temperature = 66;
if ($temperature <= 65) {
echo "Pretty chilly outside.";
}
?>
You can see all the PHP comparison operators in Table 2-3.
For example, you can see how to use the == equality operator in phpequality.php,
which checks if someone has been in the pool for exactly 30 minutes:
<html>
<head>
<title>Using the == operator</title>
</head>
———
Identical $a === $b TRUE if $a is equal to $b, and they are of the
same type
!= Not equal $a != $b TRUE if $a is not equal to $b
<> Not equal $a <> $b TRUE if $a is not equal to $b
Not identical $a !== $b TRUE if $a is not equal to $b, or they are not
!==
of the same type
<body>
<hl>Usin§1 the == operator</hl>
<?php
$minutes = 30;
if($minutes == 30) {
echo "Warning:<br>";
echo "Your time in the pool is almost up.";
}
?>
. • i
</body>
</html>
You can see phpequality.php in Figure 2-8; make sure you don't confuse the equality
operator, ==, and the assignment operator, =.
Similarly, this example uses the not-equal operator, !=, to test if the temperature is not
equal to 67 degrees:
<?php
$temperature = 30;
if($temperature != 67 {
echo "The temperature is not 67 degrees.";
}
?>
Besides using comparison operators, there is also a set of logical operators you can use
with decision-making statements like the if statement.
But what if you wanted to check if the temperature is greater than 65 degrees and less
than 75 degrees? In that case, you can use the and logical operator, &&, to connect two
conditional clauses as shown in phplogical.php:
<html>
<head>
<title>Using the logical operators</title>
>
</head>
<body>
<hl>Using the logical operators</hl>
<?php
$temperature = 66;
if ($temperature > 65 && $temperature < 75) {
echo "It's between 65 and 75 outside.";
}
?>
</body>
</html>
<html>
<head>
<title>Using the logical operators</title>
</head>
<body>
<hl>Using the logical operators</hl>
<?php
62 PHP: The Complete Reference
$teraperature = 66;
if ($temperature <32 || $temperature >100) {
echo "Better stay inside today.";
}
?>
</body>
</html>
You can find all the PHP logical operators in Table 2-4.
You might wonder why there are two and logical operators ("and" and &&) and two or
logical operators ("or" and | |). The answer is that the && and | | operators have high
precedence, and there are times when you might want low precedence logical operators so
that you don't have to specifically use parentheses in your expressions to get things right.
if expression
statementl <'4
else
expression2
Here, if the expression is true, statementl will be executed. If expression is false, on the
other hand, expression2 will be executed.
Here's an example, phpelse.php. Say you want to print out one message if the outside
temperature was outside the range 32 degrees to 100 degrees, and another message if the
temperature is inside that range. You can start by determining if the temperature is outside
that range and displaying a message if so:
<html>
<head>
<title>Using the else statement</title>
</head>
<body>
<hl>Using the else statement</hl>
<?php
$temperature = 66;
if ($temperature <32 || $temperature > 100) {
echo "Better stay inside today.";
}
?>
</body>
</html>
Otherwise, if the temperature is inside the range 32 to 100, you can display an alternate
message, "Nice day outside.":
<html>
<head>
<title>Using the else statement</title>
</head>
<body>
<hl>Using the else statement</hl>
<?php
$temperature = 66;
if ($temperature <32 || $temperature > 100) {
echo "Better stay inside today.";
}
64 PHP: The Complete Reference
else {
echo^'Nice day outside.";
}
?>
</body>
</html>
<html> \
<head>
<title>Using the else statement</title>
</head>
<body>
<hl>Using the else stateraent</hl>
<?php
$gallons = 6;
if ($gallons < 5) {
echo "Got a parachute?";
}
else {
echo "You'll be OK.";
}
?>
</body>
</html>
You'll be OK.
if expressionl
statementl *'*
elseif expression2
expression2
elseif expressions
expressions
elseif expression4
expression4
elseif expressions
expressions
else
expressions
<html>
<head>
<title>Using the elseif statement</title>
</head>
<body>
<hl>Using the elseif statement</hl>
<?php
$temperature = 66;
if ($temperature < 32) {
echo "Too cold.";
}
elseif ($temperature < 60) {
echo "Pretty chilly.";
}
elseif ($temperature < 70) {
echo "Pretty nice outside.";
}
elseif ($temperature < 80) {
echo "Pretty warm outside.";
}
else {
echo "Too hot.";
}
?>
</body>
</html>
66 PHP: The Complete Reference
You can see how this works. If the if statement's conditional expression is false, PHP
checks the first elseif statement's conditional expression, and if that's true, the elseif
statement's code is executed. If the first elseif statement's conditional expression is false,
PHP moves on to the next elseif statement and so on. At the end of the whole chain is an
else statement, whose code is executed if no other code has been executed in the if statement
up to this point. The whole thing appears in Figure 2-11.
And with the addition of the elseif clauses, you've now mastered the if statement—you
know all there is to know about it.
Okay, what's going on here? If condition is true, the ternary operator—which is made
up of the characters ?:—returns expressionl. Otherwise, it returns expression2. So as you
can see, this is an operator that lets you make real-time choices.
Here's an example. This code displays "Nice day outside." if the outside temperature is
between 32 and 100 degrees, and "Better stay inside today." otherwise:
<?php
$temperature = 66;
if ($temperature < 32 || $temperature > 100) {
echo "Better stay inside today.";
}
else {
echo " Nice day outside.";
}
?>
Chapter 2: Operators and Flow Control 67
Here's the same code using the ternary operator—note how compact this is:
<?php
$temperature = 66; •
echo ($temperature < 32 || $temperature > 100) ? "Better stay inside
today." : "Nice day outside.";
?>
i • *
Here s another example that finds the absolute value of numbers—all it does is to use
the negation operator, to change the sign of a value if that value if negative:
<?php
$value = -3;
$abs_value = $value < 0 ? -$value : $value;
echo $abs_value;
?>
<?php
$value = 15;
$hex = $value < 10 ? "Ox" . $value : "Ox" . chr($value - 10 + 65);
echo "In hex, $value = $hex";
?>
This script will give you: In hex, 15 = OxF (you preface hex values with Ox in PHP to tell
PHP that it's a hex value). Pretty cool—the conversion is done in a single statement (of course,
the PHP dechex function can do even better, converting multidigit values).
switch (testvalue) {
case expressionl:
statementl
[break;]
case expression2:
statement2
[break;]
case expression3:
statements
[break;]
case expression4:
statement4
68 PHP: The Complete Reference
[break;]
[default:
default_statement]
}
Here's how this works: You pass a value (integer or floating-point numbers or strings) to
the switch statement, and the switch statement checks it against all the cases you've listed; if
the value you're checking matches the value in a case statement, that case statement's code is
executed. If no case matches the value you're checking, the code in the default statement, if
there is a default statement, is executed. The break statement ends execution of the switch
statement—if you omit the break statement, execution will continue with the code in the
following case statement automatically.
And here's an example, phpswitch.php, which displays different messages, depending
on the current outside temperature:
<html>
<head>
<title>
Using the switch statement
</title>
</head>
<body>
<hl>
Using the switch statement
</hl>
<?php
$temperature = 70;
switch ($temperature) {
case 70:
case 71:
case 72:
echo "Nice day outside.";
break;
case 73:
case 74 :
case 75:
echo "OK, but a little warm.";
break;
case 76:
case 77:
case 78:
echo "A little warmer.";
break;
default:
echo "Temperature outside the range this statement can handle "•
}
?>
</body>
</html>
The for loop executes expressionl before it starts; then it checks the value of expression2—if
it's true, the loop executes statement once. Then the loop executes expression (which often
increments the value in a loop counter variable) and after that checks the value of expression2
again (which might check the value in the loop counter variable). If expression2 is still true,
the loop executes statement once again. Then the loop executes expression again, and the
process keeps going until expression2 evaluates to false, when the loop ends. Note that
expression2 is checked before the loop executes, and expression is executed after every time
the loop loops.
Here's an example, phpfor.php, which displays a message six times. You can start by
initializing a loop counter variable to 0:
<?php
for ($loop_counter = 0;...){
}
?>
70 PHP: The Complete Reference
Each time through the loop, you can check if the loop counter is greater than 6, in which
case you should quit:
<?php
for ($loop_counter = 0; $loop_counter < 6;...){
?>
And after each time the loop is executed, you can increment the loop counter:
<?php
for ($loop_counter = 0; $loop_counter < 6; $loop_counter++){
}
?>
That sets up the loop, which will execute six times. All that's left is the body of the
loop—the statement (which can be a compound statement) that you want to execute each
time the loop loops. In this case, the example will just display another line of text, as you
see in phpfor.php:
<htral>
<head>
<title>
Using the for loop
</title>
</head>
<body>
<hl>
Using the for loop
</hl>
<?php
for ($loop_counter = 0; $loop_counter < 6; $loop_counter++){
echo "You're going to see this message six times.<br>";
}
?>
</body>
</html>
You can see the results in Figure 2-13, where as you can see, the message appears six
times, once for each iteration of the for loop. Very nice.
Chapter 2: Operators and Flow Control 71
There's more about for loops as well; for loops can handle multiple loop counters if you
want, as long as you separate them with the comma operator. Here's an example that uses
two loop counters:
<?php
for ($loopl = 2, $loop2 = 2; $loopl < 6 && $loop2 < 6; $loopl++, $loop2++){
echo "$loopl x $loop2 = ", $loopl * $loop2, "<br>";
}
?>
2x2 = 4
3x3 = 9
4 x 4 = 16
5 x 5 = 25
In fact, you don't have to use loop counters at all in a for loop. Here's an example that
starts by initializing a connection to a database, gets a new record each time through the
loop, and processes the new record until the end of the data is reached, at which point the
process_record function returns -1:
You can also nest for loops, one inside another, as you'll see when we work with arrays.
Here's a quick example:
<?php
for ($loop_counterl = 0; $loop_counterl < 6; $loop_counterl++){
for ($loop_counter2 = 0; $loop_counter2 < 2; $loop_counter2++){
72 PHP: The Complete Reference
}
}
?>
while (expression)
statement
While expression is true, the loop executes statement. That's all there is to it. When expression
is false, the loop ends (which means, please note, that it's possible that statement will never get
executed). In other words, the while loop keeps executing while its test expression is true.
Here's an example, phpwhile.php, which keeps incrementing a variable until its value is
greater than or equal to 10, at which point it quits:
<html>
<head>
<title>
Using the while loop
</title>
</head>
<body>
<hl>
Using the while loop
</hl>
<?php
$variable = 1;
And you can see the results in Figure 2-14—the while loop kept looping while $variable
held less than 10—and when that was no longer true, it quit.
You can even convert a while loop into a for loop if you use an explicit loop counter, as
in this example:
<?php
$loop_counter = 0;
while ($loop_counter < 6){
/
Chapter 2: Operators and Flow Contro 73
Then you increment and use the loop counter in the body of the loop:
<?php
$loop_counter = 0;
while ($loop_counter < 6) {
echo "You're going to see this message six times. <br>";
$loop_counter++;
}
?>
You often use the while loop when you have a looping situation where you don't actually
need a loop counter. For example, while loops are often used to read data from files; you
might open a file, and then use a while loop to check if you're at the end of the file:
<?php
openfile();
while (notat endoffile0){
}
?>
If you're not at the end of the file, you can read data from the file and echo it:
<?php
open_file();
while (not at_end_of_file()){
74 PHP: The Complete Reference
$data = read_data_fromfile();
echo $data;
}
?>
do
statement
while (expression)
In this case, the do...while loop keeps executing statement while expression is true—and note
in particular that because expression is tested at the end of the loop, expression could actually
be false, and the loop's body would still be executed at least once. That's useful when you
have a situation in which the test condition is set inside the body of the loop and so can't be
tested until the end of the loop.
Here's an example, phpdowhile.php, that converts the previous while example into do...
while form:
<htral>
<head>
<title>
Using the do...while loop
</title>
</head>
<body>
<hl>
Using the do. . .while loop
</hl>
<?php
$variable = 1;
do {
echo "Now \$variable holds: ", $variable, "<br>";
$variable++;
}
while ($variable < 10)
?>
</body>
</html>
You can see the results in Figure 2-15, where the do...while loop has done its thing.
Chapter 2: Operators and Flow Control 75
Here's another example that points out the difference between the while loop and the
do...while loop, phpdoornot.php. Here, even though its condition evaluates to false, you'll
see that the do...while loop executes its body once—but the while loop does not:
<html>
<head>
<title>
Using the do...while loop
</title>
</head>
<body>
<hl>
Using the do...while loop
</hl>
<?php
$variable = 20;
do {
echo "The do...while loop says \$variable = ", $variable, "<br>";
}
while ($variable < 10);
}
?>
</body>
</html>
76 PHP: The Complete Reference
Figure 2-16 The do...while loop vs. the while loop in PHP
You can see the results in Figure 2-16—the do...while loop executed once, but the while
loop didn't.
And here's an example, phpforeach.php, putting the foreach loop to work. This example
loops over all the items in an array—types of sandwiches (see the next chapter for more on
arrays)—and displays each item:
<html>
<head>
<title>
Using the foreach loop
</title>
</head>
Chapter 2: Operators and Flow Control 77
<body>
<hl>Using the foreach loop</hl>
<?php
$arr = array("turkey", "ham", "beef");
foreach ($arr as $value) {
echo "Current sandwich: $value<br>";
}
?>
</body>
</html>
You can see the results in Figure 2-17, where the foreach loop has looped over the
array. Nice.
switch ($temperature) {
case 70:
case 71:
case 72:
echo "Nice day outside.";
break;
78 PHP: The Complete Reference
But you can also use break in loops. Here's an example, phpbreak.php, that stops a loop
when the loop counter reaches a value of 5:
<html>
<head>
<title>
Using the break statement
</title>
</head>
<body>
<hl>Using the break statement</hl>
<?php
for ($loop_counter = 0; $loop_counter < 1000; $loop_counter++){
echo "I’m going to do this a thousand times unless you stop me!<BR>";
if ($loop counter == 5) {
echo "Alright, I'm quitting.<BR>";
break;
}
}
?>
</body>
</html>
Skipping Iterations
Sometimes, you might want to skip an iteration of a loop to avoid some kind of problem,
such as a division by zero—and you can do that with the continue statement, which makes
the loop move on to the next iteration.
Chapter 2: Operators and Flow Control 79
Here s an example, phpcontinue.php, which finds the reciprocals (that is, 1 divided by
the number) of various integers—note that it checks to see if it's being asked to divide by
zero, and if so, it skips to the next iteration:
<html>
<head>
<title>
Using the continue statement
</title>
</head>
<body>
<hl>Using the continue statement</hl>
<?php
$number =1;
for ($number = -2; $number < 3; $number++){
if($number == 0){
continue;
}
echo "1/$number = ", 1 / $number, "<br>";
$number++;
}
?>
</body>
</html>
And you can see the results in Figure 2-19, where, as you can see, the script skipped the
step where it was supposed to divide by zero. Cool.
PH P Alternate Syntax
PHP also supports an alternative syntax for if, while, for, foreach, and switch. In each case,
the form of the alternate syntax changes the opening curly brace to a colon (:) and the
closing brace to endif;, endwhile;, endfor;, endforeach;, or endswitch;, respectively.
Here's an example showing an if statement using alternate syntax:
<?php
$temperature =61; \ *
if ($temperature == 60) :
echo "The temperature is 60";
elseif ({temperature == 70):
echo "The temperature is 70";
else:
echo "The temperature is not 60 or 70";
endif;
?>
<?php
for ($loop_counter = 0; $loop_counter < 6; $loop_counter++)
echo "You're going to see this message six times.<BR>";
endfor;
<?php
$temperature = 65;
switch ({temperature) :
case 60:
echo "The temperature is 60.";
break;
case 70:
echo "The temperature is 70.";
break;
case 80:
echo "The temperature is 80.";
break;
default:
echo "The temperature is not 60, 70, or 80.";
endswitch;
Okay, you've gotten a good grounding in working with PHP operators and control
structures like if statements and for loops. Coming up next: handling arrays and strings.
I • * __________
CHAPTER
Strings and Arrays
T his chapter represents the next step up in handling your data in PHP: text strings and
arrays. You've seen strings already to some extent, but there's a lot more to the story.
Data on the Internet is usually in text format, and PHP excels in handling strings—
there's a huge library of prebuilt string functions in PHP. From sorting strings to searching
them, from trimming extra spaces to getting the length of a string, we'll master the PHP
string functions in this chapter.
In addition to strings, you're also going to see how to work with arrays in PHP in this
chapter. Arrays represent our first contact with collections in PHP—the storing of more than
one data item under a single name. Arrays are an important part of PHP because, among
other things, you use array notation to read data sent you from the user.
You've already seen simple variables, which hold simple data items like strings or
numbers. Arrays store whole sets of data items in the same way, and you can access those
individual data items with, for example, a numeric array index. That's great from a
programming point of view, because you can use a loop to steadily increment that array
index, letting you loop over, and handle, all the items in an array.
Say you have 12,000 numeric data items and want to find their average value. It would
be a serious chore to write code to handle all those data items individually. But you can
stash them all in a single array, and then loop over that array, handling the data items one
by one, with a simple loop in a couple of lines. No problem.
Okay, we're ready to start. Let's begin by taking a look at the PHP built-in string functions.
81
82 PHP: The Complete Reference
html entity decode Converts all HTML entities to their applicable characters
htmlentities Converts all applicable characters to HTML entities
htmlspecialchars Converts special characters to HTML entities
implode Joins array elements with a string
join Alias of the implode function
levenshtein Calculates the Levenshtein distance between two strings
localeconv Gets the numeric formatting information
Itrim Strips whitespace from the beginning of a string
md5 file Calculates the md5 hash of a given filename
md5 Calculates the md5 hash of a string
metaphone Calculates the metaphone key of a string
money format Formats a number as a currency string
nljanginfo Queries language and locale information
nl2br Inserts HTML line breaks before all newlines in a string
number format Formats a number with grouped thousand separators
ord Returns the ASCII value of a character
strcspn Finds the length of the initial segment not matching a mask
strip tags Strips HTML and PHP tags from a string
stripcslashes Un-quotes string quoted with addcsIashesQ
As you can see, there are plenty of string functions. Let's put some of them to work in
an example called phpstrings.php. You might start with the string "No problem":
You can use the strlen function to find the string's length:
The chr function converts ASCII numeric codes into their corresponding characters—
here's ABC in ASCII:
You can uppercase the first letter of the string with ucfirst:
echo "Uppercasing the first letter gives you: ", ucfirst("no problem"),
"<br>";
You can trim excess spaces with the trim function (the codes you see here are to
create nonbreaking spaces in the browser so that the browser doesn't collapse the four
spaces here into one space):
echo " ’  ,-No problem' trimmed is: '", trim(
" No problem"), "'<br>";
And you can count the number of occurrences of a substring with the substr_count
function like this in phpstrings.php:
<html>
<head>
<title>
Using string functions
</title>
</head>
86 PHP: The Complete Reference
<body>
<hl>
Using string functions
</hl>
<?php
echo "The test string is 'No problem1.<br>";
echo "'No problem' is ", strlenC'No problem"), " characters long<br>";
echo "The substring substr('No problem', 3, 7) is '", substr("No problem",
3, 7), "1<br>";
echo "The word 'problem' is at position ", strposC'N© prbblem",
problem") ,
"<br>";
echo "Replacing 'problem' with 'problems' gives: ", substr_replace(
"No problem", "problems", 3, 9), "<br>";
echo "Using ASCII codes: ", chr(65), chr(66), chr(67), "<br>";
echo "Uppercasing the first letter gives you: ", ucfirstC'no problem"),
"<br>";
echo "In upper case: ", strtoupper("No problem"), "<br>";
echo "In lower case: ", strtolower("No problem"), "<br>";
echo "' No problem' trimmed is: '", trim(
" No problem"), "'<br>";
echo "Reversed: ", strrev("No problem"), "<br>";
echo "There are ", substrcount("No problem", "o"), " o's in 'No problem'.";
?>
</body>
</html>
How will all this look in a browser? Take a look at Figure 3-1, where you can see the results.
As you can see, there's plenty of string-handling power that comes with PHP.
<?php
$float = 3.1415;
echo (string) $float, "<br>";
echo strval($float), "<br>";
?>
How do the (string) cast and the strval function work when converting other values?
A boolean TRUE value is converted to the string "1"; the FALSE value is represented as ""
(empty string). An integer or a floating-point number (float) is converted to a string
representing the number with its digits (including the exponent part for floating-point
numbers). The value NULL is always converted to an empty string.
You can also go the other way, and convert a string into a number. The string will be
treated as a float if it contains any of the characters 7, e', or 'E'. Otherwise, it will be
treated as an integer. The numeric value of a string is given by the initial part of the string.
If the string starts with numeric data, that will be the value used. Otherwise, the value
will be 0 (zero). Valid numeric data consists of an optional sign (+ or -), followed by one
or more digits (including, if you use it, a decimal point), followed by an optional exponent
(the exponent part is an 'e' or 'E' followed by one or more digits).
For example, you can add a number and a quoted number (that is, a number in a string)
and PHP will do the right thing:
$value = 1 + "19.2";
echo "$value <br>";
$value = 1 + "2.5e4";
echo "$value <br>";
You can also explicitly convert text to floats with the (float) cast, for example:
$text = "3.0";
$value = (float) $text;
echo $value / 2.0, "<br>";
<html>
<head>
<title>
Converting from strings and numbers
</title>
</head>
88 PHP: The Complete Reference
<body>
<hl>
Converting from strings and numbers
</hl>
<?php
$float = 3.1415;
echo (string) $float, "<br>";
echo strval($float), "<br>";
$value = 1 + "19.2";
echo "$value <br>";
$value = 1 + "2.5e4";
echo "$value <br>";
$text = "3.0";
$value = (float) $text;
echo $value / 2.0, "<br>";
?>
</body>
</html>
places after the decimal point? It turns out that there are two PHP functions that specifically
handle formatting of text strings, and here they are—printf and sprintf:
The printf function prints a string (much like echo), and the sprintf function also "prints" its
data, but in this case, the output is a string-—that is, it returns a string.
The format string is a little complex here. It's made up of zero or more directives, which
are characters copied to the result, and conversion specifiers, which are made up of a percent
sign (%) followed by one or more of these items (in this order):
• An optional padding specifier that indicates which character should be used to pad
the results to the correct string size. This may be a space character or a 0 (zero character).
The default is to pad with spaces.
• An optional number, the width specifier, specifying how many characters (minimum)
this conversion should result in.
• An optional precision specifier that indicates how many decimal digits should be
displayed for floating-point numbers. (There is no effect for other types than float.)
• A type specifier that says what type the argument data should be treated as.
• c The argument is treated as an integer and presented as the character with that
ASCII value.
• d The argument is treated as an integer and presented as a (signed) decimal
number.
• u The argument is treated as an integer and presented as an unsigned decimal
number.
• f The argument is treated as a float and presented as a floating-point number.
Getting formats to work can be tricky. Here's an example, phpformat.php. You might
start with the %s format, which just inserts a string, with printf:
This will display "I have 4 pants and 12 shirts.". That's the way it works—you put the format
into a string template, and then the data to be formatted follows.
Here's how to use sprintf, which returns a string:
Here's a more involved use of formatting, using the format %01.2f, which results in two
places after the decimal point:
$price = 2789.992;
echo "The price is
printf (" \ $%01.2f <brxbr>", $price) ;
This will display "The price is 2789.99". Here are some more uses of format strings for
formatting floating-point numbers:
$year = 2007;
$month = 9;
$day = 2;
echo "The date is ";
printf("%04d-%02d-%02d<br>", $year, $month, $day);
<html>
<head>
<title>
Using string formatting
</title>
</head>
<body>
<hl>
Using string formatting
</hl>
<?php
printf ("I have %s pants and %s shirts. <brxbr>", 4, 12);
$price = 2789.992;
echo "The price is
printf ("\$%01.2f<brxbr>", $price) ;
$year = 2007;
$month = 9;
$day = 2;
echo "The date is ";
printf("%04d-%02d-%02d<br>", $year, $month, $day);
?>
</body>
</html>
TlP Incidentally, there's another function for formatting numbers in PHP: number_format().
This statement creates a new array named $actors, and stores "Cary Grant" in the first
element, element 0. As in other programming languages, arrays start with element 0 in PHP.
Now when you echo $actors like this:
echo $actors[0];
<html>
<head>
<title>
Creating an array
</title>
</head>
<body>
<hl>
Creating an array
</hl>
<?php
$actors[0] = "Cary Grant";
$actors[1] = "Myrna Loy";
$actors [2] = "Lome Green";
Now $actors[0] holds "Cary Grant", $actors[l] holds "Myrna Loy", and $actors[2] holds
"Lome Green", as you can see in Figure 3-4.
So far, these array examples have all used numeric indexes, which is useful when you
want to loop over an array—coming up soon—because you can use the loop counter as the
array index. However, PHP also lets you use a string array index, and that can be useful too,
Chapter 3: Strings and Arrays 93
because you might forget that the amount cousin Jill owes you is stored in $debts[342]/ but
you won't forget $debts["Jill"]:
$debts["Jill"] = 2493.77;
Now $debts["Jill"] holds 2493.77. And you can store other debts in that array as well:
$debts["Jill"] = 2493.77;
$debts["Bob"] = 4930.33;
$debts["Sam"] = 5493.22;
In fact, even though you are using string indexes for these array elements, it turns out that
you can loop over this array using PHP—more on that later.
There's a shortcut for creating arrays—you can simply use the array name followed by
empty square brackets like this, and PHP will fill in the numbers:
After you execute this code, $actors[0] will hold "Cary Grant", $actors[l] will hold "Myrna
Loy", and $actors[2] will hold "Lome Green".
In fact, there's even a shorter shortcut in PHP for creating an array: you can use the
array function, which returns an array. That looks like this:
This also creates an array such that $actors[0] will hold "Cary Grant”, $actors[l] will hold
"Myrna Loy", and $actors[2] will hold "Lome Green .
94 PHP: The Complete Reference
By default, arrays start with index 0. What if you wanted to start with index 1 instead?
You could use the PHP => operator like this:
The => operator lets you create key/value pairs in arrays—the item on the left of the =>
is the key, and the item on the right is the value. For example, you could do this in
phparray function.php:
<html>
<head>
<title>
Using the array function
</title>
</head>
<body>
<hl>
Using the array function
</hl>
<?php
$debts = array("Jill" => 2493.77, "Bob" => 4930.33, "Sam" => 5493.22);
$debts["Jill"] = 2493.77;
$debts["Bob"] = 4930.33;
$debts["Sam"] = 5493.22;
As you can see, the => operator is a useful one. For example, you can put it to work in
case you don't want to fill consecutive values, like this:
$actors = array(1 => "Cary Grant", 5 => "Myrna Loy", 7 => "Lome Green");
Here's one more shortcut: if you have a specific range of data, such as the numbers 1 to 10
or the characters a to z, you can use the PHP range function to create arrays. Here's an example:
$data = ranged, 4) ;
$data[0] = 1
$data[l] = 2
$data[2] = 3
$data[3] = 4
<?php
$actors[0] = "Cary Grant";
$actors[1] = "Myrna Loy";
$actors [2] = "Lome Green";
?>
Now say that you wanted to change $actors[2] from "Lome Green" to "Jimmy Stewart”.
No trouble, just do this:
<?php
$actors [0] = "Cary Grant";
96 PHP: The Complete Reference
Now say you wanted to add a new actor, "Julie Andrews" to this list. No problem, you
could just do this in phpmodify.php:
V ' ‘
<html>
<head>
<title> \
Modifying arrays
</title>
</head>
<body>
<hl>
Modifying arrays
</hl>
<?php
$actors[0] = "Cary Grant";
$actors[1] = "Myrna Loy" ;
$actors[2] = "Lome Green";
You can see the results in Figure 3-6, where you've been able to successfully modify the
values in the array.
You can copy entire arrays with a single assignment statement—for example, you might
copy the array Sactors over to a new array named $creative_staff like this—note that you
refer to the array with its name alone, no square brackets needed:
<?php
$actors [0] = "Cary Grant";
$actors [1] = "Myrna Loy";
$actors [2] = "Lome Green" ;
$creative_staff = $actors;
echo $creative_staff[1] ;
?>
At the end of this script, then, the statement echo $creative_staff[l]; will display "Myma
Loy". Not bad.
<?php
$actors [0] = "Cary Grant";
$actors[1] = "Myrna Loy";
$actors [2] = "Lome Green";
II II .
$actors[1] =
?>
98 PHP: The Complete Reference
But that doesn't delete the element—it just sets it to an empty string, so if you display
the array elements:
<?php
$actors[0] = "Cary Grant";
$actors[1] = "Myrna Loy";
$actors[2] = "Lome Green";
$actors[1] = "";
So how do you actually remove an element from an array? You use the unset function
like this in phpunset.php:
<html>
<head>
<title>
Deleting an array element
</title>
</head>
<body>
<hl>
Deleting an array element
</hl>
<?php
$actors[0] = "Cary Grant";
$actors[1] = "Myrna Loy";
$actors[2] = "Lome Green";
unset($actors[1]);
<html>
<head>
<title>
Using a for loop to loop over an array
</title>
</head>
<body>
<hl>
Using a for loop to loop over an array
</hl>
<?php
$actors[0] = "Cary Grant";
$actors[1] = "Myrna Loy";
$actors [2] = "Lome Green";
100 PHP: The Complete Reference
You can see the results in Figure 3-8. As you see, the for loop looped over all the
elements in the array. Beautiful.
For example, if you wanted to print out the $actors array, you could use print_r like this:
<?php
$actors[0] = "Cary Grant";
$actors[l] = "Myrna Loy";
$actors[2] = "Lome Green";
print_r($actors);
?>
This function uses newlines to print, not HTML <br> elements, so run this at the command
line to give
%php phpprint_r.php
Array
(
[0] => Cary Grant
[1] => Myrna Loy
[2] => Lome Green
)
Note that this gives you the result in key => value form. Try this one:
<?php
$debts["Jill"] = 2493.77;
$debts["Bob"] = 4930.33;
$debts["Sam"] = 5493.22;
print_r ($del»ts) ;
?>
Running this new version shows how print_r gives you key /value pairs:
%php phpprint_r.php
Array
(
[Jill] => 2493.77
[Bob] => 4930.33
[Sam] => 5493.22
You can also pass a value of true to the print_r function to make it return its text as a
string, which you can assign to a variable:
This next example, phpforeachl.php, puts the foreach loop to work, looping over the
Sactors array like this:
<html>
<head>
<title>
Using a foreach loop to loop over an array
</title>
</head.>
<body>
<hl>
Using a foreach loop to loop over an array
</hl>
<?php
$actors[0] = "Cary Grant";
$actors[1] = "Myrna Loy";
$actors [2] = "Lome Green";
102 PHP: The Complete Reference
The foreach loop here fills the variable $value with a new element from the $actors array
each time through. You can see the results in Figure 3-9.
You can use the second form of the foreach loop—the version that lets you work with
keys as well as values—in an example named phpforeach2.php. That looks like this:
<html>
<head>
<title>
Using a foreach loop with keys and values in an array
</title>
</head>
<body>
<hl>
Using a foreach loop with keys and values in an array
</hl>
<?php
$debts["Jill"] = 2493.77;
$debts["Bob"] = 4930.33;
$debts["Sam"] = 5493.22;
Figure 3-10 Using the foreach loop with keys and values on an array in PHP
<html>
<head>
<title>
Using a while loop with keys and values in an array
</title>
</head>
<body>
<hl>
Using a while loop with keys and values in an array
</hl>
<?php
$debts["Jill"] = 2493.77;
$debts["Bob"] = 4930.33;
$debts["Sam"] = 5493.22;
Figure 3-11 Using the while loop with keys and values on an array in PHP
array_combine Creates an array by using one array for the keys and another for
the values
array diff assoc Computes the difference of two arrays with additional index check
array_diff_uassoc Computes the difference of two arrays with additional index check,
performed by a user-supplied callback function
array diff Computes the difference of arrays
array fill Fills an array with values
array filter Filters elements of an array using a callback function
array flip Exchanges all keys with their associated values in an array
array intersect assoc Computes the intersection of arrays with additional index check
arrayjntersect Computes the intersection of arrays
---■
..■.■
Function Does This .1
each Returns the current key and value pair from an array and advance
the array cursor
extract Imports variables into the current symbol table from an array
There are many array functions here—a great deal of array power. The rest of the
chapter shows you the kinds of things these functions can do, such as "imploding" and
"exploding" arrays.
<?php
$ice_cream[0] = "chocolate";
$ice_cream[1] = "pecan";
$ice_cteam[2] = "strawberry";
As you can see, you specify the string that separates the array items yourself—in this
case, that's ",
How about exploding a string into an array? To do that, you indicate which text you
want to split the string on, such as ",", and pass that to explode. Here's an example:
<?php
$text = "chocolate, pecan, strawberry";
$ice_cream = explode(", ", $text);
print_r($ice_cream);
?>
And here are the results—you exploded the string into an array:
Array
(
[0] => chocolate
[1] => pecan
[2] => strawberry
<?php
$ice_cream["good"] = "orange";
$ice_cream["better"] = "vanilla";
$ice_cream["best"] = "rum raisin";
Now you can use extract to create variables whose names will be taken from the keys in
the array, and those variables will be assigned the values in the array. Here's how that
works in phpextract.php:
<html>
<head>
<title>
Extracting variables from arrays
</title>
</head>
108 PHP: The Complete Reference
<body>
<hl>Extracting variables from arrays</hl>
<?php
$ice_cream["good"] = "orange";
$ice_cream["better"] = "vanilla";
$ice_cream["best"] = "rum raisin";
extract($ice_cream);
<?php
$ice_cream[0] = "chocolate";
$ice_cream[1] = "pecan";
$ice_cream[2] = "strawberry";
list($one, $two) = $ice_cream;
echo $one, "<br>";
echo $two;
?>
chocolate
pecan
Sorting Arrays
There's a bunch of array sorting power built into PHP, starting with the sort function, which
sorts arrays in ascending order. Here's an example, phpsortarray.php:
<?php
$ice_cream[0] = "orange";
$ice_cream [G.]' = "vanilla";
$ice_cream[2] = "rum raisin";
print_r ($ice_creain) ;
sort($ice_cream);
print_r($ice_cream);
?>
%php phpsortarray.php
Array
(
[0] => orange
[1] => vanilla
[2] => rum raisin
)
Array
(
[0] => orange
[1] => rum raisin
[2] => vanilla
<?php
$ice_cream[0] = "orange";
$ice_cream[1] = "vanilla";
$ice_cream[2] = "rum raisin";
print_r($ice_cream);
rsort($ice_cream);
print_r($ice_cream);
?>
Array
(
[0] => orange
[1] => vanilla
[2] => rum raisin
)
110 PHP: The Complete Reference
Array
(
[0] => vanilla
[1] => rum raisin
[2] => orange
This doesn't work so well if you're using text string keys in your arrays instead of
numeric index values—the text string keys will just be replaced witf} numbers. Use asort
instead, as in phpasortarray.php:
<?php
$ice_cream["good"] = "orange";
$ice_cream["better"] = "vanilla";
$ice_cream["best"] = "rum raisin";
print_r($ice_cream);
asort($ice_cream);
print_r($ice_cream);
?>
%php phpasortarray.php
Array
(
[good] => orange
[better] => vanilla
[best] => rum raisin
)
Array
(
[good] => orange
[best] => rum raisin
[better] => vanilla
)
<?php
$pudding["raspberry"] = 333;
$pudding["peach"] = 222;
$ice_cream["pecan"] = 111;
$ice_cream["chocolate"] = 999;
echo "\$ice_cream: ";
print_r($ice_cream);
echo "\n";
echo "\$pudding: ";
print__r ($pudding) ;
echo "\n";
$desserts = $pudding + $ice_cream;
echo "\$desserts: ";
print_r($desserts);
echo "\n";
if ($pudding == $ice_cream){
echo "\$pudding has the same elements as \$ice_cream";
}
else {
echo "\$pudding does not have the same elements as \$ice_cream";
%php phparrayoperators.php
$ice_cream: Array
(
[pecan] => 111
[chocolate] => 999
$pudding: Array
(
[raspberry] => 333
[peach] => 222
112 PHP: The Complete Reference
$desserts: Array
(
[raspberry] => 333
[peach] => 222
[pecan] => 111
[chocolate] => 999
)
<?php
$ice_cream = array("vanilla", "chocolate", "strawberry");
$ice_cream2 = array("vanilla", "chocolate", "papaya");
This example compares two arrays and displays the elements that are different. Here's
what you get in this case:
%php phparraydiff.php
Key: 2; Value: strawberry
If you're using text string keys, use the array_diff_assoc function (arrays with text string
keys are also called associative arrays). If you want to find all the elements that two arrays
have in common, just use array_intersect or array_intersect_assoc.
$scores["Sam"] = 79;
$scores ["Ellen"] = 69;
Now say that you gave a second exam. You could just add another index—for exam
number—to each student:
<?php
$scores["Sam"][1] = 79;
$scores["Sam"][2] = 74;
Chapter 3: Strings and Arrays U3
$scores["Ellen"][1] = 69;
$scores["Ellen"][2] = 84;
print_r($scores);
?> *r- '
At this point, $scores["Sam"][l] is Sam's test score on the first test, $scores["Sam"][2] is
his score on the second test, and so on. This script displays the new, multidimensional array
with print_r, giving ybu this:
In addition, you can access elements using both indexes, like this:
If you want to interpolate an array item in double quotes, it takes a little more work—
you have to enclose it in curly braces:
As you might expect, you can also create multidimensional arrays this way (note that
this will start the arrays off at an index value of 0):
<?php
$scores["Sam"][] = 79;
$scores["Sam"][] = 74;
$scores["Ellen"][] = 69;
$scores["Ellen"][] = 84;
print_r($scores);
?>
You can also think of multidimensional arrays as arrays of arrays. For instance, you can
think of a two-dimensional array as a one-dimensional array (the rows of the two-
dimensional array) of one-dimensional arrays (the columns of the two-dimensional array).
That means that this syntax is legal:
<?php
$scores = array("Sam" => array(79, 74), "Ellen" => array(69, 84));
print_r($scores);
?>
114 PHP: The Complete Reference
You could even start the array indexes at 1 instead of 0 like this:
<?php
$scores = array("Sam" => array(l => 79, 2 => 74),
"Ellen" => array(l => 69, 2 => 84));
print_r($scores) ;
?>
<?php
$ scores [0] [] = 79 ;
$scores [0] [] = 74 ;
$scores [1] [] = 69 ;
$scores [1] [] = 84 ;
for ($outer = 0; $outer < count($scores); $outer++){
}
?>
Chapter 3: Strings and Arrays 115
Now you can loop over the inner index like this in phpmultiloop.php:
<html>
/ '■
<head>
<title>
Looping over multidimensional arrays
</title>
</head> *
<body>
<hl>
Looping over multidimensional arrays
</hl>
<?php
$scores [0] [] = 79;
$scores [0] [] = 74 ;
$scores [1] [] = 69;
$ scores [1] [] = 84 ;
for ($outer = 0; $outer < c'ount ($scores) ; $outer+ + ) {
for($inner = 0; $inner < count($scores[$outer] ) ; $inner++){
echo "\$scores[$outer] [$inner] = ",
$scores[$outer] [$inner], "<br>";
}
}
?>
</body>
</html>
You can see the results, where the two-dimensional array has indeed been looped over.
in Figure 3-13.
$ice_cream[0] = "chocolate";
$ice_cream[1] = "pecan";
$ice_cream[2] = "strawberry";
You can access the current element in the array with the current function:
You can move the array pointer to the next element with the next function:
The prev function moves the pointer back to the previous element:
The end function moves the pointer to the last element in the array:
If you want to move back to the beginning of the array, use the reset function:
reset($ice_cream);
<html>
<head>
<title>
Navigating through arrays
</title>
</head>
<body>
<hl>
Navigating through arrays
</hl>
<?php
$ice_cream[0] = "chocolate";
$ice_cream[1] = "pecan";
$ice_cream[2] = "strawberry";
reset($ice cream);
echo "Current element: ", current($ice_cream) , "<br>";
?>
</body>
</html>
You can see the results, where you've navigated through the array, in Figure 3-14.
<html>
<head>
<title>
Splitting arrays
</title>
</head>
<body>
<hl>
Splitting arrays
</hl>
<?php
$ice_cream["good") = "orange";
$ice_cream["better"] = "vanilla";
$ice cream["best"] = "rum raisin";
$ice_cream["bestest"] = "lime";
$subarray = array_slice($ice_cream, 1, 2);
118 PHP: The Complete Reference
}
?>
</body>
</html>
And you can see what this gives you in Figure 3-15—you've been able to extract a
section of an array. v • >
You can also merge arrays with the arrayjmerge function, like this in phpmergearrays.php:
<html>
<head>
<title>
Merging arrays
</title>
</head>
<body>
<hl>
Merging arrays
</hl>
<?php
$pudding = array("vanilla", "rum raisin", "orange");
$ice_cream = array("chocolate", "pecan", "strawberry");
?>
</body>
</html>
You can see the result in Figure 3-16, where the two arrays have been merged.
<?php
$scores = array(65, 61, 70, 64, 65);
In addition, the array_flip function will flip an array's keys and values. You can see that
at work in phparrayflip.php:
<html>
<head>
<title>
Flipping keys and values in arrays
</title>
</head>
120 PHP: The Complete Reference
<body>
<hl>
Flipping keys and values in arrays
</hl>
<?php
$ice cream = array (" flavor__l" => "vanilla", "flavor_2" => "rum raisin",
"flavor_3" => "orange");
} :
echo "<br>";
$ice_cream = array_flip($ice_cream);
}
?>
</body>
</html>
<?php
$scores = array(65, 61, 70, 64, 65);
print_r($scores);
$scores = array_unique($scores);
printer ($score.s) ;
?>
%php phparrayunique.php
Array / r'
(
[0] => 65
[1] => 61
[2] => 70 ,
[3] => 64
[4] => 65
)
Array
(
[0] => 65
[1] => 61
[2] => 70
[3] => 64
As you can see, the duplicate array element has been removed.
*s
.
!H*i»iiaaiJ«H88a»«88S8ggai838^lttM]IMIIirj»MliMfc8aa8aS»8388%88£8gil8i«
CHAPTER
Creating Functions
I t s time to take the next step in programming power, and that means creating your own
functions. You've seen many built-in PHP functions already—functions are those
callable sections of code that you can pass data to, and that can return data to you.
Functions let you break your code up, following that old programming dictum: Divide
and Conquer. Got some code that needs to be run multiple times in your application? Put it
into a function. Got some code that shouldn't be run automatically when the page loads
(as all the code up to now has)? Put it into a function. Got code that's just getting too long to
effectively debug and maintain? Put it in a function.
By putting code into a function, you get it out of the way—out of sight, out of mind is
the idea. You pass data to that function, and the function can pass data back to you. You
may have seen functions in other languages, but as you're going to see, PHP functions
support many unique features.
Restricting code to functions breaks up your code in an especially useful way: the
variables you use inside a function are, by default, not visible outside that function. That
means you don't have to worry about conflicts with variables names; using a $account
variable in two different parts of your code may conflict, but not if you wrap code inside
a function.
Using functions is only the beginning of dividing up your code—using object-oriented
programming is going to let you wrap both functions and data into classes and objects. That
is, functions were vital to letting programmers section their code, but in time, developers'
needs outgrew simple functions, and combining functions and data into objects was the
next step. It all starts with functions, however, and that's coming up now.
function function_name([argument_list...] )
{
[statements]
[return return_value;]
123
124 PHP: The Complete Reference
Time for an example. You might create a function named display that displays some text
in the browser in an example named phpdisplay.php. You might have phpdisplay.php
display some text indicating it's about to call the function:
<?php
echo "About to call the function...<br>";
echo "Calling the function...<br>";
?>
Next, add the code for the display function; that looks like this:
<?php
echo "About to call the function...<br>";
echo "Calling the function ...<br>";
function display()
{
echo "This text was displayed by the function.";
}
?>
There are a couple of things to note here. First, the code inside a PHP function isn't
executed until that function is called. That's different from the scripts you've seen up to
now—if you simply place code in a script, outside a function, that code is executed when
the page loads.
Note also the syntax of the function definition; that definition starts with the keyword
function, followed by the name of the function, which is followed by parentheses (empty at
this point, because you're not passing any data to the function). The body of the function—
that is, the statements that will be executed when the function is called—are enclosed in
curly braces.
Alright, that creates the function; how do you call it? You can call the display function
as you'd call it in any other programming language—by using its name as a statement,
followed by parentheses (empty parentheses in this example, because you're not passing
any data to the display function):
<html>
<head>
<title>
Creating functions
</title>
</head>
<body>
<hl>
Creating functions
</hl>
<?php
echo "About to call the function...<br>";
echo "Calling the function...<br>";
display();
Chapter 4: Creating Functions 125
function display()
{
echo "This text was displayed by the function.";
}
?>
</body>
</html>
You can see this example at work in Figure 4-1—note that the display function was
called and did its thing, displaying text. Not bad.
function function_name([argument_list...] )
{
[statements]
[return return_value;]
Here's an example, phppassdata.php. Say you wanted to pass the text data to the
display function that the function should display. You can do that by adding a function
argument to the argument list, like this in the display function:
function display($greeting)
}
126 PHP: The Complete Reference
Now you can refer to the passed data by name, Sgreeting, like this in the display
function's code:
function display($greeting)
{
echo $greeting;
}
That's how to let a function accept passed data—you list the napae you want to give to the
passed data in the function's argument list, and then you can refer to that data in the code
for the function.
You pass data to a function by placing that data inside the parentheses that follow the
function's name when you call that function. For example, if you wanted to pass the text
"Hello!" to the display function to make that function display that text, you could do so
like this:
display("Hello!");
function display($greeting)
{
echo $greeting;
Now when the display function is called like this, the Sgreeting argument—also called a
parameter—is assigned the value "Hello!”, when the line echo Sgreeting is executed, "Hello!"
will appear in the browser.
What if you wanted to pass two data items to a function? You can list them in the
argument list of the function, separated by commas. For example, to make the display
function accept two arguments, you simply list them by name, say Sgreeting and Smessage:
Now you can refer to Sgreeting and Smessage by name in your function's code:
When you call the display function, you list the arguments you want to pass to that
function, separated by commas like this in phppassdata.php:
<html>
<head>
<title>
Chapter 4: Creating Functions 127
{
echo $greeting;
echo $message;
}
?>
</body>
</html>
You can see the results in Figure 4-2, where the data has indeed been passed to the
display function.
<?php
$scores = array(65, 32, 78, 98, 66);
?>
^ • ‘
And here's how you might pass the Sscores array to the averager function:
<?php
$scores = array(65, 32, 78, 98, 66);
averager($scores);
?>
In the averager function, you specify the name of the array, which we'll call simply
$array here:
<?php
$scores = array(65, 32, 78, 98, 66);
averager($scores);
function averager($array)
{
}
?>
In the averager function, you can use a foreach statement to loop over the array:
<?php
$SCores = array(65, 32, 78, 98, 66);
averager($scores);
function averager($array)
{
foreach ($array as $value) {
}
}
?>
Chapter 4: Creating Functions 129
Then you might add up all the elements in the array in a variable named $total:
<?php
$scofes = array(65, 32, 78, 98, 66);
averager($scores);
i • *
function averager($array)
{
$total =0;
foreach ($array as $value) {
$total += $value;
}
}
?>
And finally, you can determine the average value of the array elements and display it in
phppassarray. php:
<html>
<head>
<title>
Passing arrays to functions
</title>
</head>
<body>
<hl>
Passing arrays to functions
</hl>
<?php
$scores = array(65, 32, 78, 98, 66);
averager($scores);
function averager($array)
{
$total = 0;
foreach ($array as $value) {
$total += $value;
}
}
?>
</body>
</html>
And you can see the result—the average was 67.8, as you see in Figure 4-3.
130 PHP: The Complete Reference
Passing by Reference
When you pass data to a function, what's really passed is a copy of that data. So, for
example, if you pass a variable, a copy is made of that variable, and that copy is actually
passed to the function.
What if you wanted to actually pass the real thing to the function? Say for example that
you wanted a function to alter the value in a variable? For example, say that you had a
variable $value:
<?php
$value = 4;
?>
and you wanted a function to square the value in Svalue. You might try that by passing
Svalue to a function named, say, squarer, which squares the number passed to it:
function squarer($number)
{
$number *= $number;
}
However, that's not going to work, because the arguments passed to the squarer
function are passed by value. You can change that by prefacing the argument you want
passed by reference with an ampersand (&)—which will make PHP pass that argument
by reference. When you pass an argument by reference, that gives the code in the function
direct access to that argument back in the calling code, so to square the value in $value.
Chapter 4: Creating Functions 131
all you have to do is to preface the argument with & in the argument list like this in
phpreference.php:
<head>
<title>
Passing data to functions by reference
</title> ,,,
</head>
<body>
<hl>
Passing data to functions by reference
</hl>
<?php
$value = 4;
function squarer(&$number)
{
$number *= $nuraber;
}
?>
</body>
</html>
And you can see the results in Figure 4-4, where, as you can see, the data in $value back
in the calling code was squared. Very cool.
display("No worries");
PHP isn't going to like that; here's the kind of warning you get:
On the other hand, you can fix this problem by supplying a default argument here.
Here's the way it works: you add the default argument in the argument list, using an
equal sign, as you see here:
}
Now if you don't pass anything for the second argument to the display function, the
default argument is automatically used. Here's the way you might call the display function
in an example, phpdefaultarguments.php
<html>
<head>
<title>
Using default function arguments
</title>
</head>
<body>
<hl>
Using default function arguments
</hl>
<?php
echo "About to call the function...<br>";
echo "Passing data to the function...<br>";
display("The default argument is: ");
And you can see the result in Figure 4-5, where the default argument was indeed used.
Want to provide multiple default arguments? No problem:
You can give default values to more than one argument, but once you start assigning
default values, you have to give them to all arguments that follow as well so that PHP won't
get confused if more than one argument is missing.
connector("Hello");
or like this:
connector("Hello", "there");
or like this:
How do you handle variable number of arguments like this in a function? You can
handle them with these functions:
For example, here's how you start the connector function—by getting an array of the
arguments passed to the function:
function connector()
{
$arguments = func_get_args();
Then you can loop over the arguments like this—note that you can get the number of
arguments from the func_num_args function:
function connector()
{
$data = "";
$arguments = func_get_args();
}
echo $data;
Note that the final, resulting string is echoed. Here's how you might put the connector
function to work in an example, phpvariableargs.php:
<html>
<head>
<title>
Passing variable arguments to functions
</title>
</head>
<body>
<hl>
Passing variable arguments to functions
</hl>
<?php
echo "Passing ’How1 'are1 'things?' to connector...<br>";
echo "Getting this result:
connector("How", "are", "things?");
Chapter 4: Creating Functions 135
/
function connector()
{
$data = "";
$arguments = func_get_args();
}
echo $data;
?>
</body>
</html>
You can see the results in Figure 4-6, where the connector function was able to handle
the arguments passed to it.
Now say that you didn't want the connector function to display the connected string,
but wanted to have that string returned to your code so that you could put it to work
yourself. That's a very common thing for functions to do—return values that give you their
results. And it's coming up next.
<?php
function adder(operand_l, operand_2)
{
$sum = $operand_l + $operand_2;
136 PHP: The Complete Reference
}
?>
Now that you've got the sum in the variable named $sum, how do you return that value
to the calling code? You can use the PHP return statement:
v ‘ ‘
<?php
function adder(operand_l, operand_2) •
{
$sutn = $operand_l + $operand_2;
return $sum;
?>
This returns the value in $sum to the calling code. Here's how you can put adder to
work—the expression adder($value_l, $value_2) here is replaced by the value returned by
the adder function, which is 5:
<?php
$value_l = 2;
$value_2 = 3;
{
$sum = $operand_l + $operand_2;
return $sum;
?>
The sum of 2 + 3 is 5
Here's another example using the connector function from the preceding topic. You just
have to modify the connector function to return its data like this in phpreturndata.php:
<html>
<head>
<title>
Returning values from functions
</title>
</head>
<body>
<hl>
Returning values from functions
</hl>
Chapter 4: Creating Functions 137
/
<?php
echo "Passing 'How' 'are' 'things?1 to connector...<br>";
echo "Getting this result: ", connector("How", "are", "things?");
function connector()
{
$data = "" ;
$arguments = func_get_args();
}
return $data;
}
?>
</body>
</html>
You can see the results in Figure 4-7, where the connector function returned its result
string, which was then displayed by the calling code.
That's how to return simple values like strings from functions. How about arrays?
Coming up next.
Returning Arrays
You can return arrays from functions as easily as you return simple values. Say you have a
function, create_array, that creates arrays of the length you specify by passing a number to
the create_array function. This function stores 0 in the zeroth element, 1 in the first element,
2 in the second element, and so on.
138 PHP: The Complete Reference
So if you passed a 3 to create_array, you should get the array [0,1, 2] back. If you passed
a 4, you should get [0,1, 2, 3] back, and so on. Here's how you start the create_array
function:
Here's how you can create the array, $array, to return from this function:
function create_array($number)
{
for ($loop_counter = 0; $loop_counter < $number; $loop_counter++){
$array[] = $loop_counter;
That creates the array named $array. Now you can return it from the create_array
function just as you would return any simple value—with the return statement:
function create_array($number)
{
for ($loop_counter = 0; $loop_counter < $number; $loop_counter++){
$array[] = $loop_counter;
}
return $array;
Here's how you can put the create_array function to work in an example named
phpreturnarray.php:
<html>
<head>
<title>
Returning arrays from functions
</title>
</head>
<body>
<hl>
Returning arrays from functions
</hl>
Chapter 4: Creating Functions 139
<?php
$data = create array(3);
echo "Here's the first array:<br>";
print_r($data);
echo "<br>";
function create_array($number)
{
for ($loop_counter = 0; $loop_counter < $number; $loop_counter++){
$array[] = $loop_counter;
return $array;
}
?>
</body>
</html>
You can see the results in Figure 4-8, where the create_array function created the array it
was asked to create and returned it. Very nice.
Returning Lists
You may recall the list function from Chapter 3, which converted arrays into lists of
variables. That's the key to letting your functions return multiple values as well.
140 PHP: The Complete Reference
Normally, functions can only return single values, but if you return an array and
handle that array as a list in the calling code, you'll find that you can return as many
values as you like from PHP functions. For example, say that you wanted to convert the
create_array function from the preceding topic into a function create_list:
{
for ($loop_counter = 0; $loop_counter < $number; $loop_counter++)(
$array[] = $loop_counter; '
} ;
return $array;
Now you can handle the returned array as a list in the calling code in phpreturnlist.php
like this:
<html>
<head>
<title>
Returning lists from functions
</title>
</head>
<body>
<hl>
Returning lists from functions
</hl>
<?php
list($first, $second, $third) = createlist(3);
echo "Here's the first list:<br>";
echo "$first, $second, $third<br>";
function create_list($number)
{
for ($loop_counter = 0; $loop_counter < $number; $loop_counter++){
$array[] = $loop_counter;
return $array;
}
?>
</body>
</html>
You can see the results in Figure 4-9, where the create_list function returned an array
that was properly handled as a list. Cool.
Chapter 4: Creating Functions 141
Returning References
Functions can also return references in PHP. That's not something you're going to do all the
time, so feel free to move on to the next topic if you want. But if you want the complete
story, keep reading.
References are interesting items in PHP. For example, say that you had a variable named
$value; you could get a reference to that variable with the reference operator, &:
$value = 4;
$ref = & $value;
Now $ref is a reference to $value, and it will point to the same data in memory as
$value—changing one changes the other:
$value = 4;
$ref = & $value;
$ref = 6;
{
return $ref;
Note that this function takes a reference as its argument, as the & in the argument list indicates.
And it also returns a reference, as is indicated by the & in front of the function's name.
142 PHP: The Complete Reference
So you pass the return_reference function a reference to a variable, and it returns the
same reference. Now let's pass a reference to a variable to the retum_reference function, and
get that reference back:
<?php
$value = 4;
echo "Current value: ", $value, "\n";
$re£ = &return_reference($value); . ,
<?php
$value = 4;
echo "Current value: ", $value, "\n";
$ref = &return_reference($value);
$ref++;
And you can confirm that the original variable was incremented like this in
phpreturnreference.php:
<html>
<head>
<title>
Returning references from functions
</title>
</head>
<body>
<hl>
Returning references from functions
</hl>
<?php
$value = 4;
echo "Current value: ", $value, "\n";
$ref = &return_reference($value);
$ref++;
You can see the results in Figure 4-10, where the reference was created and passed to the
retum_reference function, which returned the same reference. And then that reference was
used to increment the variable it points to.
...
.....IB
f|-rr--i----Bonr-"riiarT-it-trii-n-]irii>ir-irMnMTror-|-[i-inir-rmn»iini.iT.ini] ■ . _
<?php
$value =4;
Next, it calls the scoper function, which also has a variable named $value, which is set
to 8000000, and echoes that variable from inside the function. Then it goes back to script
144 PHP: The Complete Reference
scope again and echoes the script-level $value again—which is still 4. You can see it all in
phpscope.php:
<html>
<head>
<title>
Handling scope in functions
</title>
</head> * • »
<body>
<hl> f
Handling scope in functions
</hl>
<?php
$value = 4;
scoper();
echo "In the calling code again, \$value still = ", $value, "<br>";
function scoper()
{
$value = 8000000;
echo "In the function, \$value = ", $value, "<br>";
}
?>
</body>
</html>
You can see the results in Figure 4-11, where you can see the scope of the $value variable
both inside and outside the scoper function.
<?php
$value = 4;
function scoper()
{
$value = 8000000;
echo "In the function, \$value = ", $value, "<br>";
}
?>
How would you do that? In PHP, script-level data is called global data, and you can
access that data from inside a function with the global keyword. You can see how this
works in a new example, phpglobalscope.php, which modifies the preceding example to
also call a function named global_scoper:
<?php
$value = 4 ;
scoper();
global scoper ();
echo "In the calling code again, \$value still = ", $value, "<br>";
function scoper()
{
$value = 8000000;
echo "In the scoper function, \$value = ", $value, "<br>";
}
?>
To access the global variable $value from inside global_scoper, you can declare that
variable using the global keyword:
<?php
$value = 4;
146 PHP: The Complete Reference
scoper();
global_scoper();
echo "In the calling code again, \$value still = ", $value, "<br>";
function scoper()
{ $value = 8000000;
echo "In the scoper function, \$value = ", $value, "<br>";
function global_scoper()
{
global $value;
}
?>
Now you can echo the $value variable inside the global_scoper function to verify that
you're really dealing with the global $value variable like this in phpglobaldata.php:
<html>
<head>
<title>
Handling local and global scope in functions
</title>
</head>
<body>
<hl>
Handling local and global scope in functions
</hl>
<?php
$value = 4;
scoper();
global_scoper();
echo "In the calling code again, \$value still = ", $value, "<br>";
function scoper()
{
$value = 8000000;
echo "In the scoper function, \$value = ", $value, "<br>";
}
Chapter 4: Creating Functions 147
function global_scoper()
{
global $value,-
echo "In the global scoper function, \$value = ", $value, "<br>";
}
?>
</body>
</html>
You can see the results in Figure 4-12, where you can see you can indeed access global
data from inside a function if you use the global keyword.
<html>
<head>
<title>
Keeping a count of function calls
</title>
</head>
<body>
<hl>
Keeping a count of function calls
</hl>
148 PHP: The Complete Reference
php
count is: ii count function(), "<br>";
echo "Now the /
echo "Now the count is: / count function(), "<br:>";
"Now the count is: ii count function(), "<br>";
echo /
"Now the count is: ii countfunction(), "<br>";
echo #
"Now the count is: ii count function(), "<br>";
echo §
function count_function()
{
$counter = 0;
$counter++;
return $counter;
}
?>
</body>
</html>
But you get the results shown in Figure 4-13, where the count is always 1. That's
because $counter is reset to 0 every time you call the count_function.
How do you fix this?
There are two easy ways to fix this issue. First, you can make $counter a global variable,
and access it as such in the count_function like this:
<?php
{counter =: 0;
echo "Now the count is : n count functionO, "<br>";
ii
echo "Now the count is : count functionO, "<br>";
ti
echo "Now the count is : count functionO, "<br>";
ii
echo "Now the count is : / count functionO, "<br>";
ii
echo "Now the count is : / count functionO, " <br>";
function count_function()
{
global $counter;
* '-$counter++ ;
return $counter;
}
?>
i - *
That works, and you get:
There's another way as well, and it doesn't compromise by insisting you use global
variables. You can also declare the $counter variable in the counter_function as static, which
means that it will preserve its value between function calls. Here's how you do that with the
static keyword:
<html>
<head>
<title>
Keeping a count of function calls
</title>
</head>
<body>
<hl >
Keeping a count of function calls
</hl>
<?php
count is : n count_ function() , "<br>";
echo "Now the /
count is : ii count _function(), "<br>";
echo "Now the !
{
static $counter = 0;
$counter++;
return $counter;
}
?>
</body>
</html>
Now you can see the results in Figure 4-14—as you see there, the static keyword did the
trick, because the number of times the function was called is indeed reported correctly.
150 PHP: The Complete Reference
<?php
echo "normal_function() is ready to go as soon as the script starts.<br>";
normal_function();
function normal_function()
{
echo "Hello from the normal function.<br>";
}
This code will call and execute normal_function as soon as the page loads, and there's
no problem with that. However, now say that you have another function, conditional,
function, whose code is inside an if statement. That function isn't available until the code
inside the if statement is executed, so you're going to have problems calling conditional,
function before the if statement is run, as here:
<?php
echo "normal_function() is ready to go as soon as the script starts.<br>";
normal_function();
Chapter 4: Creating Functions 151
$create_function = TRUE;
conditionalfunction();
if ($create_function) {
function conditionalfunction()
{
echo "Hello from the conditional function.<br>";
}
}
function normal_function()
{
echo "Hello from the normal function.<br>";
You can see the results in Figure 4-15—as you see, the conditional_function doesn't exist
before the if statement containing it executes, and you get a fatal error.
So let's change this to make sure that conditional_function is called only after it exists,
which you can keep track of with a variable named $function_created:
<?php
echo "normal function() is ready to go as soon as the script starts.<br>";
normal function();
152 PHP: The Complete Reference
$create_function = TRUE;
$function_created = FALSE;
if ($create_function) {
function conditional function() , .
{
echo "Hello from the conditional function.<br>";
}
$function_created = TRUE;
}
function normal_function()
{
echo "Hello from the normal function.<br>";
}
And you can call conditional_function after it has been created, like this in
phpconditionalfunction.php:
<html>
<head>
<title>
Creating conditional functions
</title>
</head>
<body>
<hl>
Creating conditional functions
</hl>
<?php
echo "normal_function() is ready to go as soon as the script starts.<br>"
normal_function();
$create_function = TRUE;
$function_created = FALSE;
if ($create_function) {
function conditional_function()
{
echo "Hello from the conditional function.<br>";
}
$function_created = TRUE;
}
Chapter 4: Creating Functions 153
if ($function created){
conditional_function();
}
function normal_function()
{
echo "Hello from the normal function.<br>" ;
}
?>
</body>
</html>
Now you can see the results in Figure 4-16—as you see there, the conditional function
was accessible after the if statement was executed. Cool.
<?php
function red()
{
echo "In red() now.<br>";
}
154 PHP: The Complete Reference
function white($argument)
{
echo "$argument <br>";
}
function blue($argument)
{
echo "$argument <br>";
}
?>
v ' ‘
Now you can assign the name of the red function to a variable that we'll call Sfunction
variable in this example—and then you can treat $function_variable' as though it is the
name of a function, and call it like this:
<?php
$function_variable = "red";
$function_variable();
function red()
{
echo "In red() now.<br>";
}
function white($argument)
{
echo "$argument <br>";
}
function blue($argument)
{
echo "$argument <br>";
}
?>
Similarly, you can use the same technique to call the white and blue functions (note that
the functions called this way can have different argument lists):
<html>
<head>
<title>
Creating variable functions
</title>
</head>
<body>
<hl>
Creating variable functions
</hl>
<?php
$function_variable = "red";
$function_variable();
\
$function_variable = "white";
$function_variable("In whiteO now.");
$function_variable = "blue";
$function_variable("In blue() now.");
function red()
{
echo "In red() now.<br>";
}
function white($argument)
{
echo "$argument <br>";
}
function blue($argument)
{
echo "$argument <br>";
}
?>
</body>
</httnl>
Nesting Functions
You can also nest function definitions in PHP. Note that you can't call the nested function until
its enclosing function has been run—the nested function won't be accessible until that time.
Here's an example, phpnestedfunctions.php. This example starts by defining a function,
outer_function, which encloses another function, inner_function:
<?php
function outer_function()
{
echo "In the outer function.<br>";
function inner_function()
{
echo "In the inner function.<br>";
}
?>
Now you can call outer_function and inner_function—but only in that order, because
calling outer_function makes PHP define inner_function—like this in phpnestedfunctions.
php:
<html>
<head>
<title>
Nesting functions
</title>
</head>
<body>
<hl>
Nesting functions
</hl>
<?php
outerfunction();
inner_function();
function outer_function()
{
echo "In the outer function.<br>";
function inner_function()
{
echo "In the inner function.<br>";
}
}
?>
</body>
</html>
Chapter 4: Creating Functions 157
The results appear in Figure 4-18, where you can see the calls to both outer Jhnction and
inner_function were successful.
<?php
define("premium", 176.53);
?>
Now you can include premium.inc in your code with the PHP include statement
this way:
<?php
echo "Including constants.inc....<br>";
include("premium.inc");
?>
158 PHP: The Complete Reference
After you include premium.inc, the contents of that file are available to your code. In
this case, that means the constant named premium is now accessible to your code, so you
can make use of that constant like this:
<html>
<head>
<title>
Using include files
</title>
</head>
<body>
<hl>
Using include files
</hl>
<?php
echo "Including premium.inc....<br>";
include("premium.inc");
The results appear in Figure 4-19, where you can see that the constant from the include
file has indeed been included.
Here's an example—say you have a function named reciprocal that calculates reciprocals
(one divided by a number). But you don't want to try to calculate one divided by zero, so
return FALSE if you're asked to like this in the reciprocal function, and TRUE if things
worked,, out okay: j
<?php
function reciprocal($value)
{
if ($val'ue != 0) {
echo 1 / $value, "<br>";
return TRUE;
}
else {
return FALSE;
}
}
?>
Now you can call the reciprocal function and add the clause "or die (message)", where
message is a message that will be displayed if the reciprocal function returned a value of
FALSE. It looks like this in code—when you call the die function, the application quits:
<html>
<head>
<title>
Handling errors from functions
</title>
</head>
<body>
<hl>
Handling errors from functions
</hl>
<?php
echo "The reciprocal of 2 is:
reciprocal(2) or die ("Cannot take the reciprocal of zero.");
echo "The reciprocal of 0 is:
reciprocal(0) or die ("Cannot take the reciprocal of zero.");
function reciprocal($value)
{
if ($value != 0) {
echo 1 / $value, "<br>";
return TRUE;
}
else {
return FALSE;
}
}
?>
</body>
</html>
v
160 PHP: The Complete Reference
The results appear in Figure 4-20, where you can see that the reciprocal of 2 appears
fine, but then when you ask the reciprocal function to calculate the reciprocal of zero, it
choked and returned FALSE, which ended the application.
CHAPTER
Reading Data in Web Pages
T his is the chapter a lot of developers have been waiting for—the chapter that covers
connecting HTML controls in Web pages like text fields, radio buttons, check boxes
and so on, to PHP back on the server.
You have the basics of PHP down at this point, which means you can handle the code
necessary to work with PHP and HTML controls. So we're going to get connected to HTML
in this chapter, seeing how to read data that the user has entered into HTML controls in
Web pages.
<form>
</form>
You need to specify the method with which your data will be sent—the two most
common methods are "get" and "post" (more on the difference between them later—
both methods will get your data to your PHP script), and you might choose the get
method here:
<form method=Mget">
</form>
161
162 PHP: The Complete Reference
Alright, this tells the browser how it's supposed to send the data in the Web page—and
you also have to tell the browser where to send that data with an URL. You assign that URL
to the <form> element's action attribute, like this:
</form>
v • ‘
This <form> element will send its data to the URL http://www.phpisgreat.com/phpreader.
php when the Submit button (coming up in a moment) is clicked.
You can also assign relative URLs to the action attribute. If, for example, this HTML
page resided on the server in a specific directory, and the PHP script phpreader.php resided
in the same directory on the server, you could shorten the URL to this:
</form>
This version of the <form> element assumes that the HTML page currently in the browser
came from the same directory as the PHP script is in. For example, if this HTML page was
http://www.phpisgreat.com/input.html, then the PHP script specified by simply assigning
"phpreader.php" to the action attribute would send the data in the HTML page to the PHP
script at http://www.phpisgreat.com/phpreader.php.
There's even another version—you can omit the action element altogether:
<form methods"get">
</form>
In this case, the form s data is sent back to the same URL that the current document is at.
For example, if you have a PHP script that can display HTML controls, phpcomplete.php,
then when you navigate to that script in your browser, you'll see those HTML controls. If
there's no action attribute, the data in the form will be sent back to the exact same script
when the user clicks the Submit button.
That's a common thing to do—have a PHP script handle both the display of the HTML
controls, and then read the data in those HTML controls when the user clicks the Submit
button. You'll see how this works in this book.
Besides the HTML controls like text fields and check boxes, you'll also need a submit
button in your form, because the data in the form is sent to your PHP script when that
submit button is clicked. The submit button need not have the caption "Submit"—you
can set its caption to anything you like by assigning that caption to the submit button's
value attribute.
Chapter 5: Reading Data in Web Pages 163
Here's how to create a submit button—note it has to be inside the HTML <form>
element with the caption Send, and that you use an <input> element with the type
attribute set to "submit" to create a submit button:
<html>
<head>
<title>
Connecting to PHP
</title> < • 4
</head>
<body>
<hl>
Connecting to PHP
</hl>
<form method="get" action="phpreader.php">
Note that there's also a (optional) reset button here; when clicked, this button resets the data
in all the HTML controls in the form back to their default values.
Say you wanted to use a text field (that is, a <input type = "text"> HTML control) to ask
for the user's name; you could do that like this in the HTML form:
<html>
<head>
<title>
Connecting to PHP
</title>
</head>
<body>
<hl>
Connecting to PHP
</hl>
<form method="get" action="phpreader.php">
What’s your name?
Note that this HTML gives the name "data" to the text field. How can you access the name
entered into this text field on the server, in your PHP script?
164 PHP: The Complete Reference
If you've used the POST method, you can find that data in the $_POST array, as we're
going to start seeing in the next chunk on retrieving data from text fields. If you've used the
GET method, you use the $_GET array These arrays are "superglobal" arrays, which means
that they're available to you without having to use the global keyword. Also, the $_REQUEST
array holds data from both $_GET and $_POST.
That means that to recover the name the user entered into the text field named "data",
you can use the expression $_REQUEST["data"] in your PE1P script.
Let's put all this into practice with real text fields, coming up next.
<html>
<head>
<title>
Entering data into text fields
</title>
</head>
<body>
<hl>
Entering data into text fields
</hl>
<form method="get" actions"phptext.php">
What's your name?
You can see this HTML page in Figure 5-1, waiting for you to enter your name.
Okay, so how do you read the data the user entered in this Web page—that is, their
name in a text field we've named "data"—from PHP on the server?
This HTML page is set up to send its data to the PHP script phptext.php (note that
because you've assigned a relative URL to the action attribute—just the name of the
PHP script that PHP script must be stored in the same directory on the server as
phptext.html):
In phptext.php, you can access the text in the text field named "data" as $_REQUEST["data"].
So here's phptext.php:
<html>
<head>
<title>
Reading data from text fields
</title>
</head>
<body>
<hl>
Reading data from text fields
</hl>
Thanks for answering,
<?php
echo $_REQUEST["data"];
?>
</body>
</html>
All this PHP script, phptext.php, does is to echo the name the user entered into the
data text field. Make sure that phptext.php goes in the same directory as phptext.html on
your server, and give this example a try. When you click the submit button in phptext.
html, you see the results, something like what you see in Figure 5-2, where the user's
name appears.
Note the URL in Figure 5-2: http://localhost/ch05/phptext.php?data=Steve. That URL
includes the data the user entered into the text field, placed there following a question
mark (?). The data sent with the "get" method is always URL-encoded (spaces are replaced
with + signs, different controls name/data pairs are separated with an &), and placed into
the URL.
166 PHP: The Complete Reference
The get method works, but as you can see, it can create less-than-professional results. If
you don't want the user's data to appear in the URL they access the server with, use the
"post" method instead, like this in phptext.html:
<html>
<head>
<title>
Entering data into text fields
</title>
</head>
<body>
<hl>
Entering data into text fields
</hl>
<form method="post" action="phptext.php">
What's your name?
When you use this new version of phptext.html, the user's data is sent in the HTTP
headers that the browser sends to the server, instead of the URL. That results in a cleaner
URL, as you can see in the URL text area in the browser in Figure 5-3. Because posted data is
sent in HTTP headers and not in the URL, data that you send with the post method is
slightly more secure.
Chapter 5: Reading Data in Web Pages 167
Figure 5-3 Reading text from a text field without visible URL-encoding
Excellent, you've been able to read data from a text field. A similar HTML control, text
areas, is coming up next.
<html>
<head>
<title>
Entering data into text areas
</title>
</head>
<body>
<hl>
Entering data into text areas
</hl>
<form method="post" action="phptextarea.php">
Enter the pizza toppings you want: <br>
<br>
cinput type="submit" value="Send">
</form>
</body>
</html>
168 PHP: The Complete Reference
Then it adds a text area like this, where the numbers 1-4 will appear in the text area:
<html>
<head>
<title>
Entering data into text areas
</title>
</head>
<body>
<hl> v ■ >
Entering data into text areas
</hl>
<forra method="post" action="phptextarea.php">
Enter the pizza toppings you want: <br>
<textarea name="data" cols="50" rows="5">
1.
2 .
3 .
4.
</textarea>
<br>
<input type="submit" value="Send">
</form>
</body>
</html>
You can see this page in Figure 5-4, waiting for you to enter your pizza toppings.
So how do you read the data the user entered in this Web page—in the text area named
data from PHP on the server? The data the user entered will be sent to phptextarea.php on
the server, and you can access the text from the text area as $_REQUEST["data"] in that script:
<html>
<head>
<title>
Reading data from text areas
</title> ' *
</head>
<body>
<hl>
Reading data from text areas
</hl>
You ordered a pizza with: <br>
<?php
$text = $ REQUEST["data"];
?>
</body>
</html>
Note that because you're dealing with a text area, multiline text will be filled with
newline characters, \n. When you display that text, the browser is going to ignore the
newlines, so you might replace them with <br> elements instead, like this, where we
display the user's pizza toppings in phptextarea.php:
<html>
<head>
<title>
Reading data from text areas
</title>
</head>
<body>
<hl>
Reading data from text areas
</hl>
You ordered a pizza with: <br>
<?php
$text = $_REQUEST["data"];
echo str_replace("\n", "<br>", $text);
?>
</body>
</htmi>
And you can see the results in Figure 5-5, where the application has not only echoed the
text the user entered, but also preserved the multiline nature of that text. Nice.
170 PHP: The Complete Reference
<html>
<head>
<title>
Entering data into check boxes
</title>
</head>
<body>
<hl>
Entering data into check boxes
</hl>
<form method="post" action="phpcheckbox.php">
Do you want fries with that?
<input name="checkl" types"checkbox" values"yes">
Yes
<input names"check2" type="checkbox" value="no“>
No
<br>
<br>
cinput type="submit" value="Send">
</form>
</body>
</html>
Note that the value of the first check box is "yes" and the value of the second is "no"—
those are the values that will be sent to your script on the server.
Chapter 5: Reading Data in Web Pages 171
And you can see the results in Figure 5-6, where the application is asking the user if they
want fries.
How do you read the data from the check boxes, checkl and check2? You might think
you coukhdo that simply like this, where you simply use expressions like $_
REQUEST["checkl"]:
<html>
<head> f4
<title>
Reading data from check boxes
</title>
</head>
<body>
<hl>
You selected:
<?php
echo $_REQUEST["checkl"], "<br>";
echo $_REQUEST["check2"], "<br>";
?>
</body>
</html>
Unfortunately, that's not right—the user may not have checked a check box, so
attempting to display the data from that check box would give you an error in PHP.
For example, if the user has not check checkl, then echo $_REQUEST["checkl"] will
give you an error (because the array $_REQUEST doesn't have an element with the
index "checkl").
In this case, you have to first check if there is any data waiting for you from a particular
check box before you attempt to display that data. You can check if an array has an element
with a certain index with the isset function, so before echoing $_REQUEST["checkl"], check
if that array element exists with isset($_REQUEST["checkl"]). Here's how that works in
phpcheckbox.php:
<html>
<head>
<title>
Reading data from text fields
</title>
</head>
<body> '
<hl>
Reading data from check boxes
</hl>
You selected:
<?php
if (isset($_REQUEST["checkl"])) {
echo $_REQUEST["checkl"], "<br>";
}
if (isset($_REQUEST["check2"])) {
echo $_REQUEST["check2"], »<br>";
}
?>
</body>
</html>
And you can see the results in Figure 5-7, where you're reading what check boxes the
user selected.
Note that the user could click both check boxes here—which would mean that they both
wanted fries and didn't want fries. A better choice for the controls here are radio buttons,
where only one can be selected at a time, and they're coming up next.
<html>
<head>
<title>
Entering data with radio buttons
</title>
</head>
<body>
<hl>
Entering data with radio buttons
</hl>
<form method="post" action="phpradiobutton.php">
Do you want fries with that?
cinput name="radios" type="radio" value="yes">
Yes
cinput name="radios" type="radio" value="no">
No
<br>
<br>
cinput type="submit" value="Send">
</form>
c/body>
c/html>
You can see this page in Figure 5-8, waiting for your answer.
How do you read data from radio buttons? You can use $_REQUEST like this in
phpradiobutton.php:
<html>
<head>
<title>
Reading data from radio buttons
</title>
</head>
<body> \ ' ‘
<hl>
Reading data from radio buttons
</hl>
You selected
<?php
echo $_REQUEST["radios"];
?>
</body>
</html>
But you'd run into the same problem as with the check boxes—the user may not
have selected either radio button. On the other hand, there will only be one entry in the
$_REQUEST array under the index "radios", so you only need one statement like this in
phpradiobutton.php:
<html>
<head>
<title>
Reading data from radio buttons
</title>
</head>
<body>
<hl>
Reading data from radio buttons
</hl>
You selected
<?php
if (isset($_REQUEST["radios"])) {
echo $ REQUEST["radios"];
}
?>
</body>
</html>
In fact, you can indicate that no radio button was selected if that was the case:
<head>
<title>
Reading data from radio buttons
</title>
</head>
Chapter 5: Reading Data in Web Pages 175
<body>
<hl>
Reading data from radio buttons
</hl>
You selected
<?php
if (isset($_REQUEST["radios"])) {
echo $_REQUEST["radios"];
}
else {
echo "No radio button was selected. <br>";
}
?>
</body>
</html>
You can see the results in Figure 5-9, where the application has accurately determined
which radio button was clicked.
<html>
<head>
<title>
Entering data with list boxes
</title>
</head>
176 PHP: The Complete Reference
<body>
<hl>
Entering data with list boxes
</hl>
Select your favorite ice cream flavors:
<form method="post" action="phplistbox.php">
<select>
</select>
<br>
<br>
<input type="submit" value="Send">
</form>
</body>
</html>
To let the user select multiple ice cream flavors, we're going to make this a multiple
select control, which you do in HTML with the stand-alone attribute multiple in the
<select> element. And here's the trick that will let this multiple-selection control work with
PHP—you give the control the name of an array, not just a name. For example, if this control
were a single-selection control, you might call it "ice_cream"—but because it's a multiple-
selection control, you call it "ice_cream[]", which tips PHP off that this is a control that
allows multiple selections:
<html>
<head>
<title>
Entering data with list boxes
</title>
</head>
<body>
<hl>
Entering data with list boxes
</hl>
Select your favorite ice cream flavors:
<form method="post" action="phplistbox.php">
<select name=" ice cream [] " multiple:*
</select>
<br>
<br>
<input type="submit" value="Send">
</form>
</body>
</html>
Chapter 5: Reading Data in Web Pages 177
Now you re free to add the ice cream flavors as <option> elements inside the <select>
control (the items in <select> controls are given as <option> elements in HTML):
<html> , /
/ - ' '
<head>
<title>
Entering data with list boxes
</title>
</head> < ‘ 4
<body>
<hl>
Entering data with list boxes
</hl>
Select your favorite ice cream flavors:
<form method="post" action="phplistbox.php">
<select name="ice_cream[]" multiple>
<option>vanilla</option>
<option>strawberry</option>
<option>chocolate</option>
<option>herring</option>
</select>
<br>
<br>
<input type="submit" value="Send">
</form>
</body>
</html>
You can see this page in Figure 5-10, waiting for your ice cream selections.
Alright, what about reading the selections the user made? Up until now, you would
have handled their selections like this, simply echoing $_REQUEST["ice_cream"] to
the browser:
<head>
<title>
Reading data from list boxes
</title>
</head>
<body> '
<hl>
Reading data from list boxes
</hl>
Your ice cream flavors:
<BR>
<?php
echo $_REQUEST["ice_cream"];
?>
</body>
</html>
But that won't work here, because ice_cream is an array, not a single variable. So
you might use a foreach loop to display the user's ice cream selections like this in
phplistbox.php:
<head>
<title>
Reading data from list boxes
</title>
</head>
<body>
<hl>
Reading data from list boxes
</hl>
Your ice cream flavors:
<BR>
<?php
foreach($_REQUEST["icecream"] as $flavor){
echo $flavor, "<br>";
}
?>
</body>
</html>
You can see the results in Figure 5-11, where the PHP page has accurately reported the
user's ice cream selections.
Chapter 5: Reading Data in Web Pages 179
<html>
<head>
<title>
Entering data with password controls
</title>
</head>
<body>
<hl>
Entering data with password controls
</hl>
<form method="post" action="phppassword.php">
Enter your password:
<br>
<br>
cinput type="submit" value="Send">
</form>
</body>
</html>
You can see this page in Figure 5-12, where the user has entered their password.
180 PHP: The Complete Reference
You can store the password on the server—which is the charm of using PHP for
password verification. In this case, you check $_REQUEST["password"] against the
password, which is "letmein" in this case, and if it matches, display a welcome page to
the user in phppassword.php:
<head>
<title>
Reading data from password controls
</title>
</head>
<body>
<hl>
Reading data from password controls
</hl>
<?php
if ($_REQUEST["password"] == "letmein"){
?>
<h2>
Password accepted
</h2>
OK, you're in.<br>
Please act responsibly.
?>
</body>
</html>
Chapter 5: Reading Data in Web Pages 181
<head>
<title>
Reading data from password controls
</title>
</'head>
<body>
<hl>
Reading data from password controls
</hl>
<?php
if ($_REQUEST["password"] == "letmein"){
?>
<h2>
Password accepted
</h2 >
OK, you're in.<br>
Please act responsibly.
<?php
}
else {
?>
<h2 >
Password denied
</h2>
182 PHP: The Complete Reference
<html>
<head>
<title>
Storing data with hidden controls
</title>
</head>
<body>
<hl>
Storing data with hidden controls
</hl>
Chapter 5: Reading Data in Web Pages 183
The customer type is not apparent by just looking at the Web page, however, as you can
see in Figure 5-15.
However, you can read the data in the customer_type hidden control in PHP on the
server. That looks like this:
<head>
<title>
Reading data from password controls
</title>
</head>
<body>
<hl>
Reading data from password controls
</hl>
We think you are a
<?php
echo $_REQUEST["customer_type"];
?>
customer.
</body>
</html>
And you can see the result in Figure 5-16—the customer is a good customer.
Hidden controls like this are popular for storing information about the user for use with
PHP—another popular way of storing information about the user is to use cookies, also
coming up in this book.
<html>
<head>
<title>
Entering data with image maps
</title>
</head>
<body>
<hl>
Entering data with image maps
</hl>
<form method="post" action="phpimagemap.php">
Click the image:
<br>
And you can see the image map in Figure 5-17. Note that no Submit button is needed
here—clicking the image itself sends that location of that click in the image to the server.
So how do you handle image clicks in PHP? You might try something like this in
phpimagemap.php—the image map was given the name imap, so you might make a first
attempt by simply using $_REQUEST["imap"]:
<head>
<title>
Reading data from image maps
</title>
</head>
<body>
<hl>
Reading data from image maps
</hl>
You clicked the image map at
<?php
echo $_REQUEST["imap"];
?>
</body>
</html>
However, that's not going to work, because the mouse location in the image map consists
of two coordinates, an x coordinate and a y coordinate. In PHP, those coordinates are stored
under the name of the image map with _x and _y appended. That means you can display the
186 PHP: The Complete Reference
location at which the user clicked the image (in image coordinates, (0, 0) is the upper-left
comer of the image, positive x is to the right, positive y is downward, and all measurements
are in pixels) like this in phpimagemap.php:
<head>
<title>
Reading data from image maps
</title>
</head> _
<body>
<hl>
Reading data from image maps
</hl>
You clicked the image map at location (
<?php
echo $_REQUEST["imapx"], ", ", $_REQUEST["imap_y"];
?>
) .
</body>
</html>
And you can see the result in Figure 5-18—the location at which the user clicked the
image map is displayed.
Tip Image maps are good for all kinds of things in PHP—with them, you can let the user make
selections or jump to other URLs.
<html>
<head>
<title>
Entering data with file uploads
</title>
</head>
<body>
<hl>
Entering data with file uploads
</hl> ►
<form method="post" action="phpimagemap.php"
enctype="multipart/form-data"
action="phpfile.php" methods"post">
To actually upload the file, you use a file upload control, cinput type="file">. In this
case, you might give the upload control the name userfile like this in phpfile.html:
chtml>
<head>
<title>
Entering data with file uploads
</title>
</head>
<body>
<hl>
Entering data with file uploads
</hl>
<form methods"post" action="phpimagemap.php"
enctype="multipart/form-data"
actions"phpfile.php" methods"post">
Upload file: cinput name="userfile" type="file" />
<br>
<br>
cinput type="submit" value="Send File" />
c/form>
c/body>
c/html>
188 PHP: The Complete Reference
Here
are
the
file's
contents.
You can see what this looks like in Figure 5-19, where the user has browsed to the file
to upload. '
Okay, that takes care of the HTML side of things—how about the PHP side? You use the
$_FILES array in PHP to handle uploaded files; here are the array elements that are available:
As you can see, there's a lot of power here. To actually read the uploaded file, we're
going to use come techniques that will be introduced later in this book, under the topic of
file handling.
You start by getting a file handle corresponding to the file. This value corresponds to the
file as far as PHP is concerned, and you get a file handle when you open a file. The file¬
handling functions in PHP often start with "f," and opening a file is no exception—you open
a file with the fopen function. Openihg a file gives you access to the data in that file; the
name of the file to open, as you see in the preceding list, is $_FILES['userfile']['tmp_name']/
so here's how you open the uploaded file—note the final "r" argument, which opens the file
for reading (as opposed to opening it for writing, which would allow you to overwrite the
data in the file): /•*
<html>
<head>
<title>Reading file data</title>
</head>
<body>
<hl>Reading file data</hl>
<br>
The file contained:
<br>
<?php
$handle fopen($_FILES[1userfile' ] [1tmpname '], "r") ;
?>
</body>
</html>
Okay, that's great—now you have opened the uploaded file and have a file handle
corresponding to it. You can now read the data from the file. This example assumes that the
data in the file is text data, and we're going to read strings of text from the file repeatedly
until we've reached the end of the file. You can check when you've reached the end of the
file with the feof function, which returns true when you're at the end of a file and there's no
more data to read.
The way the file-reading process usually works is to use a while loop that keeps looping
while you're not at the end of the file. That looks like this:
<html>
<head>
<title>Reading file data</title>
</head>
<body>
<hl>Reading file data</hl>
<br>
The file contained:
<br>
<?php
$handle = fopen($_FILES[1userfile1][1tmp_name1], "r");
while (!feof($handle)){
} ’
?>
</body>
</html>
190 PHP: The Complete Reference
Each time through the loop, we can read another line of text from the file using the fgets
function, which reads a string from the file:
<html>
<head>
<title>Reading file data</title>
</head>
<body>
<hl>Reading file data</hl>
<br> * • '
The file contained:
<br>
<?php
$handle = fopen($_FILES['userfile1]['tmp_name'], "r");
while (!feof($handle)){
$text = fgets($handle);
}
?>
</body>
</html>
This code reads a line of text from the file and stores it in the variable $text. Now you
can display that line of text in the browser:
<html>
<head>
<title>Reading file data</title>
</head>
<body>
<hl>Reading file data</hl>
<br>
The file contained:
<br>
<?php
$handle = fopen($_FILESt'userfile1]['tmp_name'], "r");
while (!feof($handle)){
$text = fgets($handle);
echo $text, "<br>";
}
?>
</body>
</html>
Okay, that loops over the file's contents, echoing it line by line to the browser. When
you're done with a file, you should close it, and that works like this, where you pass the file
handle to the fclose function:
<html>
<head>
<title>Reading file data</title>
</head>
Chapter 5: Reading Data in Web Pages 191
<body>
<hl>Reading file data</hl>
<br>
The file contained:
<br>
<?php
$handle = fopen($_FILES['userfile']['tmp_name'], "r");
while (!feof($handle)){
$text = fgets($handle);
echo $text, "<br>";
}
fclose($handle);
?>
</body>
</html>
You can see all this at work in Figure 5-20, where the uploaded file's contents are
displayed.
Although this example worked with a text file, you can also upload binary files, of
course. All you have to do is to use the techniques for handling binary files coming up in
the general discussion of file-handling in this book.
So now you've been able to upload files that the user passes to you. Cool.
Handling Buttons
There's still one popular HTML control that we haven't covered—buttons. Although you
often see buttons in Web pages, they are more difficult to work with using server-side
scripts for one reason—they pop back. That is, there's no data that's stored that will be sent
to the server when a Submit button is clicked.
192 PHP: The Complete Reference
So how do you handle buttons in Web pages with PHP? There are a couple of solutions
here, and the remainder of this chapter is dedicated to them—if you have little interest in
buttons in your Web pages, feel free to skip on to the next chapter.
</form>
</body>
</html>
Then you can add, say, three standard HTML buttons to the page:
<html>
<head>
<title>Handling buttons</title>
</head>
<body>
<hl>Handling buttons</Hl>
<form name="forml" action="phpbuttons.php" method="post">
<input type="hidden" name="button">
cinput type="button" value="Button 1" onclick="setbuttonl()">
cinput type="button" value="Button 2" onclick="setbutton2()">
cinput type="button" value="Button 3" onclick="setbutton3()">
</form>
c/body>
c/html>
So how do you store data in the hidden control when the user clicks a button? Since
these are standard HTML buttons, all the action has to take place in the browser_so that
means using a browser-side scripting language like JavaScript; there's no other choice.
Here's how you can store the name of the button that was clicked in the hidden control:
chtml>
chead>
ctitle>Handling buttonsc/title>
cscript language="JavaScript">
function setbuttonl()
Chapter 5: Reading Data in Web Pages 193
{
document.forml.button.value = "button 1"
function setbutton2()
{
document.forml.button.value "button 2"
function setbutton3()
{
document.forml.button.value "button 3"
}
</script>
</head>
<body>
<hl>Handling buttons</Hl>
<form name="forml" action="phpbuttons.php" method="post">
<input type="hidden" name="button">
<input type="button" value="Button 1" onclick="setbuttonl()">
<input type="button" value="Button 2" onclick="setbutton2()">
<input type="button" value="Button 3" onclick="setbutton3()">
</form>
</body>
</html>
After the name of the button has been stored in the hidden field, you can complete the
process by submitting the form from JavaScript:
<html>
<head>
<title>Handling buttons</title>
<script language="JavaScript">
function setbuttonl()
{
document.forml.button.value = "button 1"
forml.submit()
function setbutton2()
{
document.forml.button.value = "button 2"
forml.submit()
}
194 PHP: The Complete Reference
function setbutton3()
{
document.forml.button.value = "button 3"
forml.submit()
}
</script>
</head>
<body>
<hl>Handling buttons</Hl>
<form name="forml" action="phpbuttons.php" methvod=*post">
<input type="hidden" name="button">
cinput type="button" value="Button 1" onclick="setbuttonl()">
cinput type="button" value="Button 2" onclick="setbutton2()">
cinput type="button" value="Button 3" onclick="setbutton3()">
</form>
</body>
</html>
<html>
<head>
<title>
Reading buttons
</title>
</head>
<body>
<hl>Reading buttons</hl>
You clicked
<?php
if (isset($_REQUEST["button"])) {
echo $_REQUEST["button"], "<br>";
}
?>
</body>
</html>
You can see the result in Figure 5-22, where the PHP script has correctly identified the
clicked button.
However, this is a book on PHP, not on JavaScript. Isn't there a better way to handle
buttons in Web pages?
<html>
<head>
<title>Reading submit buttons</title>
</head>
<body>
<hl>Reading submit buttons</hl>
<form name="forml" action="phpsubmit.php" method="post">
196 PHP: The Complete Reference
</form>
’ i 1 *
</form>
</form>
</body>
</html>
Then give each form its own hidden control with the button's name like this in
phpsubmit.html:
<html>
<head>
<title>Reading submit buttons</title>
</head>
<body>
<hl>Reading submit buttons</hl>
<form name="forml" action="phpsubmit.php" method="post">
<input type="hidden" name="button" value="button 1">
<input type="submit" value="Button 1">
</form>
You can see the result in Figure 5-23, where the three apparent "buttons" are really
Submit buttons.
Chapter 5: Reading Data in Web Pages 197
Now all you need to do is to read the value stored in the hidden control in your PHP
script to determine which button was clicked, like this in phpsubmit.php:
<html>
<head>
<title>
Reading submit buttons
</title>
</head>
<body>
<hl>
Reading submit buttons
</hl>
You clicked
<?php
if (isset($_REQUEST["button"] ) ) {
echo $_REQUEST["button"] , "<br>";
}
?>
</body>
</html>
You can see the result in Figure 5-24, where the PHP script has correctly identified the
clicked button. Not bad.
In fact, there's an easier way to use Submit buttons as standard HTML buttons—you
can actually read the values (that is, the captions) of Submit buttons in PHP. So you don't
need any hidden controls to hold the name of each button, like this in phpsubmit2.html:
<html>
<head>
<title>
Using submit buttons with values
</title>
</head>
198 PHP: The Complete Reference
<body>
<hl>
Using submit buttons with values
</hl>
<form name="forml" action="phpsubmit2.php" method="post">
<input type="submit" name="button" value="button 1">
</form>
<html>
<head>
<title>
Reading submit buttons
</title>
</head>
<body>
<hl>
Reading submit buttons
</hl>
Chapter 5: Reading Data in Web Pages 199
You clicked \
<?php
if (isset($_REQUEST["button"])) {
echo $_REQX7EST ["button"] , "<br>";
}
?>
</body>
</html>
And you can see the results from phpsubmit2.php in Figure 5-26, where the correct
button was identified.
In fact, you can make this even simpler—you don t need three separate forms here,
you can use three'different Submit buttons in the same form. That looks like this in
phpsubmit3.html:
<html>
<head>
<title>
Using submit buttons in the same form
</title> v . ,
</head>
<body>
<hl>
Using submit buttons in the same form
</hl>
<form name="forml" action="phpsubmit3.php" method="post">
<input type="submit" name="button" value="button 1">
Then you can simply read the value of the clicked Submit button in phpsubmit3.php:
<html>
<heac^>-. . /
<title>
Reading submit buttons
</title>
</head>
<body> '' -
<hl>
Reading submit buttons
</hl>
You clicked
<?php
if (isset($_REQUEST["button"])) {
echo $_REQUEST["button"], "<br>";
}
?>
</body>
</html>
And you can see the result in Figure 5-28, where phpsubmit3.php did its thing correctly—
determined which button was clicked.
'
/
in'll—...»» !■ i) in i—mwsis^winwiiwuciiiiii).Mt;...i^aiitw«i«cmiwwMwmii—
CHAPTER
PHP Browser-Handling Power
T his chapter gets us into the power of PHP when it comes to working with browsers—
using server variables to gain control of the browser, determining browser type,
reading Web page data using custom arrays, and so on. The preceding chapter got us
started on handling the browser/server connection in PHP, and this chapter takes it from
there, introducing many new and powerful tools.
Also, you're going to see a discussion of how to validate user-supplied data in this
chapter. Knowing how to check and validate data—has the user entered data in a required
field? has the user entered a number where a number is required?—is a big part of creating
Web applications. And how to implement data validation is coming up in this chapter.
<html>
<head>
<title>
Welcome to my script
</title>
</head>
<body>
<hl>Welcome to my script</hl>
<?php
echo "You have accessed ", $_SERVER["PHPSELF"], " on port ",
$ SERVER["SERVERPORT"];
?>
</body>
</html>
203
204 PHP: The Complete Reference
You can see the results of this script in Figure 6-1, where the script has correctly
identified itself.
Chapter 6: PHP Browser-Handling Power 205
'HTTP_ACCEPT_ENCODING' Text in the Accept-Encoding: header from the current request, if there
is one, such as: 'zip'.
'HTTP_ACCEPT_LANGUAGE' Text in the Accept-Language: header from the current request, if there
is one, such as 'en' for English.
'HTTP_CONNECTION' Text in the Connection: header from the current request, if there is
one, such as: 'Keep-Alive'.
'HTTPJHOST' Text in the Host: header from the current request, if there is one.
’HTTP_REFERER' The address of the page (if any) that referred the user agent to the
current page. This is set by the browser.
'HTTP_USER_AGENT' Text in the User-Agent: header from the current request, if there is
one. This is a string denoting the browser that is accessing the page.
One of the most popular HTTP headers for use with PHP is HTTP_USER_AGENT, and
that's coming up next.
<html>
<head>
<title>
Getting the user's browser type
</title>
</head>
<body>
<hl>Getting the user's browser type</hl>
</body>
</html>
When the user clicks the button in Figure 6-2, the browser contacts phpbrowser.php on
the server, sending all the usual HTTP headers—including HTTP_USER_AGENT. The string
returned by $_SERVER["HTTP_USER_AGENT"] will include the text "MSIE" if the user has
MicrosoftTnternet Explorer, and you tan acknowledge that fact with a <marquee> element:
<html>
<head>
<title>Determin^ng Browser Type</title>
</head>
<body>
<hldetermining Browser Type</hl>
<br>
<?php
if(strpos($_SERVER["HTTPUSERAGENT"], "MSIE")){
echo ( "<marqueexhl>You' re using the Internet Explorer</hlx/marquee>") ;
}
?>
</body>
</html>
On the other hand, you can check if the user has Firefox by searching $_SERVER["HTTP_
USER_AGENT"] for "Firefox" this way:
<html>
<head>
<title>Determining Browser Type</title>
</head>
<body>
<hl>Determining Browser Type</hl>
<br>
<?php
if(strpos($_SERVER["HTTP_USER_AGENT" ], "MSIE")){
echo ("<marqueexhl>You' re using the Internet Explorer</hlx/marquee>") ;
?>
</body>
</html>
208 PHP: The Complete Reference
If the user has neither of these two browsers, you can also indicate that fact:
<html>
<head>
<title>Determining Browser Type</title>
</head>
<body>
<hl>Determining Browser Type</hl>
<br> ( • i
<?php
if(strpos($_SERVER["HTTP_USER_AGENT"], "MSIE")){
echo("<marqueexhl>You're using the Internet Explorer</hl></marquee>");
}
elseif (strpos($_SERVER["HTTP_USER_AGENT"], "Firefox")) {
echo("<hl>You are using Firefox</hl>");
}
else {
echo("<hl>You are not using Internet Explorer or Firefox</hl>");
}
?>
</body>
</html>
You can see the results in the Internet Explorer in Figure 6-3, in a scrolling
marquee element.
And you can see the results in Firefox in Figure 6-4.
<html>
<head>
<title>Welcome</title>
</head>
<body>
<hl>Welcome</hl>
Welcome to this application.
</body>
</html>
and hello.html:
<html>
<head>
<title>Hello</title>
</head>
210 PHP: The Complete Reference
<body>
< hi >He 11 o </'111 >
Hello from this application.
</body>
</html>
Here's phpredirect.html, which passes the name of the page to redirect to using the
value—that is, the caption—of the Submit button in two forms, one for welcome.html, and
the other for hello.html:
V 1
<html>
<head>
<title>Redirecting the browser</title>
</head>
<body>
<hl>Redirecting the browser</hl>
The redirection script, phpredirection.php, takes the name of the script to redirect to
from the value of the Submit button that was clicked ($_REQUEST[/button']) like this:
<?php ff- . I
$redirect = "Location: " . $_REQUEST[1 button1 ] . ".html";
?> )■ *
Now the Sredirect variable holds the text for a new redirect header: "Location: welcome,
html or Location: hello.html". You can create the actual HTTP header and send it back to
the browser using the PHP header function like this:
<?php
$redirect = "Location: " . $_REQUEST['button'] . ".html";
echo header($redirect);
?>
You can see this script, phpredirect.php, at work in Figure 6-6, where the person has
clicked the welcome button and so was redirected to welcome.html.
As you can see, you can easily make, the browser do what you want from your PHP
code, making it navigate where you want.
Another use for redirection headers is with image maps, the clickable images discussed in
the preceding chapter. For example, in PHP, you might check if the user clicked a particular
"hotspot" in an image map:
<?php
if($REQUEST["map_x"] > 20 && $REQUEST["map_x"] < 80){
if($REQUEST["map_y"] > 10 && $REQUEST["map_y"] < 40){
i
}
Welcome
Welcome to this application.
And, if the user did indeed click a hotspot, you can make their browser navigate to a
new URL simply by redirecting it like this:
<?php
if($REQUEST["map_x"] > 20 && $REQUEST["map_x"] < 80){
if($REQUEST["map_y"] > 10 && $REQUEST["map_y"] < ' 40){
$redirect = "Location: www.php.net";
echo header($redirect);
Very cool.
<html>
<head>
<title>
Dumping form data
</title>
</head>
<body>
<hl>Dumping form data</hl>
You can see this page, phpform.html, at work in Figure 6-7, where the user has entered
data into the form.
It s easy enough to create a script that will dump all the form data from phpform.html.
You can sfart by looping over all the key/value pairs in the $_REQUEST array:
<html>
<head>
<title> ,, t
Dumping form data
</title>
</head>
<body>
<hl>Dumping form data</hl>
Here is the data from the form:
<br>
<?php
foreach($_REQUEST as $key => $value){
} *
?>
</body>
</html>
If the form data item you're working with is an array—such as the array that holds ice
cream flavors in phpform.html, you can loop over that array, displaying all the elements
in it this way—note that we're checking if the data item is an array with the PHP is_array
function:
<html>
<head>
<title>
Dumping form data
</title>
</head>
<body>
<hl>Dumping form data</hl>
Here is the data from the form:
<br>
<?php
foreach($_REQUEST as $key => $value){
if(isarray($value)){
foreach($value as $item){
echo $key, " => ", $item, "<br>";
}
}
}
?>
</body>
</html>
If the data item from the form is not an array, it's a simple data item, and you can echo it
to the browser like this:
<html>
<head>
<title>
Dumping form data
</title>
</head>
<body>
<hl>Dumping form data</hl>
Here is the data from the form:
<br>
<?php
foreach($_REQUEST as $key => $value){
if(is_array($value)){
foreach($value as $item){
echo $key, " => ", $item, "<br>";
}
}
Chapter 6: PHP Browser-Handling Power 215
else {
echo $key, " => ", $value, "<br>";
}
}
?>
</body>
</html>
Okay, that's the script phpform.php, a general-purpose script for dumping form data. You
can see this script at work, dumping the data passed to it from phpform.html, in Figure 6-8.
You can also tell PHP to group together data into custom arrays with similar syntax. For
example, say that you wanted to group a form's data sent to you into an array named data.
216 PHP: The Complete Reference
You might have a text field that will take the user's name, and whose data you wanted to
refer to as data['n<lme']. You could set up that control in a Web page like this:
chtml>
<head>
<title>
Using custom form arrays
</title>
</head>
<body>
<hl>Using custom form arrays</hl>
Similarly, you might ask the user their favorite ice cream flavor, storing that text in the
array element dataf'flavor'] this way:
<html>
<head>
<title>
Using custom form arrays
</title>
</head>
<body>
<hl>Using custom form arrays</hl>
<html>
<head>
<title>
Using form arrays
</title>
</head>
<body>
<hl>Using form arrays</hl>
Your name is
<?php
$data = $_REQUEST[1 data 1 ] ;
echo $data[1 name 1], "<br>";
?>
And you can see the results in Figure 6-10, where the application was successful in
retrieving the data from a custom array.
<html>
<head>
<title>Using one page to accept and process data</title>
</head>
<body>
<hl>Using one page to accept and process data</hl>
<?php
if(isset($_REQUEST["flavor"])){
?>
<?php
}
?>
</body>
</html>
Chapter 6: PHP Browser-Handling Power 219
If there is data waiting for you, you can display that data like this:
<html>
<head^. , f
<title>Using one page to accept and process data</title>
</head>
<body>
<hl>Using onfe' £>age to accept and process data</hl>
<?php
if(isset($_REQUEST["flavor"] )){
?>
Your favorite ice cream flavor is
<?php
echo $_REQUEST["flavor"] ;
}
?>
</body>
</html>
If, on the other hand, there is no data waiting for you, the user hasn't entered anything
yet, so it's time to ask them for their favorite flavor. That looks like this:
<html>
<head>
<title>Using one page to accept and process data</title>
</head>
<body>
<hl>Using one page to accept and process data</hl>
<?php
if(isset($_REQUEST["flavor"] )){
?>
Your favorite ice cream flavor is
<?php
echo $_REQUEST["flavor"] ;
}
else {
?>
<form method="post" action="phpone.php">
What’s your favorite ice cream flavor?
cinput name="flavor" types"text">
<br>
<br>
<input typessubmit valuesSubmit>
</form>
<?php
}
?>
</body>
</html>
220 PHP: The Complete Reference
You can see this example, phpone.php, in Figure 6-11—there's no data waiting for the
application to display yet, so it displays the welcome page, asking for your favorite flavor.
After you enter a flavor and click the Submit button, the application displays your
selection, as you see in Figure 6-12.
Not bad—you've handled this entire application with one PHP page, no HTML page
needed. The whole application turned on one point: checking to see whether or not some
data was ready for you to read. If that data was ready, it was processed; if not, the welcome
page was displayed, and the data was entered by the user. In this way, you can create entire
Web applications that use only a single PHP page.
if(isset($_REQUEST["welcome_already_seen"] ) ) {
}
else {
show_welcome () ;
If the user has seen the welcome page, they've presumably entered their data (that's
what we're about to check) and you should start processing that data. You can check
whether the entered data is in the format you want with a function named, say, check_data,
which will store any errors found in a global array named $errors_array:
$errors_array = array();
if(isset($_REQUEST["welcome_already_seen"])){
check data();
}
else {
show_welcome();
Now you can check if there were any errors—the $errors_array array will be empty if
not, so you might check on errors this way— show the errors with a function named show_
errors, and then show the welcome page again:
$errors_array = array();
if(isset($_REQUEST["welcome_already_seen"])){
check_data();
if(count($errors_array) != 0){
show errors();
222 PHP: The Complete Reference
}
else {
show_welcome();
}
1\ '
If there were no errors, you can handle the data the user entered in another function,
named, say, handle_data:
v
$errors_array = array();
if(isset($_REQUEST["welcome_already_seen"])){
check_data();
if(count($errors_array) != 0){
show_errors();
show_welcome();
else {
handledata();
}
}
else {
show_welcome();
So the idea is to check the data the user entered in a function named check_data:
function check_data()
The array $errors_array will be filled with any errors by the check_data function, and
the show_errors function will display those errors:
function show_errors()
{
global $errors_array;
foreach ($errors_array as $err){
echo $err, "<br>";
}
}
The show_welcome function depends on what data you want to ask from the user, of
course. This function displays the controls the user should use. One thing that will be the
Chapter 6: PHP Browser-Handling Power 223
same in all cases is that we want to make sure to create the hidden field "welcome_already.
seen" here:
function show_welcdme()
{
echo "<form method='post' action=phpvalidate.php1>";
i ■ *
That's how our example data-validation framework works. Now let's put it to work.
<html>
<head>
<title>
Checking required data
</title>
</head>
<body>
<hl>Checking required data</hl>
<?php
$errors_array = array();
if(isset($_REQUEST["welcome_already_seen"])){
check_data();
if(count($errors_array) != 0){
show_errors();
show_welcome();
}
else {
handle data();
}
else {
show_welcome();
Now you've got to write the functions called by this code. You might start with the
show_welcome page, which displays the welcome page that asks the user for their favorite
224 PHP: The Complete Reference
flavor and sends it back to the same page under the key "flavor"—note that the form doesn't
need an action attribute, because you want the browser to send its data back to the same
PHP page:
function show_welcome()
{
echo "<form method='post'> II /•
echo "What's your favorite ice cream flavor?
echo "<br>";
echo "<input name='flavor' type=1 text'; '
echo "<br>";
echo "<br>";
echo "cinput type=1 submit1 value='Submit'>";
echo "</form>";
}
Also, don't forget to create the hidden field welcome_already_seen here—if this hidden
field exists, the application knows that the user has already seen the welcome page:
function show_welcome()
{
echo "<form method='post1> M /.
echo "What's your favorite ice cream flavor?";
echo "<br>";
echo "<input name =1 flavor' type='text'>" ;
echo "<br>";
tr
echo
A
Next, the check_data function will check if the user has entered anything for their
favorite ice cream flavor. That flavor will be stored in the $_REQUEST array with the key
'flavor', so you might check if the user has left the corresponding text field blank like this
in check_data:
function check_data()
{
if($_REQUEST["flavor"] == "") {
}
}
If the user has not entered any text, you can add an entry to the global $errors_array
array like this—note that this error is going to display its message in red, "Please enter
your flavor":
Chapter 6: PHP Browser-Handling Power 225
function check_data()
{
global $errors_array;
if ($ REQUEST ["flavor"] == " "/) {
$errors_array[] = "<font color='red1>Please enter your flavor</font>";
}
}
The show_errorsl function simply displays the errors in the browser, using the echo
statement. All this function has to do is to loop over the $errors_array array and display
each error:
function show_errors()
{
global $errors_array;
}
}
If everything is okay—if there were no data validation errors—the application will call
the handle_data function, and in this example, that function displays the user's favorite ice
cream flavor:
function handle_data()
{
echo "Your favorite ice cream flavor is ";
echo $_REQUEST["flavor"];
}
You can see this application at work in Figure 6-13, where it's waiting for the user to
enter their favorite ice cream flavor.
If the user doesn't enter anything but just clicks the Submit button, they'll see the error
that appears in Figure 6-14, asking them to enter their flavor.
If the user then enters a flavor and clicks Submit, that flavor is displayed by the application,
as you see in Figure 6-15. Very nice.
Okay, that handles the case where you want to check that the user entered some data.
But there are other things you can check for—for example, whether the user entered a
text string.
Requiring Numbers
How about requiring that the user enter integer data? Here's an example, phprequirednumber
.php, that does that. It starts off with the boilerplate code for validation checking:
<html>
<head>
<title> (,4
Requiring integer input
</title>
</head>
<body>
<hl>Requiring integer input</hl>
<?php
$errors_array = array();
if (isset ($_REQUEST [ "welcoine_already_seen" ] ) ) {
check_data();
if(count($errors_array) »!= 0){
show_errors();
show_welcome();
}
else {
handle_data();
}
}
else {
show_welcome();
}
Okay, now it's time to write the functions called by this code, starting with the show_
welcome function, which asks the user their age, passing that age under the key "number"
back to the server:
function show_welcome()
{
echo "cform method= 1 post1 >11;
echo "Please enter your age as an integer.";
echo "<br>";
echo "cinput name=1 number 1 type=1 text'>";
echo "<br>";
echo "<br>";
echo "<input type='submit' value='Submit'>";
echo "cinput type=hidden name=1welcomealreadyseen'
value='alreadyseen'>";
echo "</form>";
}
228 PHP: The Complete Reference
Next is the check_data function, where you're supposed to check if the age the user
entered is in the correct form. So how do you check if the string $_REQUEST["number"]
holds an integer in string format? One way of checking that is to convert the string into an
integer using the PHP intval function, then convert it back to a string using the strval
function—and then compare that to the original string. If the two strings are equal, the
string represents an integer. Here's what that looks like in code:
function check_data()
{
if(strcmp($_REQUEST["number"], strval(intval($_REQUEST["number"])))) {
}
}
If the strings are equal, strcmp returns 0, which is interpreted as FALSE. On the other
hand, if the strings are not equal, strcmp will return a non-zero result, which is interpreted
as TRUE. If the result is TRUE, you should add a new error to the global array $errors_
array, indicating that the user should enter an integer:
function check_data()
{
global $errors_array;
if(strcmp($_REQUEST["number"], strval(intval($_REQUEST["number"])))) {
$errors_array[] = "<font color=1 red1>Please enter an integer</font>";
}
}
And in the show_errors function, you can display the errors, if there were any:
function show_errors()
{
global $errors_array;
The handle_data function displays the user's age in case the user indeed entered an
integer:
function handle_data()
{
echo "Your age is ";
echo $ REQUEST["number"];
}
Chapter 6: PHP Browser-Handling Power 229
Okay, that's it. You can see this application, phprequirednumber.php, in Figure 6-16.
The user has, unaccountably, decided to enter their age by spelling it out, rather than
entering an integer.
And you can see the results in Figure 6-17—an error was indeed reported.
Fixing the error by actually entering a number gives you the result you see in Figure 6-18—
everything's okay.
Requiring Text
You can also write applications that require the user to enter text, or even specific text. For
example, you may want to ask the user's favorite ice cream flavor—and then make sure they
enter your own favorite flavor, pistachio. You can start this application, phprequiredtext.php,
like this:
<html>
<head>
<title>
Requiring text input
</title>
</head>
<body>
<hl>Requiring text input</hl>
<?php
$errors_array = array();
if(isset($_REQUEST["welcome_already_seen"])){
check_data();
if(count($errors_array) != 0){
show_errors();
show_welcome();
}
else {
handle_data();
}
}
else {
show_welcome();
}
Chapter 6: PHP Browser-Handling Power 231
You can ask the user their favorite flavor this way in the show_welcome function:
function show_welcome()
l* ■ <
echo "<form method=1 post';
echo "What is your favorite ice cream flavor?";
echo "<br>";
And you can make sure the flavor gets sent to the server under the key 'flavor' like this
in show_welcome:
*
On the server, you can check the flavor the user entered in the check_data function. This
function handles text using regular expressions. Regular expressions (the complete specification
is at www.perldoc.com/perl5.6/pod/perlre.html) let you match text in your PHP code. For
example, if you want to insist that the user's text entry includes the word "pistachio", you can
use the PHP preg_match function like this (the "I" here makes the search case-insensitive):
function check_data()
{
global $errors_array;
if(!preg_match(1/pistachio/i1 , $_REQUEST["flavor"] ) ) {
}
}
232 PHP: The Complete Reference
Although this regular expression check was to make sure a particular word appeared in
the user's text entry, you can also use regular expressions to make sure their data entry is in a
particular format-for example, you might want the person to enter a social security number,
with the format xxx-xx-xxxx, where each "x" is a digit. You could do that by matching their
text to the regular expression "\d\d\d-\d\d-\d\d\d\d", where "\d" is the regular-
expression way of specifying a single digit. Or you might want the person to enter a social
security number, with the format xxx-xx-xxxx, where each x is a digit.
If the user's response doesn't include the word "pistachio", you can complain with an
error message like this: '
function check_data()
{
global $errors_array;
if(!preg_match(1/pistachio/i1, $_REQUEST["flavor"])){
$errors_array[] = "<font color='red1>Your favorite flavor should be
\"pistachio\".</font>";
}
}
In the show_errors function, you can show any errors that have been placed into the
global $errors_array array:
function show_errors()
{
global $errors_array;
function handle_data()
{
echo "Your favorite flavor is
echo $_REQUEST["flavor"];
}
You can see this application, phprequiredtext.php, in Figure 6-19. There, the user is
attempting to indicate that their favorite ice cream flavor is strawberry.
You can see the results in Figure 6-20—an error was reported, because their flavor was
not pistachio.
Chapter 6: PHP Browser-Handling Power 233
Entering pistachio as the user's favorite flavor gives you the results you see in Figure 6-21—
everything's okay now.
<html>
<head>
<title>
Persisting user data
</title>
</head>
<body>
<hl>Persisting user data</hl>
<?php
$errors_array = array();
if(isset($_REQUEST["welcome_already_seen"])){
check_data();
if(count($errors_array) != 0){
show_errors();
show_welcome();
} else {
handle_data() ;
}
}
else {
show_welcome();
}
Chapter 6: PHP Browser-Handling Power 235
The show_welcome function has to check if the user already entered data into any
controls, and if so, you can display that data. Here's how that works—you fill the
variables $first_name and $last_name with either what the user has already entered,
or an empty string, /
function show_welcome()
{
$first_nam% = isset($_REQUEST["first"]) ? $ REQUEST["first"] : "";
$last_name = isset($_REQUEST["last"]) ? $_REQUEST["last"] : "";
}
Then when you display the text fields in the welcome page, you can use $first_name
and $last_name as the values of those controls:
function show_welcome()
{
$first_name = isset($_REQUEST["first"]) ? $_REQUEST["first"] : "";
$last_name = isset($_REQUEST["last"]) ? $_REQUEST["last"] :
echo "<form method='post'>";
echo "Enter your first name:
echo "<input name=1 first' type='text' value='", $first name, ";
echo "<br>";
echo "<br>";
echo "Enter your last name:
echo "cinput name='last' type='text' value='", $last_name, ;
echo "<br>";
echo "<br>";
echo "<input type='submit' value='Submit'>";
echo "<input type=hidden name='welcome_already_seen'
value='already_seen'>";
echo "</form>";
}
That'll make what the user has already entered reappear if they have to be notified of an
error. The check_data function checks to see if the user has left any text field blank, and if
so, it generates an error:
function check_data()
{
global $errors_array;
if($_REQUEST["first"] == "") {
$errors_array[] = "<font color='red'>Enter your first name</font>";
}
if($_REQUEST["last"] == "") {
$errors_array[] = "<font color='red1>Enter your last name</font>";
}
}
236 PHP: The Complete Reference
function show_errors()
{
global $errors_array;
And the handle_data function displays the data the user entered:
function handle_data()
{
echo "Here is your first name:
echo $_REQUEST["first"] ;
echo "<br>Here is your first name:
echo $_REQUEST["last"] ;
}
You can see this application in Figure 6-22, where the user has only entered their
first name.
When the user clicks the Submit button, the application indicates their error—and
also redisplays the correctly entered data ("Edward"), saving the user the effort of
retyping that as in Figure 6-23.
<body>
<hl>
Client-side data validation
</hl>
<form name="forml" action="script.php" method="post">
Please enter your birthday (mm/dd/yyyy):
<input type="text" name="date">
<br>
cinput type="submit" value="Submit">
</form>
</body>
Note that this example posts its data to a (non-existent) script named script.php. To
check the user's data before submitting the form, you can connect the form's onsubmit
attribute to a JavaScript function, check_data. If that function returns a value of false, the
form won't be submitted:
<body>
<hl>
Client-side data validation
</hl>
238 PHP: The Complete Reference
You create the JavaScript function check_data like this in fhe page's <head> section,
inside a <script> element:
<head>
<title>
Client-side data validation
</title>
<script language="javascript">
function check_data()
}
</script>
</head>
JavaScript supports regular expressions, so you can create a regular expression to check
for dates using the format dd/mm/yyyy like this:
<head>
<title>
Client-side data validation
</title>
<script language="javascript">
function check_data()
{
var regexp = /A(\d{l,2})\/(\d{l,2})\/(\d{4})$/
}
</script>
</head>
Then you can check the date the user entered against that regular expression like this:
<head>
<title>
Client-side data validation
</title>
Chapter 6: PHP Browser-Handling Power 239
<script language="javascript">
function check_data()
U . /
var regexp = /"(\d{1,2})\/(\d{1,2})\/(\d{4})$/
var result = document.forml.date.value.match(regexp);
'■ 4
}
</script>
</head>
If the result of attempting to match the regular expression to what the user entered was
null, the user did not enter the date in the format you want. You can display an error using
a JavaScript alert box, and return false from the function, which means the form will not be
submitted, giving the user a chance to fix the problem:
<head> »
<title>
Client-side data validation
</title>
<script language="javascript">
function check_data()
{
var regexp = (\d{1,2})\/(\d{1,2})\/(\d{4})$/
var result = document.forml.date.value.match(regexp);
if (result == null) {
alert("Please enter a date in dd/mm/yyyy format.");
document.forml.date.value =
return false;
}
</script>
</head>
If the data is okay, you can submit the form from JavaScript with the JavaScript
submit function:
<head>
<title>
Client-side data validation
</title>
<script language="javascript">
function check_data()
if (result == null) {
alert("Please enter a date in dd/mm/yyyy format.");
document.forml.date.value = "";
return false;
} else {
document.forml.submit();
return true;
}
}
</script>
</head>
And you can see this application, phpclientside.html, in Figure 6-24. There, the user has
entered their birth date in the wrong format.
You can see the results in Figure 6-25—the error is displayed in a JavaScript alert
box. Cool.
<html>
<head>
<title>Handling HTML in user input</title>
</head>
<body>
<Hl>Handling HTML in user input</Hl>
<?php
$errors_array = array();
if(isset($_REQUEST["welcomejalready_seen"])){
check_data ();
if(count($errors_array) != 0){
show_errors();
show_welcome();
}
else {
handle_data();
}
}
else {
show_welcome();
}
function check_data()
{
global $errors_array;
if($_REQUEST["flavor"] == "") {
$errors_array[] = "<font color='red'>Enter your favorite
flavor</font>";
}
}
function show_errors()
{
global $errors_array;
}
}
242 PHP: The Complete Reference
function handle_data()
{
echo "Your favorite flavor is ";
$ok_text = htmlentities($_REQUEST["flavor"]);
echo $ok_text;
}
function show_welcome()
{
echo "<form method='post'; '
echo "What's your favorite ice cream flavor?<br,>" ;
echo "cinput name='flavor' type='text'>"; \
echo "<brxbr>";
echo "<input type='submit' value='Submit’>";
echo "<input type='hidden' name='welcome_already_seen'
VALUE='already_seen'>";
echo "</form>";
}
?>
</body>
</html>
Now the user can enter HTML in their data, as you see in Figure 6-26.
Using the htmlentities function escapes any included HTML, so the text
"<b>strawberry</b>" is converted to "<b>strawberry</b>", and that's what
gets displayed, as you can see in Figure 6-27.
function handle_data()
{
echo "Your name is ";
$ok_text = striptags($_REQUEST["flavor"]);
echo $ok_text;
Using the strip_tags function strips any HTML tags from text—and the result appears
in Figure 6-28.
,
/ . . ..-.-.-.
CHAPTER
....-
Object-Oriented Programming
P HP is not designed to be an object-oriented language from start to finish, but it's
got an incredible number of object-oriented features built into it, including many
that were added in PHP 5. You're going to see those features in this chapter and
the next.
On the other hand, you don't need object-oriented programming (OOP) to create Web
applications in PHP, so don't feel you have to read this material if it doesn't apply to you.
OOP is targeted at larger applications. That's why OOP was created—to let you break up
bigger applications when simply packaging code in functions isn't going to help.
Programming started as a very linear affair—you just wrote your code, line after line.
Then functions were introduced, and that let you break up your code—the code in functions
wouldn't run until called. And that's fine up to a point. But when you get still bigger
applications, you need another solution.
That solution is to use objects. Object-oriented programming might sound daunting if
you've never used it before, but it shouldn't—the whole idea is to make life easier for you.
For example, say that in real life you have all the interconnected parts of a refrigerator in
your kitchen. To refrigerate food, you have to turn on pumps, start fans, circulate the
refrigeration fluid, run the compressor, and so on. That sounds like a lot of work—better to
wrap all that up into an easily conceptualized object—a refrigerator. Now all the internal
workings are hidden from view, and you can think—there's the refrigerator. It refrigerates
food. Easy.
That's the idea behind object-oriented programming. You break your code up into
objects—a database manager, for example, or a screen manager. That's the way
programmers can think of their applications: in terms of objects with specific duties and
responsibilities. All the functions necessary for the internal workings of the object are
wrapped up inside that object, and hidden from exterior view. The data used by the object
is also hidden inside the object, and that's one of the main ways that objects differ from
just using functions—you can wrap not only many functions together into an object, but
also the data those functions use.
So instead of the 200 functions and 500 variables needed to support printing in your
application, you can wrap everything up into an object, named, say, printer. All the
functions and variables are hidden inside that object, not accessible from outside it.
Functions in object-oriented programming are given a new name—methods. And the data
items stored in an object are called properties.
245
246 PHP: The Complete Reference
The printer object might hide nearly all its methods internally, but it will also intentionally
expose some methods for public use, and those methods are the ones that you use to work
with the printer object. For example, the printer object may have a method called print, and
you can pass text to that method to print: printer("This is a test.");.
Okay, let's start getting to the details. To create an object, you first need to create a class.
Classes are to objects what cookie cutters are to cookies—you create objects using classes. In
fact, an object is called an instance of a class. All that's coming up next.
Creating Classes
Everything OOP starts with classes. Classes are the type of objects, ip the same way that
"integer" may be the type of a variable. You have to create the type before you can create
specific objects of that type. That's important to realize—a class is an object's type. And
because you can structure objects as you like, you have to specify their structure when you
create classes. After you've created a class, you can then create objects of that class, as you're
going to see.
The class is the type of the object, and the object is an instance of the class. You normally
create objects using classes, and then use those objects in your code.
Here's an example, a class named Person. In a few pages, we're going to create people
objects from the Person class; the class is the specification of what will be inside those
objects. Here's how you create a class in PHP, with the class keyword:
class Person
{
}
Okay, that creates a class named Person. In PHP, classes are usually given names that
start with a capital letter, and objects are given names that start with a lowercase letter. As
you know, classes can hold data items, called properties, so let's give the person a name,
$name. In the class, you're declaring the properties and methods that will go into the objects
of this class—and that means you use the var statement to declare properties in PHP. Here's
how you add a property named $name to the Person class:
class Person
{
var $name;
You can also add methods (functions in non-OOP speak) to the Person class. For
example, you'll need some way to set the person's name, so you might use a method named
set_name to do that. Here's how you add that method to the Person class—note that it takes
the person's name as an argument named $data:
Chapter 7 Object-Oriented Programming 247
class Person
{
var $name;
' • t
function set_name($data)
{
»• *
}
}
Now you've got to store the name passed to the set_name function in the Sname variable.
You could do that, by accessing Sname as a global variable:
class Person
{
var $name;
>
function set_name($data)
{
global $name;
}
}
Then you can assign the argument passed to set_name, Sdata, to the internally stored
name, Sname, like this:
class Person
{
var $name;
function set_name($data)
{
global $name;
$name = $data;
}
}
That stores the person's name. You'll also need some way to read the person's name, so
you might add another method called get_name:
class Person
{
var $name;
function set_name($data)
{
global $name;
$name = $data;
}
248 PHP: The Complete Reference
function get_name()
}
}
In the get_name method, you can access the internal name, $name, and return it like this:
i • '
class Person
{ •
var $name;
function set_name($data)
{
global $name;
$name = $data;
function get_name()
{
global $name;
return $name;
}
}
That looks good, and it will work, but there's one change to make. You won't normally see
OOP done using the global keyword. Instead, you usually refer to the properties of the class
using the $this keyword. The $this keyword points to the current object. In PHP terms, this:
global $name;
$name = $data;
$this->name = $data;
Note the syntax here—you use $this, followed by the -> operator. In addition, you omit the
$ in front of the property you're referring to, like this: $this->name.
Using this syntax, which is the normal syntax you'll see in PHP OOP programming, you
can write the methods in the Person class like this:
class Person
{
var $name;
function get_name()
{
return $this->name;
Here's one thing to know when talking about creating properties: you can't assign a
property a computed value inside a class. For example, this is okay; it assigns the name
"Ralph" to $name: ' ‘ -
class Person
{
var $name = "Ralph";
function set_name($data)
{
$this->name = $data;
}
P
function get_jiame()
{
return $this->name;
}
}
This means that when you create objects of the Person class, $name will be assigned the
name "Ralph". However, you can't assign anything but a constant value to a property in a
class. For example, you can't even assign the expression "Ralph " . "Kramden", which
concatenates "Ralph " and "Kramden", to the $name property. This won't work:
class Person
{
var $name = "Ralph " . "Kramden"; //NO GOOD.
function set_name($data)
{
$this->name = $data;
function get_name()
{
return $this->name;
}
}
That's one thing to be careful about when creating properties. Are there similar
restrictions on methods? Not really, except that you shouldn't begin the name of a method
with a double underscore (_)—there are a number of built-in methods that start that way,
and you might conflict with them.
Okay, you've now created a PHP class, the Person class. Now it's time to put it to work,
creating some objects.
250 PHP: The Complete Reference
Creating Objects
To create a new object, you use the new operator in PHP. You just need to define your class,
and then you can use the new operator to create an object of that class. Objects are stored as
variables, so the object-creation process using the new operator looks like this:
class Person
{
var $name; ,
function set_name($data)
{ ;
$this->name = $data;
}
function get_name()
{
return $this->name;
}
}
$ralph = new Person;
That's how it works in PHP; you create an object, and then you can call the methods
built into that object using the -> operator. Executing the statement $ralph->set_
name("Ralph”); sets the name stored internally in $ralph to "Ralph".
And you can read that name from the object using the object's get_name method. That
looks like this in phpobject.php, where you can display the object's internal name:
<html>
<head>
<title>
Creating an object
</title>
</head>
<body>
<hl>Creating an object</hl>
<?php
class Person
{
var $name;
Chapter 7: Object-Oriented Programming 251
function set_name($data)
{
$this->name = $data;
>. . /
function get_name()
{
return $this->name;
}
}
You can see the results in Figure 7-1—this example created a class, then created an object
of that class, configured that object by calling its set_name method—and then called get_
name to get the stored name. Not bad.
You saw that, after you create an object, you can access the methods of that object like this:
By default, you can also access the properties inside an object the same way. For
example, you might want to read the name stored internally (as $name) in the $ralph
object, without having to call the get_name method. You can indeed access that property
like this:
<?php
class Person
{
var $name;
function set_name($data)
{
$this->name = $data; < ' 1
function get_name()
{
return $this->name;
}
}
So you can recover the name stored in the using the get_name method:
$ralph->get_name()
$ralph->name
In OOP programming, you usually call a method to get data from an object, you don't
access the object's properties directly. Methods that return the values of properties are called
accessor methods in OOP, and they're popular because they give you control over the way
the internal data in an object is set. For example, someone may pass an empty string to the
set_name method, and in such a case, you may want to set the object's internal name to a
default value instead:
function set_name($data)
{
if($data != ""){
$this->name = $data;
}
else {
$this->name = "Ralph";
}
}
If you just let code outside the object set the value of the $name property directly, you
wouldn't have this kind of control over the acceptable values of the $name property.
Chapter 7: Object-Oriented Programming 253
Okay, you might want to restrict access to an object's internal data and want code to
have to call get_name instead of access the $name property directly But how would you
stop code from accessing that property directly? You can do it.
<?php
class Person
{
var $name;
function set_name($data)
{
$this->name = $data;
}
function get_name()
{
return $this->name;
}
}
$ralph = new Person;
$ralph->set_narae("Ralph");
You can restrict access to the members of a class or object with the PHP access modifiers,
and here they are:
Public Access
Public access is the most unrestricted access of all, and it's the default. You can explicitly
declare properties and methods to be public with the public keyword:
<?php
class Person
{
public $name;
254 PHP: The Complete Reference
{
$this->name = $data;
{
return $this->name;
}
}
This code works, echoing the name stored internally in the object, because that name
has been stored with public access. Now let's restrict access to that name.
Private Access
You can make a class or object member private with the private keyword. When you make a
member private, you can't access it outside the class or object. Here's an example, phpprivate
.php, where the $name property has been made private to the Person class, and we're trying
to access it from outside the $ralph object:
<html>
<head>
<title>
Creating an object
</title>
</head>
<body>
<hl>Creating an object</hl>
<?php
class Person
{
private $name;
function set_name($data)
{
$this->name = $data,-
}
function get_name()
{
return $this->name;
}
Chapter 7: Object-Oriented Programming 255
You can see this'example at work in Figure 7-2—as you can see, you get an error because
the property you're trying to access is private:
The name of your friend is PHP Fatal error: Cannot access private property
Person::$name in C:\Inetpub\wwwroot\ch07\phpprivate.php on line 29
That means you have forced code outside the object to access the name stored in the $ralph
object using the get_name accessor method, instead of directly accessing the $name property:
<?php
class Person
{
private $name;
function get_name()
{
return $this->name;
}
}
<html> '
<head>
<title>
\
Creating an object
</title>
</head>
<body>
<hl>Creating an object</hl>
<?php
class Person
{
var $name;
function set_name($data)
{
$this->name = $data;
}
private function get_name()
{
return $this->name;
}
}
But now this code*isn't going to work, because you're trying to call get_name
outside the object—and the get_name method is private. That means that you can call it
only from code inside the same object. For example, code like this is legal (although not
very useful), because it calls the now-private method get_name from inside the object's
own code:
<?php
class Person
{
var $name;
P
function set_name($data)
{
$this->name = get_name();
{
return $this->name;
}
}
$ralph = new Person;
$ralph->set_name("Ralph");
We'll take a look at the other access modifier, the protected modifier, after talking about
inheritance, coming up in this chapter.
. ... —- ,. - . - . -
{
$this->name = $data;
}
258 PHP: The Complete Reference
In this way, you can initialize the data inside an object before you start working with
that object.
Wouldn't it be convenient if you could both create and initialize an object at the same
time? PHP allows you to do that with constructors, which, as in other languages that support
OOP, are special methods automatically run when an object is created.
Constructors have a special name in PHP— construct; that is, "construct" preceded by
two underscores. Here's an example:
As you see, this constructor takes an argument, $data. You can assign that data to the
internal name stored in the object like this:
function _construct($data)
{
$this->name = $data;
How do you use this constructor? You pass data to the constructor when you use the
new operator to create new objects, and you pass data to the constructor by enclosing that
data in parentheses following the class name. Here's an example, phpconstructor, that
initializes an object with the name "Dan":
<html>
<head>
<title>
Using a constructor
</title>
</head>
<body>
<hl>Using a constructor</hl>
<?php
class Person
{
var $name;
function _construct($data)
{
$this->name = $data;
}
function set_name($data)
{
$this->name = $data;
}
Chapter 7: Object-Oriented Programming 259
function get_name()
{
return $this->name;
,'} ■ I
}
You can see the results in Figure 7-4, where the constructor did indeed initialize
the object.
You can pass as many arguments to constructors as you need—as long as the constructor
is set up to take those arguments:
All PHP classes come with a default constructor that takes no arguments—it's the
default constructor that gets called when you execute code like this:
However, as soon as you create your own constructor, no matter how many arguments it
takes, the default constructor is no longer accessible.
You can also give the constructor the name of the class (as in other languages that
support OOP) instead of_construct, like this for the Person class:
class Person
{
var $name;
function Person($data)
{
$this->name = $data;
} \
function _destruct()
{
}
Here's an example, phpdestructor.php:
<html>
<head>
<title>
Using a destructor
</title>
</head>
<body>
<hl>Using a destructor</hl>
<?php
class Person
{
var $name;
function _construct($data)
{
echo "Constructing ", $data, "...<br>";
Chapter 7: Object-Oriented Programming 261
$this->name = $data;
}
'''’function set_name ($datci)
{
$this->name = $data;
}
/ • *
function get_name()
{
return $this->name;
}
function _destructO
{
echo "Destructing ", $this->name, "...<br>";
}
}
>
You can see the results in Figure 7-5, where the destructor was run when the $dan object
was destroyed when the script ended.
class Person !
{
var $name;
function set_name($data)
{
$this->name = $data;
}
function get_name()
{
return $this->name;
}
}
Now say that you want to create a new class. Friend, that has all the functionality of
the Person class—that is, the set_name and get_name methods—but also supports some
new methods. You can base the Friend class on the Person class with the extends keyword
this way:
Now the Friend class supports the Person methods, set_name and get_name. You can
also add your own methods to the Friend class. If you wanted each Friend object to have
their own personalized messages, you might add a set_message method that lets you set
each object's message, and a speak method that returns that message:
{
var $message;
function setmessage($msg)
{
$this->message = $msg;
}
Chapter 7: Object-Oriented Programming 263
function speak()
{
echo $this->message;
- /
}
Now Friend objects will support the set_name, get_name, set_message, and speak
methods. Here's an example, phpinheritcance.php, which shows this in action:
<html>
<head>
<title>
Inheriting with constructors
</title>
</head>
<body>
<hl>Inheriting with constructors</hl>
<?php
class Person
{
var $name;
function set_name($data)
{
$this->name = $data;
}
function get_name()
{
return $this->name;
}
}
{
var $message;
function set_message($msg)
{
$this->message = $msg;
function speak()
{
echo $this->message;
}
}
You can see the results in Figure 7-6, where the code has used all methods: set_name,
get_name, set_message, and speak.
That's how inheritance works—you base one class on another, and the derived class
inherits functionality from the base class. Inheriting properties and methods from the base
class depends on the access modifiers you've used in the base class. Public members are
visible in the derived class (and everywhere else), but members declared private in the base
class won't be accessible in the derived class.
What if you want a member accessible in the base class—and in the derived class—but
not to code outside the base class and derived classes? For that, you use protected access.
Protected Access
Using the protected keyword makes class members accessible only in the class they're
declared in, and any class derived from that class. For example, you can make the set_name
method protected in the Person class:
<?php
class Person
{
var $name;
function get_name()
{
return $this->name:
. i
)
That means that only code inside Person and classes derived from it can call the set_name
method. For example, this code won't work:
To make set_name accessible to code outside the object, you might create a new
method, set_name_public, which calls set_name internally, like this in the Friend class
in phpprotected.php:
<html>
<head>
<title>
Inheriting with constructors
</citle>
</head>
<body>
<hl>Inheriting with constructors</hl>
<?php
class Person
{
var $name;
{
$this->name = $data;
function get_name()
{
return $this->name;
}
}
{
var $message;
function set_message($msg)
{
$this->message = $msg;
function speak()
{
echo $this->message;
}
266 PHP: The Complete Reference
function set_name_public($name)
{
$this->set_name($name);
}
}
Now this works, because set_name_public has public access—any code can call it.
That's the idea behind the protected access modifier—public access gives all code access to
a member, private restricts access to the current class, and protected restricts access to the
current class and any classes derived from that class.
class Person
{
var $name;
function _construct($data)
{
$this->name = $data;
}
How could you call this constructor from the Friend class, which is based on the Person
class? You can do that like this in the Friend class's constructor—parent::_construct calls
the parent class's (the Friend class's ) constructor:
function _construct($data)
{
parent::_construct($data);
}
And you can pass other data to this constructor as well—data targeted for the Friend
class. You can see how this works in phpinherticonstructor.php:
<html>
<head>
<title>
Inheriting with constructors
</title>
</head>
Chapter 7: Object-Oriented Programming 267
<body>
<hl>Inheriting with constructors</hl>
<?php
drass' Person
{
var $name;
function ,,^construct($data)
{
$this->name = $data;
}
function set_name($data)
{
$this->name = $data;
}
function get_name()
{
return $this->name;
}
}
class Friend extends Person
{
var $message;
compost e <1
function _construct($data, $msg)
{ -to
parent::_construct($data);
$this->message = $msg;
}
a^d C
function speak()
{
echo $this->message;
You can see the results in Figure 7-7, where the Friend constructor passed data back to
the Person constructor.
because you've inherited them from the base class. But what if the base class has methods
that are protected—and you want to make them public by letting any code call them?
Just as you saw with constructors, you can call base class methods by appending "parent::"
in front of the base class method's name. Here's an example, phpbasemethods.php. Here, the
methods get_name and set_name have been made protected in the Person class:
<?php
class Person
{
var $name;
And the friend class has two methods, get_name_public and set_name_public, which
call the protected methods using the parent:: syntax:
<html>
<head>
<title>
Calling base class methods
</title>
</head>
Chapter 7: Object-Oriented Programming 269
<body>
<hl>Calling base class methods</hl>
<?php
class Pferson '
{
var $name;
function set_message($rasg)
{
$this->message = $msg;
}
function speak()
{
echo $this->message;
}
function set_name public($data)
{
parent::set_name($data);
}
function getnamepublic()
{
return parent::getname();
}
}
That's it—the code then creates a friend named Britta and uses get_name_public and
set_name_public to call the protected versions of these methods, which the code does with
the parent:: syntax. You can see the results in Figure 7-8.
NOTE You can also use the parent:: syntax to access base class properties.
What do you do if you've inherited from a class that itself has inherited from another
class? Can you use grandparent:: syntax? No, but you can simply prepend the member you
want to access with the name of the class it's in. That would look like this in this example,
where the member you're looking for is in the Person class:
<?php
class Person
{
var $name;
function speak()
{
echo $this->message;
}
function set_name_public($data)
{
Person::set_name($data);
}
>
function getnamepublic()
{
return Person: :get_naihe () ;
}
}
Overriding Methods
In PHP, as with OOP in many languages, you can override methods. That means that you
can redefine a base class method in a derived class.
Here's an example, phpoverride.php. This example overrides the set_name method in
the Person base class:
<?php
class Person
{
var $name;
function setname($data)
{
$this->name = $data;
}
function get_name()
{
return $this->name;
}
}
272 PHP: The Complete Reference
This method is overridden in the Friend class, simply by redefining it. The overriding
version of this method capitalizes the name before storing it:
<html>
<head>
<title>
Overriding methods
</title>
</head> v • t
<body> i
<hl>
Overriding methods
</hl>
<?php
class Person
{
var $name;
function set_name($data)
{
$this->name = $data;
function get_name()
f
return $this->name;
function speak()
{
echo $this->name, " is speaking<br>";
}
function set_name($data)
{
$this->name = strtoupper($data);
}
}
echo "Creating your new friend...<BR>";
$friend = new Friend;
$friend->set__name ("Susan") ;
$friend->speak();
?>
</body>
</html>
CJiapter 7: Object-Oriented Programming 273
That's it—now when you create a $susan object and give the object a name, that name
is capitalized by the overridden version of the set_name method. You can see the results
in Figure 7-9.
Overloading Methods
Besides overriding methods, you can also overload methods in PHP. Overriding a method
means redefining it, but overloading it means creating an alternate version with a different
argument list. In standard OOP languages, you overload a method by defining a new
version of the method with a different argument list. Here's an example, where you define
two versions of the set _name method, one that takes the person's name, and another that
takes both the person's name and their message:
function set_name($data)
{
$this->name = $data;
}
function set_name($data, $msg)
{
$this->name = $data;
$this->message = $msg;
Now you could call the set_name method with one or two arguments, and the OOP
language would call the correct version of set_name, depending on how many arguments
were passed:
$friend->set_name("Susan");
$friend->set_name("Ted", "Ted here");
In PHP, you implement method overloading with the_call method. In a class, this is
the method that gets called when you call a method that doesn't exist.
How's that again? Say that you have a class that has a_call method, but no set_
name method. When you call the set_name method on objects of that class, what
actually gets called is the _call method. The_call method is passed the name of the
missing method, as well as an array holding the argument list that was passed to that
missing method:
Because the arguments passed to the missing method are passed in an array, you
can implement method overloading using the_call method. For example, if you
wanted to overload the set_name method to be callable as both set_name($name) or
set_name($name, $message), you could leave that method unwritten, and handle it with
a_call method:
}
In the_call method, you could first check if the method called (and not found) was
indeed set_name:
}
}
The set_name method can be called with one or two arguments ($name or $name and
$message), so you can check first if a single argument was passed:
if(count($arguments) == 1){
}
}
}
/ - *
If a single argument was passed, that's the person's name, and you can store it like this:
if(count($arguments) == 1){
$this->name = $arguments[0] ;
}
}
}
On the other hand, if two arguments were passed to the function, those arguments are
$name and Smessage:
{
if($method == "set_name"){
if(count($arguments) == 1){
$this->name = $arguments[0];
}
if(count($arguments) == 2){
$this->name = $arguments[0];
$this->message = $arguments[1];
}
}
}
That's how you handle overloading—calling the same method name with different
numbers of arguments in PHP OOP Now you can call set_name with one or two arguments,
as you see in phpoverload.php:
<html>
<head>
<title>
Overloading methods
</title>
</head>
276 PHP: The Complete Reference
<body>
<hl>
Overloading methods
</hl>
<?php
class Friend
{
var $name;
var $message; v - t
function speak()
function set_message($msg)
{
$this->message = $msg;
{
if($method == "set_name"){
if(count($arguments) == 1){
$this->name = $arguments[0];
if(count($arguments) == 2){
$this->name = $arguments [0] ;
$this->message = $arguments[1];
}
}
}
You can see the results in Figure 7-10, where the code was able to call two different
versions of the overloaded set_name method.
Chapter 7: Object-Oriented Programming 277
Autoloading Classes
If you're going to create lots of classes, or if your class definitions are long ones, you might
want to store them in separate files. You could explicitly include each such file, but there's
an easier way: you can use the_autoload function.
This function is passed the names of any classes that PHP is looking for and can't find in
the current file. That means you can load the missing class using require or include like this,
where the class class_name is in a file class_name.php:
function _autoload($class_name)
{
require $class_name . '.php';
}
Let's see this in action. You've seen examples with the Person class and the Friend class,
so let's put those classes into external files. Here's Person.php (note that the <?php...?>
markup is required):
<?php
class Person
{
var $name;
function set_name($data)
{
$this->name = $data;
}
278 PHP: The Complete Reference
function get_name()
{
return $this->name;
}
}
?>
<?php
class Friend extends Person
{
var $message;
function set_message($msg)
{
$this->message = $msg;
}
function speak()
{
echo $this->message;
}
}
?>
<html>
<head>
<title>
Autoloading classes
</title>
</head>
<body>
<hl>
Autoloading classes
</hl>
<?php
function _autoload($class_name)
{
require $class_name . ■.php1;
}
$tony = new Friend;
$tony->set_name("Tony") ;
$tony->set_message("Hiya from Tony.");
Chapter 7: Object-Oriented Programming 279
You can see the results in Figure 7-11, where the Person and Friend classes were
successfully loaded in as PHP needed them. That's a good technique to know, because as
your classes become longer, you'll probably want to put them in separate files.
M^Mwra[ITlMM>l<>)lll^^««B888i«%S8888t<3g8gmttiS8maiSa3i8Siftwaiia^^
CHAPTER
Advanced Object-Oriented
Programming
T he preceding chapter got the ball rolling with OOP. In this chapter, your guided tour
continues, giving you all you need to become a PHP OOP-meister. Here, you're going
to how to handle static class members, abstraction, interfaces, and reflection—all parts
of any modem OOP-supporting language.
Let's get things started by working with static class members.
<?php
class Math
{
} ’
?>
For example, you might place a method in the Math class named squarer, which
displays the square of numbers you pass to it:
<?php
class Math
{
function squarer($op)
{
echo $op, "<sup>2</sup> = ", $op * $op, "<br>";
}
}
?>
281
282 PHP: The Complete Reference
Now you can create an object of the Math class and use its squarer method to display
the squares of numbers like this in phpmath.php:
<html>
<head>
<title>
Using the Math class
</title>
</head> , • i
<body>
<hl>
Using the Math class
</hl>
<?php
class Math
{
function squarer($op)
{
echo $op, "<sup>2</sup> = ", $op * $op, "<br>";
}
}
echo "Using a Math object...<br>";
$math = new Math();
echo $math->squarer(2);
?>
</body>
</html>
That's fine as far as it goes, but why did you need to create a Math object like this?
The Math class is just a utility class—shouldn't it be possible to just use the methods in
it, like the squarer method, directly? Shouldn't you be able to simply call such methods on
the class, not an object of that class?
<?php
class Math
}
?>
For example, you might start with a static method named say_hi that displays a message:
<?php
class Math
{
public function say_hi()
{
echo "The Math class says ’Hello there’. <br>";
}
}
To make this method static, you have to use the static keyword in front of the
function keyword:
<?php
class Math
{
public static function say_hi()
{
echo "The Math class says ’Hello there’. <br>";
}
}
284 PHP: The Complete Reference
Now you can.access the say_hi method in the Math class—without needing to first
create an object of that class—as Math::say_hi():
<?php
class Math
{
public static function say_hi()
{
echo "The Math class says 'Hello therev<bn>";
}
} •
You can see the results in Figure 8-2, where the call to the static method—also called a
class method—worked.
Note the syntax here: Math::say_hi(). You can't use the -> operator here, as you would
when working with an object, because no object is involved. Instead, you use the double¬
colon operator (::) also called the scope resolution operator (also called, very oddly, the
Paamayim Nekudotayim in PHP—which stands for "double colon" in Hebrew).
Here's another tip: You don't actually have to use the static keyword to make a method
static in PHP. If you use a method in a static way—that is, calling it using the class name
instead of calling it as part of an object—PHP will treat the method as static. So this works—
no static keyword:
<?php
class Math
{
public function say_hi()
{
echo "The Math class says 'Hello there'. <br>";
However, it's a good idea to use the static keyword to keep things straight in your own code.
<?php
class Math
{
static $data;
{
echo "The Math class says ’Hello there'. <br>";
function squarer($op)
}
?>
And you can use the data passed to this method in code inside the method:
<?php
class Math
{
static $data;
function squarer($op)
{
echo $op, "<sup>2</sup> = ", $op * $op, "<br>";
}
?>
286 PHP: The Complete Reference
Here's how to call and pass data to the squarer method in phpstaticmethods.php:
<html>
<head>
<title>
Creating static methods
</title>
</head>
<body>
<hl> '
Creating static methods
</hl>
<?php
class Math
{
static $data;
{
echo "The Math class says ’Hello there’. <br>";
function squarer($op)
{
echo $op, "<sup>2</sup> = ", $op * $op, "<br>";
}
}
echo "Using the Math class...<br>";
Math::say_hi();
Math::squarer(2);
?>
</body>
</html>
You can see the results in Figure 8-3—the squarer method got your data and is
displaying its square.
You can see that you can use static methods with classes—what about static properties?
<?php
class Math
{
public static function set_data($op)
{
Chapter 8: Advanced Object-Oriented Programming 287
}
}
?>
Now say that you want to save the data passed to this static method in a class property.
Turns out that you can do that in PHP, even though no object is involved. You have to declare
the property static this way:
<?php
class Math
{
static $data;
i
}
?>
Now you're free to store data in that property. But how do you refer to that property in
code? You can't use the $this->data syntax, because $this refers to the current object, and
there is no object here. Instead, you have to use the keyword self when working with static
288 PHP: The Complete Reference
properties in static methods. So here's how you can store the data passed to set_data in the
$data property:
<?php
class Math
{
static $data;
}
}
And you can echo the value in that property to prove it's being handled correctly:
<?php
class Math
{
static $data;
}
}
?>
And you can do things like increment the value in $data like this:
<?php
class Math
{
static $data;
self::$data = $op;
}
?>
Chapter 8: Advanced Object-Oriented Programming 289
Here s how you can put the set_data method to work in phpstaticproperty.php, passing
it a value of 5:
<html>
<head>r- • /
<title>
Creating static properties
</title>
</head>
/ • 4
<body>
<hl>
Creating static properties
</hl>
<?php
class Math
{
static $data;
And you can see the results in Figure 8-4, where the static property did its thing.
Can you also use plain variables in static methods? Yes, you can. For example, you can
create a new variable named $item, and assign the value in the $data property to it:
<?php
class Math
{
static $data;
}'
}
?>
<html>
<head>
<title>
Creating static properties
</title>
</head>
<body>
<hl>
Creating static properties
</hl>
<?php
class Math
{
static $data;
}
}
echo "Using the Math class ...<br>";
Math::set_data(5);
?>
</body>
</html>
You can see the results in Figure 8-5, where you were successful in using variables in
static methods.
<?php
class Math
{
static $data;
static $message = "No worries.";
{
echo $op, "<sup>2</sup> = ", $op * $op, "<br>";
}
}
?>
Now you can extend the Math class in a new class, New_Math:
<?php ,
class Math
{
static $data;
static $message = "No worries.";
}
class New Math extends Math
{
} ’
?>
And you can access the Math class's static Smessage property from a method in New_
Math—the show_message method:
<?php
class Math
{
static $data;
static $message = "No worries.";
<html>
<head>
<title>
Chapter 8: Advanced Object-Oriented Programming 293
<body^, r. . !
<hl>
Creating static methods
</hl>
<?php
class Math >‘ *
{
static $message = "No worries.";
You can see the results in Figure 8-6, where the static $message property in the base
class Math was indeed accessible from the static show_message method in the derived
New_Math class. Cool.
<?php
abstract class Novel
{
} '
?>
This class may have a standard method, say get_publisher_info, that returns information
about you, the publisher:
<?php
abstract class Novel
{
function getpublisherinfo()
{
return "SteveCo Publishing <br>";
}
}
?>
In addition, you can support a get_text method, that returns the text of the novel. That's
the method you want the author to implement, so you make this method abstract. To do
that, you don't give it a body, just end its declaration with a semicolon:
Chapter 8: Advanced Object-Oriented Programming 295
<?php
abstract class Novel
{
function get_publisher .info()
• i
return "SteveCo Publishing <br>";
}
The author can't create an object of the Novel class directly—they have to add code to
the get_text method themselves. They might start by creating a new class, My_Novel,
extending your abstract class Novel:
<?php
abstract class Novel
{
function get_publisher_info()
{
return "SteveCo Publishing <br>";
}
abstract function get_text();
}
}
?>
To avoid complaints from PHP, this code has to implement the get_text function, which
might look like this:
<?php
abstract class Novel
{
function get_jpublisher_info ()
{
return "SteveCo Publishing <br>";
}
abstract function get_text();
}
296 PHP: The Complete Reference
{
public function get_text()
{
return "It was a dark and stormy night...";
}
}
?>
Here's phpabstract.php, which creates and uses an object y>£ the My_Novel class:
<html>
<head>
<title>
Creating abstract classes
</title>
</head>
<body>
<hl>
Creating abstract classes
</hl>
<?php
abstract class Novel
{
function get_publisher_info()
{
return "SteveCo Publishing <br>";
}
class My Novel extends Novel
{
public function get_text()
{
return "It was a dark and stormy night...";
}
}
$mynovel = new My NovelO ;
echo "This novel comes from ", $mynovel->get_publisher_info();
echo "The novel says 1", $mynovel->get text(), "'<br>";
?>
</body>
</html>
As you can see in Figure 8-7, the abstract class did its thing—the author needed to
implement the abstract method get_text before creating any objects.
Chapter 8: Advanced Object-Oriented Programming 297
Creating Interfaces
In OOP, interfaces are a little like abstract classes—they specify what methods a class has
to implement. However, interfaces are only specifications for methods; they can't include
any code.
For example, you could have an interface named iDatabase that specifies methods a
database class must implement—get_record and set_record, for example. Any database
class that implemented the iDatabase interface would have to also implement the get_
record and set_record methods.
Like most OOP-supporting languages, PHP doesn't support multiple inheritance—that
is, you can't inherit from multiple classes at the same level, because you can't list multiple
classes with the extends keyword. That is, you can do this:
} *
}
298 PHP: The Complete Reference
Using interfaces is sometimes touted as letting you use multiple inheritance, because
you can implement multiple interfaces at the same time, like this:
}
v ' ‘
However, don't be fooled—this is not multiple inheritance. Interfaces are simply specifications
for methods, and interfaces don't include any code for those methods. Interfaces are useful
when, for example, you want to create dozens of classes and to standardize the methods in
each class. The names and the argument lists for the methods will be the same across all
classes that implement the interface—although the actual code implementations of the
methods may vary by class.
Here's an example, modifying the abstract Novel class you just saw into an interface,
iNovel. To create an interface, you use the interface keyword:
<?php
interface iNovel
}
?>
Then you list the methods you want any class that implements this interface to contain.
Note that as with abstract methods, you don't include any method body. In this case, you
might add two methods to iNovel: get_dedication, which returns the novel's dedication,
and get_text, which returns the movel's text:
<?php
interface iNovel
{
function getdedication();
function get text();
}
?>
To implement this interface in the MyJNovel class, you use the implements keyword:
<?php
interface iNovel
{
function get_dedication();
function get_text();
}
Chapter 8: Advanced Object-Oriented Programming 299
Since you've implemented the iNovel interface, you have to implement every method in
that interface. Here, that's get_dedication and get_text, and that looks like this in My_Novel:
<?php
interface iNovel
{
function get_dedication();
function get_ text();
}
{
return "To my sweetie.";
}
public function get text()
{
return "It was a dark and stormy night...";
}
}
Here's how you can create an object using My_Novel and put it to work:
<html>
<head>
<title>
Using interfaces
</title>
</head>
<body>
<hl>
Using interfaces
</hl>
<?php
interface iNovel
{
function get_dedication();
function get_text();
}
300 PHP: The Complete Reference
{
public function get_dedication()
{
return "To my sweetie.";
}
public function get_text()
{
return "It was a dark and stormy night...
}
} :
You can see the results in Figure 8-8, where the iNovel interface was implemented in the
My_Novel class. Not bad.
Bear in mind that interfaces don't actually do all that much for you—they just let you
specify the methods that implementing classes must implement. And that's fine if you want
to maintain a consistent set of methods across multiple classes.
Want another interface example? Coming up next.
Let s put this to work in a simple example, phpiterator, that creates objects you can use
in foreach loops. The class here is going to be called DataHandler, and to make this a simple
example, it's going to use an array internally, because arrays already support the methods
of the Iterator interface, making our job easier.
First, you create the DataHandler class, implementing the PHP Iterator interface:
<?php
class DataHandler implements Iterator
{
}
?>
This class is going to store an array internally that you pass to its constructor, and let
you iterate over that array. Here's how the constructor stores the array as the private
property $array:
<?php
class DataHandler implements Iterator
{
private $array = array();
{
if (is array($arr)) {
$this->array = $arr;
}
}
}
?>
Now you can use the PHP array functions to write the Iterator methods—that is, to let
you use arrays in foreach statements, arrays already implement those methods, so we'll
302 PHP: The Complete Reference
make use of that fact here. For example, the DataHandler method current will just use the
array method current on the private array Sarray, the key method uses the array method
key on the private array Sarray and so on. Here's how to implement the Iterator methods
in DataHandler:
<?php
class DataHandler implements Iterator
{
private $array = array();
> • ‘
All that remains is to create an object of the DataHandler class, initializing it with an
array, and then use a foreach loop to iterate over that object, which looks like this in
phpiterator.php:
<html>
<head>
<title>
Object iteration
</title>
</head>
Chapter 8: Advanced Object-Oriented Programming 303
<body>
<hl>
Object iteration
</hl>
<?phjf
class DataHandler implements Iterator
{
private $array = array();
i ■ *
public function_construct($arr)
{
if (is_array($arr)) {
$this->array = $arr;
}
}
}
>
}
?>
</body>
</html>
You can see the results in Figure 8-9, where the foreach loop had no trouble with the
DataHandler object. Cool.
Comparing Objects
Comparing two objects in PHP takes a little thought. When using the comparison operator
(==), object variables are compared simply—two objects are equal if they have the same
attributes and values, and are objects of the same class. If you use the identity operator
(===), objects are identical if and only if they refer to the same object.
Here's an example, phpcompare.php, that shows how this works. In this example,
$object_l is an instance of Class_l, $object_la is another instance of Class_l, $object_lcopy
is a copy of $object_l, and $object_2 is an instance of Class_2:
» 1
<html>
<head> \
<title>
Comparing objects
</title>
</head>
<body>
<hl>
Comparing objects
</hl>
<?php
class Class_l
{
public $data;
function _construct($item)
{
$this->data = $item;
}
}
class Class_2
{
public $data;
function _construct($item)
{
$this->data = $item;
}
}
$object_l = new Class_l("a");
$obj ect_lcopy = $object_l;
$object_la = new Class_l("a");
$object_2 = new Class_2("a");
if($object_l == $object_la){
echo 1$object_l == $object_la is TRUE <br>';
Chapter 8: Advanced Object-Oriented Programming 305
else {
?>
</body>
</html>
You can see the results in Figure 8-10, where the various comparisons are working as
they should.
<?php
class Math
{
}
?>
<?php
class Math
{
const pi = 3.14159;
}
?>
Now you can refer to the constant pi in code inside the Math class as self::pi. You use the
constant with self:: rather than $this-> because for class constants, there's no object involved.
Here's how you might display self::pi using a public method, display_pi:
<?php
class Math
{
const pi = 3.14159;
function display__pi ()
{
echo ’Pi from inside the class (self::pi): 1, self::pi , "<br>";
}
}
?>
Can you access pi outside the class? Yes, you can—as Math::pi. Note that it uses the
class name. Math, not an object name:
<?php
class Math
{
const pi = 3.14159;
Chapter 8: Advanced Object-Oriented Programming 307
function display_pi()
{
echo 'Pi from inside the class (self::pi): self::pi , "<br>";
}
} • !
/• *
?>
You can also display pi using objects, if you call the public method display_pi:
<?php
class Math
{
const pi = 3.14159;
function display_pi()
{
echo 'Pi from inside the class (self::pi): ', self::pi , "<br>";
}
}
echo 'Pi from outside the class (Math::pi): ', Math::pi , "<br>";
$object = new MathO ;
$object->display_pi();
■? >
However, you can't access the class constant pi using object expressions like $object::pi
or $object->pi like this in phpconstant.php:
<html>
<head>
<title>
Using class constants
</title>
</head>
<body>
<hl>
Using class constants
</hl>
<?php
class Math
{
const pi = 3.14159;
308 PHP: The Complete Reference
function display_pi()
{
echo 'Pi from inside the class (self::pi): self::pi , "<br>";
}
}
echo 'Pi from outside the class (Math::pi): ', Math::pi , "<br>";
You can see the results in Figure 8-11, where the value of the constant was indeed
displayed.
So class constants are available for use inside the code in a class, and when prefixed
with the class name and the scope resolution operator—but that's it.
<html>
<head>
<title>
Final methods
</tifcle>- /
</head>
<body>
<hl>
/ * 4
Final methods
</hl>
<?php
class Person
{
var $name;
function setname($data)
{
$this->name = $data;
}
function get_name()
{
return $this~>name;
}
}
class Friend extends Person
{
var $name;
function speak()
{
echo $this->name, " is speaking<br>";
}
function set_name($data)
{
$this->name = strtoupper($data);
}
}
echo "Creating your new friend...<BR>";
$friend = new Friend;
$friend->set_name("Susan");
$friend->speak();
?>
</body>
</html>
What if you don't want to allow a method to be overridden? You can do that in PHP, as
with other OOP-supporting languages, with the final keyword. All you have to do is to use
310 PHP: The Complete Reference
this keyword when declaring a method you want to restrict, like this in the Person base
class in phpfinal.php:
class Person
{
var $name;
{
$this->name = $data; ( • '
}
function get_name()
{
return $this->name;
}
}
Marking set_name as final should give us an error; you can see the results in Figure 8-12,
where PHP is informing us that you can't override set_name, because it's final. Cool.
Tip Using the final keyword is a good idea in classes you're going to give to others that they may
inherit from, if you don't want any methods to be overridden.
In fact, you can declare entire classes to be final, which means you can't extend them.
Here's the way that looks:
<html>
<head>
<title>
Final classes
</tifcle;> 1
</head>
<body>
<hl> t.4
Final classes
</hl>
<?php
final class Person
{
var $name;
function set_name($data)
{
$this->name = $data;
}
function getname()
{
return $this->name;
}
}
class Friend extends Person
{
var $name;
function speak()
{
echo $this->name, " is speaking<br>";
}
function set_name($data)
{
$this->name = strtoupper($data);
}
}
echo "Creating your new friend...<BR>";
$friend = new Friend;
$friend->set_name("Susan");
$friend->speak();
?>
</body>
</html>
312 PHP: The Complete Reference
Now that the Person class has been declared final, this code will give you an error,
because it attempts to override that class.
Cloning Objects
When you copy over objects, you have to give the process a little thought. You can use the
clone keyword to make a copy of an object in PHP:
This statement makes a copy of $object_l, $object_copy (if you just used the assignment
operator, =, you'd end up with two variable names that pointed at the same object).
However, there's an issue here: if $object_l has some internal properties that themselves
contain subobjects, the properties of the cloned object will also point to the same subobjects.
And that might not be what you want—you might want the copy of the object to contain
new subobjects. You can make that happen by using the_clone method.
Here's an example to make this clear, phpclone.php. You might have a class, BigClass,
that contains two LittleClass objects:
<?php
class BigClass
{
public $little_l;
public $little_2;
}’
?>
You can add a_clone method to the BigClass class that will expressly clone $little_l:
<?php
class BigClass
{
public $little_l;
public $little_2;
function _clone()
{
$this->little_l = clone $this->little_l;
In LittleClass, you can give each instance a unique number, stored in the $number
property, which is inei^mented each time you create a new LittleClass object:
<?php
class LittleClass
{
static $counter = 0;
public $number;
And you can add a_clone method in LittleClass that will increment $number when a
LittleClass object is cloned:
<?php
class LittleClass
{
static $counter = 0;
public $number;
Now you can create an object of BigClass and then clone it—then take a look at the first
object's properties and the clone's property like this:
<html>
<head>
<title>
314 PHP: The Complete Reference
Cloning objects
</title>
</head>
<body>
<hl>
Cloning objects
</hl>
<?php
class BigClass
{
public $little_l;
public $little_2;
function _clone()
{
$this->little_l = clone $this->little_l
}
}
class LittleClass
{
static $counter = 0;
public $number;
echo "<br><br>";
echo "\$object_2: <br>";
print_r($object_2);
?>
</body>
</html>
Chapter 8: Advanced Object-Oriented Programming 315
You can see the results in Figure 8-13. Note that for $object_l, $little_l's $number = 1,
and $little_2's Snumber = 2. For $object_2, $little_l's $number = 3, while $little_2's Snumber
= 2. That is, $object_l's $little_2 and $object_2's $little_2 point to the same object. On the
other hand, because there was a_clone method that handled $little_l differently, $object_
l's $little_l and $object_2's $little_l point to the different objects. Very nice.
Reflection
Using reflection in OOP means that you can examine your own code at run time. Here's an
example, phpreflection.php, which shows how to get information about a method. The
method in this case is named tracker:
<?php
function tracker()
{
static $counter = 10;
$counter++;
return $counter;
}
?>
To get information about this method, you can use the ReflectionFunction class:
<?php
function tracker()
{
static $counter = 10;
$counter++;
return $counter;
}
316 PHP: The Complete Reference
?>
Now you can use this new object, $method, to find the name of the method it represents,
the lines the method spans in code, what happens when you pass data to the method, what
static properties the method has, and more. Here's what it looks like in phpreflection.php:
v • 1
<html>
<head>
<title>
Reflection
</title>
</head>
<body>
<hl>
Reflection
</hl>
<?php
function tracker()
{
static $counter = 10;
$counter++;
return $counter;
}
$method = new ReflectionFunction(1 tracker 1);
if ($method->getStaticVariables 0){
$statics = $method->getStaticVariables();
echo "It has this static variable; ", var export($statics, 1), "<br>";
}
echo "Invoking the method results in ", vardump($method->invoke()), "<br>";
?>
</body>
</html>
Chapter 8: Advanced Object-Oriented Programming 317
You can see the results in Figure 8-14, where, as you see, there's a lot of information
about the tracker method.
Note You can also perform reflection on classes, objects, properties, and more.
' ' 1
v
’i
iy
'
.
/
CHAPTER
/• *
File Handling
T his chapter discusses file handling using PHP. Storing data on the server is especially
powerful in Web applications, because it allows you to make data "persist"—that is,
stick around between page accesses. Blogs, guest books, feedback pages—all are
possible when you work with files on the server.
There's a lot of PHP technology coming up in this chapter, starting with opening files.
In this function call, filename is the name of the file you're opening, mode indicates how
you want to open the file (for example, to read from it or to write to it), use_includejpath may
be set to 1 or TRUE to specify that you want to search for the file in the PHP include path,
and zcontext holds an optional file context (contexts modify or enhance the behavior of the
data streams from and to files). Here are the possible modes:
319
320 PHP: The Complete Reference
Note that different operating systems have different line-ending conventions. When you
write a text file and want to insert a line break, you need to use the correct line-ending
character(s) for your operating system. Unix-based systems use \n as the line ending
character, Windows-based systems use \r\n as the line ending characters, and Macintosh-
based systems use \r as the line ending character.
In Windows, you can use a text-mode translation flag ('t'), which will translate \n to
\r\n when working with the file. In contrast, you can also use 'b' to force binary mode,
which will not translate your data. To use these flags, specify either 'b' or't' as the last
character of the mode parameter, such as 'wt'. (
Currently, the default mode is set to binary for all platforms that distinguish between
binary and text mode. If you are having problems with your scripts, try using the't' flag.
Here's an example, which opens the file /home/file.txt for reading (you can use
forward slashes like this in path names even in Windows—you can also use backslashes if
you escape them like this: \\):
When you open a file, you get a file handle, which represents an open file. From then on,
you use this handle to work with the file. Now that the file has been opened, you can read
from it using the various data-reading functions we'll cover in a few pages, such as fread.
This example opens a file for writing to:
In Windows, you should be careful to escape any backslashes used in the path to the file
(or use forward slashes):
You re not limited to files in the local file system, either. Here's how you might open
a file on a different Web site, as specified by URL:
When you open a file, you get a file handle to work with, and you can pass that file handle
to other file functions to work with the file.
Here's an example. Say that you have a file, file.txt, with these contents:
Here
is
your
data.
Chapter 9: File Handling 321
<?php
$handle = fopen("file.txt", "r");
y'
?>
4 < •
If the open operation fails, fopen returns FALSE, so you can check if the file was opened
like this in phpfopen.php:
<html>
<head>
<title>
Opening a file
</title>
</head>
<body>
<hl>
Opening a file
</hl>
<?php
$handle = fopen("file.txt", "r");
if($handle){
echo "File opened OK.";
}
?>
</body>
</html>
You can see the results in Figure 9-1, where the file file.txt was opened successfully.
You can open URLs on the Internet with fopen as well; preparing you to read from Web
pages, like this:
Okay, now the file was opened successfully—how do you read the text in it?
<html>
<head>
<title>
Reading from a file
</title>
</head>
<body>
<hl>
Reading from a file
</hl>
<?php
$handle = fopen("file.txt", "r");
while (!feof($handle)){
} '
?>
</body>
</html>
To make this loop active, you have to actually read from the file (otherwise, you'll never
reach the end of the file and this loop will never terminate). And you can do that with the
fgets function.
You pass this function the file handle corresponding to an open file, and an optional length.
The function returns a string of up to length - 1 bytes read from the file corresponding to
Chapter 9: File Handling 323
the file handle. Reading ends when length - 1 bytes have been read, on a newline (which is
included in the return value), or on encountering the end of file, whichever comes first. If no
length is specified, the length defaults to 1024 bytes.
Here s,hovy you might read a line of text from the file, file.txt, if phpread.php:
<?php
$handle = fopen("file.txt", "r");
while (!feof($handle)){
$text = fgets($handle);
}
?>
And you might echo the text that was read, line by line:
<html>
<head>
<title>
Reading from a file
</title>
</head>
<body>
<hl>
Reading from a file
</hl>
<?php
$handle = fopen("file.txt", "r");
while (!feof($handle)){
$text = fgets($handle);
echo $text, "<br>";
}
?>
</body>
</html>
That opens the file and reads from it. There's one more step to take to complete the file¬
reading operation—closing the file.
Closing a File
When you're done with a file, you should close it in PHR Closing the file frees up the
resources connected with that file, and avoids conflicts later in your code in case you
recycle file handle variables.
To close a file, you use fclose like this:
fclose($filehandle) ;
This function returns TRUE if the file was closed successfully, and FALSE otherwise.
324 PHP: The Complete Reference
<html>
<head>
<title>
Reading from a file
</title>
</head>
<body> v • 1
<hl>
Reading from a file
</hl>
<?php
$handle = fopen("file.txt", "r");
while (!feof($handle)){
$text = fgets($handle);
echo $text, "<BR>";
}
fclose($handle);
?>
</body>
</html>
You can see the results in Figure 9-2, where the file file.txt was opened successfully, read
from, and then closed.
That's one way of reading text—line by line. So how about character by character?
Coming up next.
This function returns the character read. It's a useful function for precision control over
reading operations. ( 4
Here's an example, phpfgetc.php. You start by opening the file to read from, file.txt:
<?php
$handle = fopen("file.txt", "r");
?>
<?php
$handle = fopenCfile.txt", "r");
$char = fgetc($handle)
>
?>
To loop over all the characters in the file, you can put the preceding statement in the
condition of a while loop—when fgetc returns FALSE, there are no more characters to read:
<?php
$handle = fopenCfile.txt", "r");
}
?>
<?php
$handle = fopenCfile.txt", "r");
echo "$char";
}
?>
326 PHP: The Complete Reference
You can see the results in Figure 9-3, where the file file.txt was opened and then read
from, character by character.
That's fine as far as it goes, but what about newline characters? The file, file.txt, has
these contents:
Here
is
your
data.
But as you can see in Figure 9-4, the newline characters from the file were simply sent to
the browser, which doesn't display newline characters—you have to convert them to <br>
elements instead. That looks like this in code:
<?php
$handle = fopen("file.txt", "r");
<html>
<head> , /
t '■ •
<title>
Reading characters from a file
</title>
</head>
/• *
<body>
<hl>
Reading characters from a file
</hl>
<?php
$handle = fopen("file.txt", "r");
fclose($handle);
?>
</body>
</html>
You can see the results in Figure 9-4, where the file file.txt was opened, read from
character by character—including proper newline handling—and then closed.
Here, filename is the name of the file, use_include_path is set to TRUE if you want to search
PHP's include path, context is a context for the operation, offset is the offset into the file at
which to start reading, and maxlen is the maximum length of data to read.
Here's an example, phpfilegetcontents.php. This example starts by reading the entire
contents of the file file.txt into the variable $text:
<?php
$text = file_get_contentsCfile.txt");
?>
Then the code converts all newlines into <br> elements using the PHP function str_
replace:
<?php
$text = file_get_contentsCfile.txt");
?>
Finally, the converted text is echoed to the browser this way in phpfilegetcontents.php:
<html>
<head>
<title>
Reading a whole file at once
</title>
</head>
<body>
<hl>
Reading a whole file at once
</hl>
<?php
$text = file_get_contentsCfile.txt");
echo $fixed_text;
?>
</body>
</html> /
/'■ 1
You can see the results in Figure 9-5, where the file file.txt was opened, read from
entirely, and then displayed.
Want to read a Web joage all at once? Just open it up and read it, as here, where we're
reading the PHP home page:
<html>
<head>
<title>
Reading a whole file at once
</title>
</head>
<body>
<hl> (
Reading a whole file at once
</hl>
<?php
$text = filegetcontents("http://www.php.net");
echo $fixed_text;
?>
</body>
</html>
In this case, filename is the name of the file you want to read, usejncludejpath should be set
to TRUE if you want to search the PHP include path for the file, and context is a context for
the operation. This function returns an array or FALSE if the 'Operation failed.
This function is extremely useful if you want to write your own database files. For
example, suppose you wanted to keep students' scores in a database file—and you could
read all those scores into an array with a single statement.
Here's an example, phpfarray.php, which reads file.txt into an array, $data. First, you
can load the contents of that file into the array:
<?php
$data = file('file.txt');
?>
That's it—now you've been able to read an entire file into the $data array. Now each line in
file.txt is an element in the $data array.
You can display the data now in the array with a foreach loop:
<?php
$data = file('file.txt');
?>
i
And all you've got to do is to display each line:
<?php
$data = file(1 file.txt');
In fact, you can do more than that—you can also display line numbers. Here's how that
works in phpfarray.php:
Chapter 9: File Handling 331
<html>
<head>
<title>
Reading a file into an array
</tiJf>le>. /
</head>
<body>
<hl>
Reading a file into an array
</hl>
<?php
$data = file('file.txt');
And you can see the result in Figure 9-6, where the entire file, file.txt, was read into an
array and displayed.
You can also open Web pages and read them into arrays using the file function. Here's
an example, phpurlarray.php, which reads http://www.php.net in and displays it:
<html>
<head>
<title>
Reading a Web page into an array
</title>
</head>
<body>
<hl>
Reading a Web page into an array
</hl>
<?php
$data = file('http;//www.php.net1);
You can see part of the result in Figure 9-7, where the URL was read in and its HTML
displayed, line by line.
Here's one thing to note: each element in the array still has a newline character at the end
of it. If you want to get rid of that newline character, you can use the rtrim PHP function.
file_exists (filename )
You pass this function a filename (which can include a path), and it returns TRUE if the file
exists, FALSE otherwise.
Chapter 9: File Handling 333
<?php
ilename = "does_not_ekist.txt";
?>
/• -
<?php
$filename = "does_not_exist.txt";
if (file_exists($filename)) {
>
9 >
If the file exists, you can read it in and display its contents:
<?php
$filename = "does_not_exist.txt";
if (file_exists($filename)) {
$data = file($filename);
?>
If the file doesn't exist, you can display a message to that effect—which beats an error
message from PHP:
<html>
<head>
<title>
Checking if a file exists
</title>
</head>
334 PHP: The Complete Reference
<body>
<hl>
Checking if a file exists
</hl>
<?php
$filename = "does_not_exist.txt";
if (file_exists($filename)) {
$data = file($filename);
else {
echo "The file $filename does not exist";
}
?>
</body>
</html>
You can see the result in Figure 9-8, where this example determined that the file didn't
exist before trying to open it, and so didn't generate an error.
filesize (filename )
You just pass the filename (including path if you want to add that) to filesize and you'll get
an integer back or FALSE if the file doesn't exist.
Chapter 9: File Handling 335
Local intranet
<html>
<head>
<title>
Getting file size
</title>
</head>
<body>
<hl>
Getting file size
</hl>
<?php
echo "The file file.txt is ", filesize("file.txt"), " bytes long.";
?>
</body>
</html>
You can see the result in Figure 9-9, where this example determined the file was
24 bytes long.
You ve seen a lot about how to handle text files—how about binary files?
This function reads up to length bytes from the file referenced by handle. Reading stops
when length bytes have been read, of the EOF (end of file) is reached.
336 PHP: The Complete Reference V
On systems like Windows, you should open files for binary reading, mode 'rb', to work
with fread. Since adding 'b’ to the mode does no harm on other systems, we'll include it
here for portability. Here's an example, phpfread.php, which treats file.txt as a binary file.
This example starts by opening file.txt for binary reading:
<?php
$handle = fopen("file.txt", "rb");
You can use filesize to determine the file's size, and read it all into a variable, $text,
using fread:
<?php
$handle = fopen("file.txt", "rb");
?>
<?php
$handle = fopenOfile.txt", "rb");
<?php
$handle = fopen("file.txt", "rb");
echo $fixed_text;
?>
Chapter 9: File Handling 337
<html>
<head>
<titvlre> • /
Reading binary data
</title>
</head>
<body>
,. *
<hl>
Reading binary data
</hl>
<?php
$handle = fopen("file.txt", "rb");
echo $fixed_text;
fclose($handle);
?>
</body>
</html>
You can see the result in Figure 9-10, where this example read file.txt in using a binary
read operation.
This function takes a file handle, and a format string of the same type you'd use with sprintf.
Here's an example, phpfscaf.php, which reads this file, actors.txt, where the actors' first
and last names are separated by tabs:
i ■ *
Cary Grant
Myrna Loy
Jimmy Stewart
June Allyson
<?php
$handle = fopen("actors.txt", "r");
?>
The format in this case is "%s\t%s\n" (string, tab, string, newline character), so here's
how you read and parse a line of data from a file into an array named $name in a while loop:
<?php
$handle = fopenCactors.txt", "r");
}
?>
Next, you assign the values in the $name array to the variables $firstname and $lastname,
and then display those names:
<html>
<head>
<title>
Parsing files
</title>
</head>
<body>
<hl>
Parsing files
</hl>
<?php
$handle = fopenCactors.txt", "r");
Chapter 9: File Handling 339
fclose($handle);
?>
</body>
</html>
You can see the result in Figure 9-11, where the file actors.txt was parsed and the data in
it displayed.
This function loads in the ini file filename and returns the settings in it in an associative array.
By setting the last process_sections parameter to TRUE, you get a multidimensional array,
with the section names and settings included. The default for process_sections is FALSE.
Note that this function is not for use with the initialization file that PHP itself uses—
php.ini. That file is parsed and read before PHP even starts.
CAUTION There are reserved words that must not be used as keys for ini files. These include: null,
yes, no, true, and false. Values null, no, and false results in yes and true results in "1".
Characters I} \ &-![()" must not be used anywhere in the key.
340 PHP: The Complete Reference
For example, here's a sample .ini file, sample.ini (note that you can start comments with
semicolons in .ini files):
[first_section]
first_color = red
second_color = white
third_color = blue
V ■ ‘
[second_section]
file = "/usr/local/code.data"
URL = "http://www.php.net"
Here's an example showing how to read sample.ini, phpparseinifile.php. You can read
the contents of sample.ini into an array, $array:
<?php
$array = parseinifile("sample.ini");
?>
Now you can recover the values in the .ini file using the $array array. For example, you
can recover the value under the key first_color (which is "red") like this: $array["first_
color"]. In this example, you can loop over the array, displaying the keys and their values:
<html>
<head>
<title>
Parsing .ini files
</title>
</head>
<body>
<hl>
Parsing .ini files
</hl>
<?php
$array = parse_ini_file("sample.ini");
You can see the result in Figure 9-12, where the data in sample.ini was read in
and displayed.
Chapter 9: File Handling 341
stat (filename )
The function returns an array containing information that mostly makes sense on
Unix machines. Here is the data stored in the returned array with these numerical indexes
(you can also use the text keys given here in parentheses):
Most of these items only have meaning in Unix; if there are no counterparts in Windows,
you'll get a value of -1.
342 PHP: The Complete Reference
Here's an example putting this to work, phpstat.php, which reports the size of the file
file.txt. This example begins by using stat on file.txt:
<?php
$array = stat("file.txt");
?>
And you can find the file file.txt size and display it this Way:'
<html> ;
<head>
<title>
Using stat
</title>
</head>
<body>
<hl>
Using stat
</hl>
<?php
$array = stat("file.txt");
You can see the result in Figure 9-13, where the file's size appears.
Here, handle is the handle of the file to set the file pointer in, offset is the number of bytes
you want to set the pointer to, and start_point indicates a starting point for the pointer,
which is one of these constants:
Here, source is the name of the source file, and destination is the name of the copy (including
pathnames, if applicable). This function returns TRUE if it was successful, FALSE otherwise.
Here's an example, phpcopy.php. This example is going to make a copy of file.txt,
copy.txt:
<?php
$file = ‘file.txt1;
$copy = ‘copy.txt1;
Here's where we try to make the copy, and report success if it worked:
<?php
$file = 'file.txt';
$copy = 'copy.txt';
if (copy($file, $copy)) {
echo "Copied $file.";
}
344 PHP: The Complete Reference \
If the copy operation failed, we can report that failure this way in phpcopy.php:
<html>
<head>
<title>
Copying files
</title>
</head>
<body>
<hl> '
Copying files
</hl>
<?php
$file = 'file.txt';
$copy = 'copy.txt';
if (copy($file, $copy)) {
echo "Copied $file.";
}
else {
echo "Could not copy $file.";
}
?>
</body>
</html>
You can see the result in Figure 9-14, where the file was copied, as planned.
Note If you just want to move a file, use the rename function instead.
Here, filename is the name of the file, and context is an optional context. This function returns
TRUE if the file was deleted, FALSE otherwise.
You can find an example in phpunlink.php. If the code is successful in deleting copy.txt,
it says so:
<?php
if(unlink("copy.txt") ) {
echo "Deleted the file.
}
?>
>
And if the file couldn't be deleted, this example, phpunlink.php, also indicates that:
<html>
<head>
<title>
Deleting files
</title>
</head>
<body>
<hl>
Deleting files
</hl>
<?php
if(unlink("copy.txt")){
echo "Deleted the file.";
}
else {
echo "Could not delete the file.";
}
?>
</body>
</html>
You can see the result in Figure 9-15, where the file was deleted.
346 PHP: The Complete Reference
You pass fwrite a file handle, the string to write, and, optionally, the maximum length of data
to write. This function returns the number of bytes written, or FALSE if there was an error.
Note that to set up your system to write files may take a little work, because of the file
system protections involved. For example, in Windows, you have to right-click the folder
where you want to write files, select Properties, click the Web Sharing tab, select the Share
The Folder radio button, and enable writing. In Unix, make sure you have writing
privileges in the folder you're writing to.
Here's an example, phpfwrite.php, which will write text to a file, data.txt. You start by
opening the file for writing:
<?php
$handle = fopen("data.txt", "w");
?>
Then you can create the text string to write to the file, Stext. Note that if you want
multiline text, you're responsible for adding the newline characters yourself:
<?php
$handle = fopen("data.txt", "w");
Chapter 9: File Handling 347
$text = "Here\nis\nthe\ntext.";
<?php
$handle =» fopenCdata.txt", "w");
$text = "Here\nis\nthe\ntext.";
fwrite($handle, $text);
?>
To make this better, you can check whether the write operation failed, like this in
phpfwrite.php:
<?php
$handle = fopenCdata.txt", "w");
$text = "Here\nis\nthe\ntext.";
If the operation was successful, you can indicate that to the user like this:
<html>
<head>
<title>
Writing files
</title>
</head>
<body>
<hl>
Writing files
</hl>
<?php
$handle = fopenCdata.txt", "w");
$text = "Here\nis\nthe\ntext.";
fclose($handle);
?>
</body>
</html>
You can see the result in Figure 9-16, where the file was written. Nice.
Here's the contents of data.txt:
Here
is
the
text.
Tip Want to check if a file is writable before trying to write to it? Call isjwritable, passing it the
filename; this function will return TRUE if you can write to the file, FALSE otherwise.
<?php
$number = 512;
$handle = fopen ("data.dat", "wb");
Chapter 9: File Handling 349
Next, it packs the data into long integer format like this:
Here ^re the formats for the pack/function, such as "L" for long integer:
• a NUL-padded string
• A SPACE-padded string
• h Hex string,'low nibble first
• H Hex string, high nibble first
• c Signed char
• C Unsigned char
• s Signed short (always 16 bit, machine byte order)
• S Unsigned short (always 16 bit, machine byte order)
• n Unsigned short (always 16 bit, big endian byte order)
• v Unsigned short (always 16 bit, little endian byte order)
• i Signed integer (machine-dependent size and byte order)
• I Unsigned integer (machine-dependent size and byte order)
• 1 Signed long (always 32 bit, machine byte order)
• L Unsigned long (always 32 bit, machine byte order)
• N Unsigned long (always 32 bit, big endian byte order)
• V Unsigned long (always 32 bit, little endian byte order)
• f Float (machine-dependent size and representation)
• d Double (machine-dependent size and representation)
• x NUL byte
• X Back up one byte
• @ NUL-fill to absolute position
<?php
$number = 512;
$handle = fopen ("data.dat", "wb");
if (fwrite ($handle, pack ("L", $number)) == FALSE) {
350 PHP: The Complete Reference
And finally, this code indicates success or failure to the user like this in
phpwritebinary.php:
<html>
<head>
<title>
Writing binary files
</title>
</head>
<body>
<hl> '
Writing binary files
</hl>
<?php
$number = 512;
$handle = fopen ("data.dat", "wb");
if (fwrite ($handle, pack ("L", $number)) == FALSE) {
echo "Can not write data.dat.";
}
else {
echo "Created data.dat. and stored $number.";
}
fclose ($handle);
?>
</body>
</html>
You can see the result in Figure 9-17, where the binary file was written to.
To read the binary data from the file, you can use the unpack function in phpbinaryread
.php. First, you open the file for binary reading:
<?php
$handle = fopen ("data.dat", "rb");
Then use fread to read the binary data, indicating that you want four bytes (the length
of a long integer):
<?php
$handle = fopen ("data.dat", "rb");
$data = fread ($handle, 4);
Then you can use unpack to unpack the data into an array with an element under the
index "data" containing a long value:
<?php
$handle = fopen ("data.dat", "rb");
$data = fread ($handle, 4);
$array = unpack ("Ldata", $data);
Now you can recover the binary data from the array using the key "data":
<?php
$handle = fopen ("data.dat", "rb");
$data = fread ($handle, 4);
$array = unpack ("Ldata", $data);
$data = $array["data"];
■p >
<html>
<head>
<title>
Reading binary files
</title>
</head>
352 PHP: The Complete Reference
v ' 1
<body>
<hl>
Reading binary files
</hl>
<?php
$handle = fopen ("data.dat", "rb");
$data = fread ($handle, 4);
$array = unpack ("Ldata", $data);
$data = $array["data"];
echo "Read this value from data.dat: ", $data;
?>
</body>
</html>
You can see the result in Figure 9-18, where the binary data was read from the file data,
dat successfully.
<?php
$handle = fopen("data.txt", "a");
?>
Chapter 9: File Handling 353
And you put together the text to append to the file, which is
Here
is
more • I
text.
<?php '' *
$handle = fopen("data.txt", "a");
$text = "\nHere\nis\nmore\ntext.
?>
Now you use fwrite to append to data.txt—and let the user know if the operation failed:
<?php
$handle = fopenOdata.txt", "a");
$text = "\nHere\nis\nmore\ntext.";
>
On the other hand, if the append operation was successful, you can let the user know
that like this in phpappend.php:
<html>
<head>
<title>
Appending to files
</title>
</head>
<body>
<hl>
Appending to files
</hl>
<?php
$handle = fopenOdata.txt", "a");
$text = "\nHere\nis\nmore\ntext.";
354 PHP: The Complete Reference
}
else {
echo "Appended to data.txt.";
}
fclose($handle);
?>
</body>
</html> * • •
You can see the result in Figure 9-19, where the file was appended to.
Here are the new contents of data.txt:
Here
is
the
text.
Here
is
more
text.
Cool.
Tip Want to do the opposite, and truncate a file? Use/truncate, specifying the new size of the file:
In this case, filename is the name of the file you want to write, data is the string text to write,
flags can be either FILEjUSE_INCLUDE_PATH and/or FILE_APPEND, and context is a file
context. The function returns the number of bytes that were written to the file, or FALSE if it
couldn't write to the file.
Using this function is much the same as calling fopen, fwrite, and fclose automatically—
you don't have to open or close the file yourself, and you don't need a file handle. Here's an
example, phpfileputcontents.php. You start with the text to write to the file:
<?php
$text = "Here\nis\nthe\ntext.";
?>
<?php
$text = "Here\nis\nthe\ntext.";
file_put_contents("data.txt" , $text);
?>
You can improve on this as you've seen before by checking the return value from the
function. If there was a problem, you can let the user know:
<?php
$text = "Here\nis\nthe\ntext.";
?>
356 PHP: The Complete Reference
Otherwise, you can let the user know that the operation was a success like this in
phpfileputcontents.php:
<html>
<head>
<title>
Writing files with file_put_contents
</title>
</head>
<body>
<hl> ' ' '
Writing files with file_put_contents
</hl>
<?php
$text = "Here\nis\nthe\ntext.";
}
?>
</body>
</html>
Note that you don't need to close the file (or open it, for that matter). You can see the
result in Figure 9-20, where the file was created.
Locking Files
In a multiuser environment, such as a Web server, multiple users may be accessing your
scripts at the same time which meaps multiple copies of the same script can operate at
the same time. If your script(s) accesses files, there may be a conflict as two scripts, or two
copies of the same script, tries to write to the same file at the same time. To fix that, use the
file locking function, flock:
Here, handle is the handle of the file you want to lock, and operation is one of these:
And the optional third argument is set to TRUE if the lock would block.
This function returns TRUE if it got a lock, FALSE otherwise.
You get a lock on files in an advisory way—all your file-accessing code must see if it
can get a lock on a file before accessing that file. If your code can't get a lock on a file, some
other code is using the file, and your present code should wait. Locks are advisory (except
under Windows, where they are mandatory), which means that other code can work with
locked files—and possibly mess things up—so you must be sure to try to get a lock before
writing to a file. When you're done, unlock the file, giving other code access to it.
The flock function normally blocks (that is, doesn't return) until a lock can be secured.
If you don't want to wait—and possibly hang your code—OR the constant LOCK_NB to
the operation, such as: LOCK_EX | LOCK_NB. That will make the flock function return
immediately, and if you didn't get a lock, you can wait a second (with the PHP sleep
function like this: sleep(l), which makes the code pause for a second) and try again, timing
out after, say, fifteen attempts.
Here's an example, phpflock.php, which locks the file data.txt before writing to it. You
can open the file and attempt to get a lock like this:
<?php
$handle = fopen("data.txt", "w");
$text = "Here\nis\nthe\ntext.11;
If you got the lock, you can write to the file and then unlock it:
<?php
$handle = fopenCdata.txt", "w");
358 PHP: The Complete Reference
$text = "Here\nis\nthe\ntext."; \
}
else {
echo "Created data.txt. <br>";
}
flock($handle, LOCKUN); ' ' ‘
echo "Unlocked the file. <br>";
}
?>
This code only tries to lock the file once, and immediately shows an error if it can't, but
you could loop over fifteen or twenty seconds, trying continuously to lock the file until you
gave up.
If you couldn't get the lock, other code is using the file, and you should let the user
know like this in phpflock.php:
<html>
<head>
<title>
Locking and unlocking files
</title>
</head>
<body>
<hl>
Locking and unlocking files
</hl>
<?php
$handle = fopenCdata.txt", "w");
$text = "Here\nis\nthe\ntext.";
fclose($handle);
?>
</body>
</html>
- I
That's it; you can see the result in Figure 9-21, where the file was locked, written to, and
unlocked. Very cool.
Just bear in mind that if you can't get a lock on a file, most likely some other code is
using that file, and you<6hould try again later.
361
362 PHP: The Complete Reference
What Is a Database?
So, just what is a database? We'll take a look at what makes a database here briefly
(and if you are already familiar with databases, tables, and so on, you can naturally
skip this intro).
Databases organize data for easy access and use by programs. The most popular
database construct is the table, and we'll take a look at tables here. Say, for example, that
you're teaching PHP to a class of students and want to keep track of their scores. You
might create a table with two columns. Name and Grade: ^ , ,
Name Grade |
You can store the name of the first student in the Name column, like this:
Name Grade
Ann
This creates a table entry for Ann—that is, a new row. Each row in a database table is
a record, and this record is for the student named Ann. Each column in a record is called a
field, and you've given the Name field the value "Ann". Similarly, you can give Ann a grade
in the Grade field:
Name Grade
Ann C
Name Grade
Ann C
Mark B
Ed A
Frank A
Ted A
Mabel B
Ralph B
Tom B
What, then, is a database? In its most conventional form, a database is just a collection of
one or more tables. And to access the data in those tables, you use SQL in PHP, which is
coming up in the next topic.
For example, say that you had a database table named fruit, and you wanted to recover
the records from that table. Here's what might be in that table at present:
Name Number
apples '' 1020
oranges 3329
bananas 8582
pears 235
i-*
To work with this table in your code, you can execute an SQL statement, called an
SQL query, on the table. This query will return all the records in the table:
Executing this query gives you a record set containing all matching records from the fruit
table. Because you specified that you wanted to match the wildcard * here, all records in the
fruit table are returned by this query. In PHP, that record set is returned as an array, and you
can loop over that array in ways you're going to see in this chapter.
How's this look in PHP? How do you actually execute an SQL query in PHP? To interact
with MySQL, you'd use the mysql_query function to execute that SQL query, something
like this, which returns the entire fruit table and stores it in $result:
Now Sresult holds an array with the records for the fruit table, and you can access the fields
in each record by name.
How about some more SQL? You can also select specific fields from a table like this,
where we're selecting the name and number fields from the fruit table:
Using the WHERE clause, you can set up selection criteria that the records in the record
set generated by the query must meet. For example, to select all the records in the fruit table
where the name field equals apples, you can execute this statement: SELECT * FROM fruit
WHERE name= "apples".
You don't have to use an equal sign here; you can test fields using these operators:
You can use an IN clause to specify a set of values that fields can match. For example,
here's how you can retrieve records that have values in the name field that match apples
or oranges:
You can also use logical operations on the clauses in your SQL statements. Here's an
example where we're specifying two criteria: the name field must hold either "apples" or
"oranges", and there must be some value in the number field. You use the NULL keyword to
test if there's anything in a field:
SELECT * FROM fruit WHERE name NOT IN ("apples", "oranges") AND number IS NOT NULL
You can use these logical operators to connect clauses: AND, OR, and NOT. Using AND
means that both clauses must be true, using OR means either one can be true, and using
NOT flips the value of a clause from TRUE to FALSE or FALSE t<? TRUE.
As you might expect, you can also order the records in the record set produced by an
SQL statement. Here's an example where we're ordering the records in the fruit table using
the name field:
You can also sort records in descending order with the DESC keyword:
You can use the DELETE statement to delete records like this, where we're removing all
records from the fruit table that have name values that are not apples or oranges:
You use the UPDATE statement to update a database when you want to make changes.
For example, here's how to change the value of the number field in the record that contains
the number of apples:
You can also insert new data into a table. Here's an example that inserts a new row into
the fruit table:
Okay, we've gotten as much SQL under our belts as we'll need here. The next step is all
about creating a database to work with in PHP.
%mysql
Chapter 10: Working with Databases 365
If you see a response from MySQL, congratulations, you've already got it installed. Otherwise,
you'll need to download and install it. In fact, MySQL used to come with PHP, but it no longer
does because of licensing issues.
Depending on your system and MySQL version, you might have to start the MySQL
server befo're working with MySQL. You can start the MySQL server with this command line:
%mysqld --console
On some systems, su^h^s Windows with recent versions of MySQL, you don't need to start
the MySQL server at all—it's already running. In that case, you'll get an error if you try to
start the MySQL server a second time; the error will concern shared resources.
Next, you should start a MySQL session that's going to connect to the server, and which
you can use to create your own database. You need a username and password to work with
MySQL; say your username is "user" and your password is "password". You can start
MySQL like this at the command prompt:
%mysql -u user -p
%mysql -u user -p
Enter password: ********
Once you've started a session, you'll see a response something like this:
%mysql -u user -p
Enter password: ********
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql>
The last line, mysql>, is a prompt for you to enter your commands.
If you don't have a username and password, enter mysql -u root, or just mysql, to start:
%mysql -u root
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql>
VERSION() | CURRENT_DATE
5.0.19-nt | 2007-05-10
This command gives you the MySQL version and the current date. Note that MySQL
commands like this end with a semicolon.
366 PHP: The Complete Reference
MySQL comes with some databases built in—which you can check with the SHOW
DATABASES; command:
These databases already exists in MySQL—mysql is a database that MySQL uses for
internal administration, and test is a database for test purposes.
Database tables are stored inside databases, so the first step is to create a database. You
might use this database to contain information about various fruits and vegetables, for
example, and so you can create a database named, say, produce. You can create the produce
database with the CREATE DATABASE command in the MySQL monitor:
That creates a new, empty database, which you can see with the SHOW DATABASES;
command:
Now make the produce database the default database with the USE command like this
in MySQL:
Are there any tables in this new database? You can use the SHOW TABLES command to
check that ©ut:. /
This response—"Empty set"—tells you that this database doesn't contain any
tables yet.
Records in the fruit table will contain two 20-character strings—the name of a fruit,
and the number of that fruit on hand. Here's how you create the fruit table in the
MySQL monitor:
That creates the fruit table, which you can check with the SHOW TABLES; command
like this:
In fact, you can check on this table, getting the format-of its fields with the DESCRIBE
SQL command like this:
Cool—now you've got a new database table, fruits. Time to stock it with some data.
apples 1020
oranges 3329
bananas 8582
pears 235
Alright, how about storing that in the new fruit database table? You've got two fields in
each record in the fruit table, as you can see in the MySQL description of the table:
So now you can insert two strings into the record for each kind of fruit—the name of the
fruit, and the number of that fruit on hand. You can create records in the fruit table with the
SQL INSERT command. For example, to insert a record for the number of apples on hand,
you'd execute this command: ,
t '■ i
Great, that creates,a new record for apples. You can check that new record with the
SELECT * FROM fruit; command:
And you can check the new fruit table and its contents with SELECT * FROM fruit;
like this:
name | number
apples 1020
oranges i 3329
bananas | 8582
pears | 235
That creates a database, produce, and a table in that database, fruit. You can quit the
MySQL monitor like this:
apples | 1020 |
| oranges | 3329
| bananas | 8582
| pears j 235
+-+-+
4 rows in set (0.00 sec)
mysql>quit
We're going to put these functions to work in this chapter. For example, you might put
together an example, phpdatatable.php, which reads in and displays the fruit table from the
produce database.
Here, server is the MySQL server, which can be URLs, port numbers, and so on. The
username and password arguments are the MySQL username and password.
The new_link argument, if set to TRUE, forces PHP to establish a new link to the
database, even if it already has such a link. Otherwise, if you try to open a second link to
the database by calling mysql_connect a second time, PHP may use its already-established
link instead.
The client_flags parameter can be a combination (created by Oring values together with
the OR operator, |) of the following constants: MYSQL_CLIENT_SSL, MYSQL_CLIENT_
COMPRESS, MYSQL_CLIENT_IGNORE_SPACE, or MYSQL_CLIENTJNTERACTIVE.
The mysql_connect function returns a connection object if successful, FALSE otherwise.
372 PHP: The Complete Reference
Okay, let's connect to MySQL from PHP using mysql_eonnect. In this case, MySQL and
PHP are on the same machine, so the server is just "localhost". Here's how to create the
connection object (fill in your own username and password, of course):
<?php
$connection = mysqlconnect("localhost","root","*****♦***")
Let's augment this a little, making it display a message ii there was an error, and quit,
using the die function:
<?php
$connection = mysql_connect("localhost","root","*********")
or die ("Couldn't connect to server");
Here, databasejname is the name of the database, which is "produce” here, and linkjdentifier
is the connection object. Here's how to put mysql_select_db to work in phpdatatable.php:
<?php
$connection = mysql_connect("localhost","root","*********")
or die ("Couldn't connect to server");
?>
Great—you've connected to the database server, and you've selected the database you
want to work with. Selecting the database is crucial—if you don't select a database before
proceeding, you'll get errors.
Here, query is the SQL query you want to send to the database server, and linkjdentifier is
the connection object, representing the connection to that server; if you only have one
connection open, PHP will use that connection.
For SELECT, SHOW, DESCRIBE, EXPLAIN, and other statements returning table
data, mysqLquery returns a resource on success, or FALSE on error. For other type of
SQL statements, UPDATE, DELETE, DROP, and so on, mysqLquery returns TRUE on
success or FALSE on error. The returned result resource should be passed to mysql_
fetch_array, and other functions for dealing with result tables, to access the returned
data. And you can use mysql_num_rows to find out how many rows were returned for
a SELECT statement.
The SQL for getting all records from the fruit table is "SELECT * FROM fruit”, so that'll
be our query:
<?php
$connection = mysql_connect'("localhost","root","*********")
or die ("Couldn't connect to server");
9 >
Now you can get a returned data table full of rows from the database like this with
mysqLquery:
<?php
$connection = mysql_connect("localhost","root", "*********n)
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
$result = mysql_query($query)
?>
Note that if the SQL query failed, you can end the application and display an error
using the mysql_error function:
<?php
$connection = mysql_connect("localhost","root","*********»)
or die ("Couldn't connect to server");
374 PHP: The Complete Reference
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
$result = mysql_query($query)
or die("Query failed: " . mysqlerror());
Alright, you've made progress. Now it's time to decipher the data you've recovered
from the database.
<?php
$connection = mysql_connect("localhost","root","*********")
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
?>
Now it's time to start dealing with the result you got back from your SQL query. That's
a PHP resource; it's the fruit table in code form. To extract the records from that table, you
can use the mysql_fetch_array function—this function returns an array corresponding to the
current record (that is, the current row) in the data table, and you can loop over the records
using loops. Here's how to use mysql_fetch_array:
Here, result is the resource returned by the mysql_query function—that's the data table
you've recovered from the database. And result,_type is the type of array that you want.
Chapter 10: Working with Databases 375
This value is a constant and can take the following values: MYSQL_ASSOC, MYSQL_
NUM, and the default value of MYSQL_BOTH.
You can use mysql_fetch_array to fetch rows from the fruit table, and you might loop
over those j;ows with a while loop. Here's how that looks, where you store each row from
the table in a variable named $row:
<?php
$connection = mysql_connect("localhost","root","*********»)
or die ("Cdifldn't connect to server") ;
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
} '
?>
This assigns the current row from the fruit table to $row. You can access the name field in
that row like this: $row['name’], and the number field in the row as $row['number'].
That means you can display the data in the current row's two fields, name and number,
like this in phpdatatable.php:
<?php
$connection = mysql_connect("localhost","root","*★*******")
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
{
echo '"<tr>";
echo "<td>", $row[1 name 1], "</td><td>", $row[1 number 1], "</td>";
echo "</tr>";
?>
v • 1
mysql_close ( [link_identifier] )
Here, link_identifier is the connection object that represents the connection to the database.
Here's how you close the connection in phpdatatable.php:
<html>
<head>
<title>
Displaying tables with MySQL
</title>
</head>
<body>
<hl>Displaying tables with MySQL</hl>
<?php
$connection = mysql_connect("localhost","root","*★*******»)
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
echo "</table>";
mysqlclose({connection);
?>
</body>
</html>
You can see the results appear in Figure 10-1, where you can see the whole fruit table.
Very cool.
Okay, you've been successful in recovering data from a database table. Excellent. Now
how about modifying that data?
Updating Databases
If someone buys your products online, you'll need to update your database. Say, for
example, that someone purchases a pear from you online, which means that you go from
235 pears in stock to 234:
apples 1020
oranges 3329
bananas 8582
pears 234
How would you make this change from PHP to the fruit table? You would connect to
the produce database and use an SQL UPDATE query to make the change.
378 PHP: The Complete Reference
You can see how this works in phpdataupdate.php. First, you get a connection to the
database server (put in your own username and password, of course):
<?php
$connection = mysql_connect("localhost","root","*********»)
or die ("Couldn't connect to server");
<?php
$connection = mysql_connect("localhost","root","*********»)
or die ("Couldn't connect to server");
$db = mysqlselectdb("produce",$connection)
or die ("Couldn't select database");
So how do you update the number of pears? You can use the UPDATE SQL statement
"UPDATE fruit SET number = 234 WHERE name = 'pears'" like this:
<?php
$connection = mysql_connect ("localhost", "root", <<*********<<)
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
<?php
$connection = mysql_connect ("localhost", "root" , "*******•*»)
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
$result = mysqlquery($query)
or die("Query failed: ".mysqlerror());
Chapter 10: Working with Databases 379
Okay, now let's confirm that the change was made to the fruit table, updating the
number of pears. You can display the new contents of the fruit table this way in
phpdataupdate.php:
<html> ,r
<head>
<title>
Updating databases
</title> ,,4
</head>
<body>
<hl>Updating databases</hl>
<?php
$connection = mysql_connect ("localhost", "root", »*■*******»)
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
$result = mysql_query($query)
or dieC'Query failed: " .mysql_error () ) ;
$result = mysqlquery($query)
or dieC'Query failed: " . mysql_error());
{
echo "<tr>";
echo "<td>", $row[1 name'], "</td><td>", $row['number 1], "</td>";
echo "</tr>";
}
echo "</table>";
mysql_close({connection);
?>
</body>
</html>
380 PHP: The Complete Reference
You can see the results in Figure 10-2, where the number of pears has been updated
to 234. Very nice.
Okay, so far so good. Now you've been able to read data from a database, and update
that data. What about inserting some new data?
But there's no record for apricots, so it's time to add one, which you can do with the
INSERT SQL statement in a new example, phpdatainsert.php.
First, you connect to the database server:
<?php
$connection = mysql_connect("localhost","root","stoic8888")
or die ("Couldn't connect to server");
Chapter 10: Working with Databases 381
<?php
$connection = mysql_connect("localhost","root","stoic8888")
p,x die ("Couldn't connect to server") ;
*• *
You can insert a new record into a table with the SQL INSERT statement. To insert a new
record for apricots into the fruit table, you can execute this SQL statement: "INSERT INTO
fruit (name, number) VALUES('apricots', '203')":
<?php
$connection = mysql_connect("localhost","root","stoic8888")
or die ("Couldn't connect to server");
$result = mysqlquery($query)
or die("Query failed: " . mysql_error());
If successful, that inserts a new record into the database table fruit. You can confirm that
by displaying the fruit table in phpdatainsert.php:
<html>
<head>
<title>
Inserting new data
</title>
</head>
<body>
<hl>Inserting new data</hl>
<?php
$connection = mysql_connect("localhost","root","stoic8888")
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
$result = mysql_query($query) v
or die("Query failed: " . mysql_error());
$result = mysqlquery($query)
or die("Query failed: " . mysql_error());
{
echo "<TR>";
echo "<td>", $row['name'], "</td><td>", $row[1 number 1], "</td>";
echo "</tr>";
}
echo "</TABLE>";
mysql close($connection);
?>
</body>
</html>
And you can see the results in Figure 10-3, where a new record has been added for
apricots. Cool.
Deleting Records
Now say that your supply of apricots has dried up, so you need to remove them from being
offered on your Web site. How do you delete a record? You can use the SQL DELETE statement.
Here'3 an example, phpdatadelete.php, which removes the apricots record from the fruit
table. You start as usual, by connecting to the database server and selecting the produce
database this way:
<?php ''4
$connection = mysqlconnect("localhost","root",
or die ("Couldn’t connect to server");
Now you can delete the apricots record from the fruit table using the SQL DELETE
FROM fruit WHERE name = 'apricots'":
<?pnp <.
$connection = mysql_connect("localhost","root", "")
or die ("Couldn't connect to server");
?>
<?php
$connection = mysql_connect("localhost", "root","")
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
$result = mysqlquery($query)
or die("Query failed: " . mysql_error());
384 PHP: The Complete Reference
<html>
<head>
<title>
Deleting records
</title>
</head>
<body>
<hl>Deleting records</hl> ' ' 1
<?php
$connection = mysgl_connect("localhost","root","*******")
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
$result = mysql_query($query)
or die("Query failed: " . mysql_error());
$result = mysqlquery($query)
or diep'Query failed: " . mysql error());
}
echo "</table>";
mysqlclose($connection);
</body>
</html>
You can see the results in Figure 10-4, where apricots have been deleted. Cool.
Chapter 10: Working with Databases 385
• Name Number
• corn 2083
• spinach 1993
• beets 437
You start by connecting to the server, as usual, and by selecting the produce database:
<?php
$connection = mysql_connect ( "localhost" , "root" , "****•****")
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
?>
You can create tables using the SQL CREATE statement. For example, to create a new
vegetables table with name and number fields, you could execute the SQL "CREATE TABLE
vegetables (name VARCHAR(20), number VARCHAR(20))':
<?php
$connection = mysql_connect ("localhost", "root", "********'')
or die ("Couldn't connect to server");
386 PHP: The Complete Reference
$db = mysql_select_db("produce",$connection) \
or die ("Couldn't select database");
$result = mysql_query($query)
or die("Query failed: " . mysqlerror());
?>
It's time to stock the new table with some vegetables, which you can do with the SQL
INSERT statement. Here's how you might insert a new record for corn, for example:
<?php
$connection = mysql_connect("localhost","root","********")
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
$result = mysql_query($query)
or dieC'Query failed: " . mysql_error () ) ;
$result = mysql_query($query)
or dieC'Query failed: " . mysql_error () ) ;
>
And here's how to create the other two records in the vegetables table:
<?php
$connection = mysql_connect("localhost","root","********")
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
$result = mysql_query($query)
or dieC'Query failed: " . mysql_error());
$result = mysql_query($query)
or die("Query failed: " . mysql_error());
$result = mysql_query($query)
or die("Query failed: " . mysqlerror());
$result = mysqlquery($query)
or die("Query failed: " . mysql_error());
Finally, you can display the new table like this in phpcreatetable.php:
<html>
<head>
<title>
Creating a new table
</title>
</head>
<body>
<hl>
Creating a new table
</hl>
<?php
$connection = mysql_connect("localhost","root","*******")
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
$result = mysql_query($query)
or diep'Query failed: " . mysql_error () ) ;
$result = mysql_query($query)
or die("Query failed: " . mysql_error());
$result = mysql_query($query)
or dieC'Query failed: " . mysql_error () ) ;
388 PHP: The Complete Reference
$result = mysql_query($query)
or die("Query failed: " . mysql_error());
$result = mysql_query($query)
or die("Query failed: " . mysqlerror());
*
echo "<table border=111>";
echo "<tr>";
echo "<th>Name</thxth>Number</th>" ;
echo "</tr>";
{
echo "<tr>";
echo "<td>", $row [' name ' ] , "</tdxtd>" ,
$row[1 number 1], "</td>";
echo "</tr>";
}
echo "</table>";
mysql close($connection);
?>
</body>
</html>
You can see the results in Figure 10-5, where the new table appears. Very nice.
• Name Number
• tacos 218
• pizza • * 193
• cheeseburgers 112
<?php
$connection = mysqlconnect("localhost","root",«******♦")
or die ("Couldn't connect to server");
?>
Now you can create a whole new database, foods, with the SQL "CREATE DATABASE
IF NOT EXISTS foods":
<?php
$connection = mysql_connect("localhost","root","*******")
or die ("Couldn't connect to server");
$result = mysqlquery($query)
or die("Query failed: " . mysql_error());
?>
<?php
$connection = mysql_connect ("localhost", "root" ,"*******'')
or die ("Couldn't connect to server");
$result = mysql_query($query)
or dieCQuery failed: " . mysql_error());
<?php
$connection = mysql_connect("localhost","root","*******")
or die ("Couldn't connect to server");
$result = mysql_query($query)
or dief'Query failed: " . mysql_error());
$result = mysqlquery($query)
or die("Query failed: " . mysql_error());
?>
And then you stock the snacks table with some snacks:
<?php
$connection = mysql_connect("localhost","root","*******")
or die ("Couldn't connect to server");
$result = mysql_query($query)
or die("Query failed: " . mysql_error());
$result = mysql_query($query)
or die("Query failed: " . mysql_error());
$result = mysqlquery($query)
or die("Query failed: " . mysql error());
$result = mysqlquery($query)
or die("Query failed: " . mysql error() ) ;
i ‘ 4
?>
<html>
<head>
<title>
Creating a new database
</title>
*
</head>
<body>
<hl>
Creating a new database
</hl>
<?php
$connection = mysql_connect("localhost","root","*******")
or die ("Couldn't connect to server") ;
$result = mysql_query($query)
or die("Query failed: " . mysql_error());
$result = mysql_query($query)
or die("Query failed: " . mysql_error());
$result = mysql_query($query)
or dieC'Query failed: " . mysql_error () ) ;
$result = mysql_query($query) \
or die("Query failed: " . mysql_error());
$result = mysql_query($query)
or die("Query failed: " . mysql_error());
$query = "SELECT * FROM snacks";
{
echo "<tr>";
echo "<td>", $row [' name ' ] , "</tdxtd>" ,
$row['number 1], "</td>";
echo "</tr>";
}
echo "</table>";
mysql_close($connection);
?>
</body>
</html>
You can see the results in Figure 10-6, where the new table in the new database appears.
<html>
<head>
<title> *' 4
Sorting your data
</title>
</head>
<body>
<hl>
Sorting your data
</hl>
<?php
$connection = mysql_connect ("l'ocalhost" , "root", "**•*****")
or die ("Couldn't connect to server");
$db = mysql_select_db("produce",$connection)
or die ("Couldn't select database");
$result = mysql_query($query)
or die("Query failed: " . mysql_error());
{
echo "<tr>";
echo "<td>", $row [' name ' ] , "</tdxtd>",
$row['number'], "</td>";
echo "</tr>";
echo "</table>";
mysql_close($connection);
?>
</body>
</html>
394 PHP: The Complete Reference
You can see the results in Figure 10-7, where your data was sorted.
Now that you can use SQL with PHP, your database capabilities are unlimited.
$
CHAPTER
Sessions, Cookies, and FTP
T here's a lot of PHP power coming up in this chapter—sessions, cookies, FTP, e-mail,
and more. These topics are of central interest of PF1P programmers, so this chapter is
going to be an interesting one.
By its very nature, the Internet is a stateless place—that is, Web pages don't store data.
The next time you load most Web pages into a browser is the same as the first—the Web
page is reinitialized and is displayed anew. However, the Web has become a more serious
place in terms of programming, and that means writing Web applications that work in a
multipage way: and that means storing data about the user that persists from page to page.
You're going to see two ways of doing that in this chapter: sessions and cookies. And we're
going to start with cookies.
Setting a Cookie
Cookies are those text segments that you can store on the user's computer, and PHP has
good support for setting and reading cookies. Those segments of text can persist even when
the user's computer is turned off, so you can store information about the user easily. That's
great when you want to customize a Web application—the user might choose a color
scheme, for example. Cookies are used for all kinds of purposes, from the benign to the
more sinister—such as tracking what ads a user has already seen and responded to. Setting
and reading cookies in PHP is not hard.
You set cookies on the user's machine with the PHP setcookie function:
395
396 PHP: The Complete Reference
Want a real simple cookie example? Here it is, phpsetcookie.php. This example sets a
cookie named message to the text "No worries.":
<html>
<head>
<title>
Setting a cookie
</title>
<?php
setcookie("message", "No worries.");
?>
</head>
<body>
<hl>
Setting a cookie
</hl>
The cookie was set.
And you can see the results in Figure 11-1, where the cookie was set.
This PHP page includes a hyperlink to another page, phpgetcookie.php, where the
cookie will be read:
<html>
<body>
<hl>
Setting a cookie
</hl>
The cookie was set.
Reading a Cookie
When you set a cookie, it won't be visible to your scripts until the next time you load a page.
That's because the cookie is sent to the server from the user's machine, so immediately after
you set a cookie, you won't be able to read it; you need to get a page back from the browser
first. Note also that cookies are sent in the HTTP headers in pages sent to you by the browser,
and if your cookie-handling page is in domain A (such as www.ultragiantbigco.com), only
the cookies that came from domain A are sent to you.
Once the cookies have been set, they can be accessed on the next page load with the
$_COOKIE array. We set a cookie named message in the previous topic—and we'll read it
here. The values of cookies are automatically loaded into the global array named $_COOKIES,
much as the values of Web page data are stored in $_REQUEST, which makes this
process easy.
In phpgetcookie.php, you can start by checking if the cookie was set (avoiding an error
when you try to display $_COOKIE['message'] and the cookie wasn't set):
<?php
if (isset($_COOKIE['message'])) {
i
If the cookie was indeed set, you can display its text like this:
<?php
if (isset($_COOKIE['message']) ) {
echo $_C00KIE['message'] ;
}
398 PHP: The Complete Reference
<html>
<head>
<title>
Reading a cookie
</title>
</head>
<body> * • 1
<hl>
Reading a cookie
</hl>
The cookie says:
<?php
if (isset($_COOKIE['message'])) {
echo $_COOKIE[1 message'];
}
?>
<body>
</html>
You can see the results in Figure 11-2, where the cookie was read.
Okay, that lets you set cookies and read them. However, this cookie will be deleted as
soon as the user closes their browser. How can you set a cookie's expiration time? That's
coming up next.
Here, the time stored in this parameter is a Unix timestamp, holding the number of
seconds since January 1970, and specifying the time when the cookie should be deleted.
To get the current number of seconds since January 1,1970, you can use the PHP time
function. For example, to specify that a cookie should be deleted in an hour, you can do
something like this, where you specify an expiration time of time() + 3600 seconds:
<?php
setcookie("mycookie", $value, time() + 3600);
?>
<?php
setcookie("message", "No worries for 30 days.", time()+60*60*24*30);
?>
<html>
<head>
<title>
Setting a cookie's expiration time
</title>
<?php
setcookie("message", "No worries for 30 days.", time()+60*60*24*30);
?>
</head>
<body>
<hl>
Setting a cookie's expiration time
</hl>
The cookie has been set to expire in 30 days. Go to
<a href="phpgetcookie.php">phpgetcookie.php</a> next.
<body>
</html>
You can see the results in Figure 11-3, where the cookie was set for 30 days.
When you click the hyperlink in this example, you're taken to the cookie-reading page,
phpreadcookie.php, and you can see the cookie's text in Figure 11-4.
You might even want more cookie control—for example, you can delete cookies, and
that's coming up next.
400 PHP: The Complete Reference
Deleting Cookies
Want to delete a cookie? Whether or not you can depends on the browser you're dealing
with. You can set the expiration time of a cookie to some time in the past, and that should
theoretically make the browser delete the cookie, but the browser may not delete the cookie
until the user closes the browser—and possibly not even then. So a wise precaution is to
first set the text for the cookie to an empty string,
<?php
setcookie("message",
?>
Then set the expiration time to some time in the past as well:
<?php
setcookie("message", pime [) - 3600);
?> / ' *
That's it—that's how you delete a cookie; there is no special deletecookie function.
Here's what this looks like in phpdeletecookie.php:
4 / *
<html>
<head>
<title>
Deleting cookies
</title>
<?php
setcookie("message", "", time() - 3600);
?>
</head>
<body>
<hl>
Deleting cookies
</hl>
You can see the results in Figure 11-5, where the cookie was deleted.
You can see what the phpgetcookie.php page says about the deleted cookie in
Figure 11-6—it couldn't find the cookie.
ftp_nb_fget Retrieves a file from the FTP server and writes it to an open file
ftp_nb_fput Stores a file from an open file to the FTP server
fJP-nb_get Retrieves a file from the FTP server and writes it to a local file
ftp_nb_put Stores a file on the FTP server
ftp_nlist Returns a list of files in the given directory
ftp_put Uploads a file to the FTP server
ftp_pwd Returns the current directory name
ftp_quit An alias of ftp_close
ftp_raw Sends an arbitrary command to an FTP server
ftp_rawlist Returns a detailed list of files in the given directory
ftp_rename Renames a file on the FTP server
ftp_rmdir Removes a directory
ftp _set_option Set miscellaneous run-time FTP options
ftp_site Sends a SITE command to the server
ftp_size Returns the size of the given file
ftp_ssl_connect Opens a Secure SSL-FTP connection
• ftp_systype Returns the system type identifier of the remote FTP server
Here's an example, phpftp.php. This example will log in to a remote directory and get a
directory listing. It starts by connecting to the remote server using ftp_connect:
This function opens an FTP connection to the given host (note that host shouldn't have
any trailing slashes and shouldn't be prefixed with ftp://). The port parameter specifies an
alternate port to connect to; if it is omitted or set to zero, then the default FTP port, 21, will
be used. The timeout parameter specifies the timeout for all subsequent network operations
If omitted, the default value is 90 seconds. This function returns an FTP stream on success,
or FALSE on error.
Here's how the code in phpftp.php connects (put in your own server here):
<?php
$connect = ftp_connect("ftp.ispname.com") ;
?>
Next, you have to log in to the FTP server, and you can use ftpjogin for that.
This function passes your username and password to the FTP server, and it returns
TRUE on success or FALSE on failure. If you get a result of TRUE, you're logged in to the
FTP server.
*
404 PHP: The Complete Reference
Here's how phpftp.php uses ftp_login to log in (fill in your own name and password):
<?php
$connect = ftp_connect("ftp.ispname.com");
Okay, so far, so good. The goal of phpftp.php is to get a directory listing of a remote
directory on the server, and in this example, that directory will be named code22. You can
use the ftp_nlist function to get the listing of the remote directory:
Here, ftp_stream is the connection object you got from ftp_connect, and directory is the
remote directory you want the listing of. This function returns an array of filenames from
the specified directory on success or FALSE on error.
Here's how to get a directory listing of the code22 directory:
<?php
$connect = ftp_connect("ftp.ispname.com");
Now you can loop over the array of filenames, $array, listing the filenames:
<?php
$connect = ftp_connect("ftp.ispname.com");
foreach($array as $value){
echo $value, "<br>";
}
?>
<html>
<head>
<title>
Chapter 11: Sessions, Cookies, and FTP 405
/r- /
<body>
<hl>
Reading a remote directory with FTP
</hl>
»
foreach($array as $value){
echo $value, "<br>";
}
?>
<body>
</html>
You can see what the phpftp.php page gives you in Figure 11-7—it connected to the
remote directory and displayed the directory's files. Not bad.
<?php
$connect = ftp_connect("ftp.ispname.com");
Then it attempts to log in (use your own username and password here):
<?php
$connect = ftp_connect("ftp.ispname.com");
?>
If logging in didn't work, you can inform the user and exit the application:
<?php
$connect = ftp_connect("ftp.ispname.com");
if(!$result){
echo "Could not connect.";
exit;
?>
On the other hand, if the user was able to log in, it's time to download the file. For that,
use ftp_get:
This function retrieves remote_file from the FTP server and saves it to local_file locally
(which can include a pathname). The transfer mode specified must be either FTP_ASCII or
FTP_BINARY. The pos argument is the position in the remote file to start downloading from.
This function returns TRUE on success or FALSE on failure.
Here's how to download the file a.php and save it as script.php locally:
<?php
$connect = ftp_connect("ftp.ispname.com");
Chapter 11: Sessions, Cookies, and FTP 407
if(!$result){
f,. echo "Could not connect;
exit ;
}
Did you actually get the file? You can check by seeing if Sresult is true or false. If Sresult
is TRUE, you got the file; if FALSE, you didn't:
<?php
$connect = ftp_connect("ftp.ispname.com");
if(!$result){
echo "Could not connect,.";
exit ;
if($result){
echo "Got the file.";
}
else {
echo "Did not get the file.";
}
?>
Finally, it's a good idea to close the FTP connection, which you can do with ftp_close
like this in phpftpget.php:
<html>
<head>
<title>
Downloading a file with FTP
</title>
</head>
<body>
<hldownloading a file with FTP</hl>
Downloading the file....
<br>
<?php
408 PHP: The Complete Reference
$connect = ftp_connect("ftp.ispname.com");
if (!$result){
echo "Could not connect.";
exit ;
}
if ($result){
echo "Got the file.";
}
else {
echo "Did not get the file.";
}
ftpclose($connect);
?>
<body>
</html>
You can see the results in Figure 11-8—the application connected to the remote server
and downloaded the file. Excellent.
This function stores local_file (which can be specified with a pathname) on the FTP
server, as remote Jile. The transfer mode specified must be either FTP_ASCII or FTP_
BINARY. The pos argument specifies the place to start reading data from in the local file. The
function returns TRUE on success or'FALSE on failure.
Here's an example, phpftpput.php, which uploads itself. It starts by connecting to the
FTP server:
<?php ,, 4
$connect = ftp_connect("ftp.ispname.com");
9 >
<?php
$connect = ftp_connect("ftp.ispname.com");
*
?>
And you can display the results of the connection attempt if it failed, exiting the program
this way:
<?php
$connect = ftp_connect("ftp.ispname.com");
if(!$result){
echo "Could not connect.";
exit;
?>
<?php
$connect = ftp_connect("ftp.ispname.com");
?>
410 PHP: The Complete Reference
And you can check the results of this operation, reporting on success to the user:
<?php
$connect = ftp_connect("ftp.ispname.com");
if(!$result){
echo "Could not connect.";
exit; i • •
if($result){
echo "Uploaded the file.";
}
?>
Or, if the operation failed, you can report that as well. Finally, you can close the
connection as well:
<html>
<head>
<title>
Uploading a file with FTP
</title>
</head>
<body>
<hl>
Uploading a file with FTP
</hl>
Uploading the file....
<br>
<?php
$connect = ftp_connect("ftp.ispname.com");
iff!$result){
echo "Could not connect.";
exit ;
}
$result = ftp_put($connect, "phpftpput.php", "phpftpput.php", FTP_ASCII);
Chapter 11: Sessions, Cookies, and FTP 411
if($result){
echo "Uploaded the file.";
}
else {
echo "Did not upload the file.";
}
ftpclose($connect);
?>
<body>
</html>
Okay, you can see the results in Figure 11-9—the application connected to the remote
server and uploaded the file.
Here, ftp_stream is the connection object, and path is the name of the file—including its
path—on the server to delete. This function returns TRUE on success and FALSE on failure.
In this example, phpftpdelete.php, you have to connect and log in first:
<?php
$connect = ftp_connect("ftp.ispname.com");
if(!$result){
412 PHP: The Complete Reference
Then you can delete the file you uploaded before, phpftpput.php:
<?php v ■ '
$connect = ftp_connect("ftp.ispname.com");
if(!$result){
echo "Could not connect.";
exit ;
?>
<?php
$connect = ftp_connect("ftp.ispname.com");
if(!$result){
echo "Could not connect.";
exit;
}
if($result){
echo "Deleted the file.";
}
?>
Otherwise, you can report failure. Either way, you should close the FTP connection like
this in phpftpdelete.php:
<html>
<head>
<title>
Deleting a file with FTP
Chapter 11: Sessions, Cookies, and FTP 413
</title>
</head>
<body>
<bli* ' 1
Deleting a file with FTP
</hl>
Deleting the file....
<br> ,,4
<?php
$connect = ftp_connect("ftp.ispname.com");
if(!$result){
echo "Could not connect.";
exit;
if($result){
echo "Deleted the file.";
}
else {
echo "Did not delete the file.";
}
ftp_close($connect);
?>
<body>
</html>
You can see the results in Figure 11-10—the file was indeed deleted.
And you can delete directories using ftp_rmdir (for "remove directory"):
\ 1
ftp_rmdir (ftp_stream, directory )
For both functions, ftp__strearn is the FTP connection object, and directory is the affected
directory.
Here's an example, phpftpdir.php. After connecting and logging in, the code attempts to
create a new directory named backup with ftp_mkdir, and lets the user know if it was
successful:
<?php
^connect = ftp_connect("ftp.ispname.com");
if ( !$result){
echo "Could not connect.";
exit ;
}
$result = ftpmkdir($connect, "backup");
if($result){
echo "Created the directory. <br>";
}
else {
echo "Could not create the directory. <br>";
}
?>
And after creating the new directory, you can delete it with ftp._rmdir like this in
phpftpdir.php:
<html>
<head>
<title>
Creating and removing directories with FTP
</title>
</head>
<body>
<hl>
Creating and removing directories with FTP
</hl>
Chapter 11: Sessions, Cookies, and FTP 415
<?php
$connect = ftp_connect("ftp.ispname.com");
if(!$result){
echo "Could not connect.";
exit ;
}
if($result){
echo "Created the directory. <br>";
}
else {
echo "Could not create the directory. <br>";
}
if($result){
echo "Removed the directory. <br>";
}
else {
echo "Could not remove the directory. <br>";
}
ftp_close($connect);
?>
<body>
</html>
You can see the results in Figure 11-11—the directory was created and then deleted.
Sending E-mail
Your PHP scripts can send e-mail as well. To enable e-mail, edit this section in the PHP
initialization file, php.ini:
[mail function]
; For Win32 only.
SMTP = localhost
; For Win32 only.
sendmail_from = [email protected]
; For Unix only. You may supply arguments as well (default:, "sendmail -t -i") .
;sendmail_path =
Windows users should list the SMTP host they want to use (such as mail.ispname.com
or smtp.ispname.com) and set their return address. Linux and Unix users may not have to
make any changes if the sendmail utility is already in their path, but if things don't work as
they are, uncomment the sendmail_path and set it to the appropriate value (such as / usr/
bin/sendmail).
To send mail, you use the mail function:
This sends mail to the e-mail address in to, with subject subject, and message message.
You can also set additional mail headers and parameters to sendmail.
You can see an example here—phpemail.html and phpemail.php. The phpemail.html
page lets the user enter the e-mail they want to send, and posts it to phpemail.php:
<html>
<head>
<title>
Send email
</title>
</head>
<body>
<hl>Send email</hl>
<br>
<form method="post" action= "phpemail.php" >
</form>
<body>
</html>
In this page, the user can enter their comments in a text area named message, and click
the Submit button to send those comments to phpemail.php:
<html>
<head>
<title>
Chapter 11: Sessions, Cookies, and FTP 417
Send email
</title>
</head>
/ '■ /
<body>
<hl>Send email</hl>
<br>
<form method="post" action="phpemail,php">
Please type four comments and click Submit:
<br>
ctextarea name= "message" cols="50" rows = "5"x/textarea>
<br>
<br>
<input type="submit" value="Submit">
</form>
<body>
</html>
You can see this page in Figure 11-12, where the user has entered an e-mail message.
The phpemail.php script reads the message sent by the user—that is,
$_REQUEST["message"]—and mails it this way:
<html>
<head>
<title>
Your email was sent
</title>
</head>
<body>
<hl>Your email was sent</hl>
Thanks for your email.
<br>
<?php
mail("[email protected]", "Web mail", $_REQUEST["message"]);
?>
<body>
</html>
You can see the results in Figure 11-13, where the e-mail was sent.
<html>
<head>
<title>
Send email with headers
</title>
</head>
<body>
<hl>Send email with headers</Hl>
And you can include text fields for cc and bcc headers as well:
! ■ *
<html>
<head>
<title>
Send email with headers
</title>
</head>
<body>
<hl>Send email with headers</Hl>
You can see this page in Figure 11-14, where the user has entered an e-mail, along with
cc and bcc e-mail addresses.
The user's e-mail message and cc and bcc headers is sent to phpadvemail.php. To use
the e-mail headers, you assemble them into a text string, separated by "\r\n". For example,
if the user entered a cc header, you can add that to a string named $headers this way:
<?php
$headers = "";
if(isset($_REQUEST["cc"])){
$headers .= "cc:" . $_REQUEST["cc"] . "\r\n";
}
And you can get the bcc header as well, if there was one:
<?php
$headers = "";
if(isset($_REQUEST["cc"])){
$headers .= "cc:" . $_REQUEST["cc"] . "\r\n";
}
if(isset($_REQUEST["bcc"])){
$headers .= "bcc:" . $_REQUEST["bcc"] . "\r\n";
}
?>
Finally, you can send the e-mail, along with the headers in phpadvemail.php:
<html>
<head>
<title>
Your email was sent
</title>
</head>
<body>
<hl>Your email was sent</hl>
Thanks for your email with headers.
<br>
<?php
$headers = "" ;
if (isset($_REQUEST["cc"] ) ) {
$headers .= "cc:" . $_REQUEST["cc"] . "\r\n";
Chapter 11: Sessions, Cookies, and FTP 421
if(isset($_REQUEST [ "bcc"])){
$headers .= "bcc:" . $_REQUEST["bcc"] . "\r\n";
You can see the results in Figure 11-15, where the e-mail—complete with cc and bcc
headers—was sent.
<?php
$to = "[email protected]";
$subject = "Web mail";
$message = "This email has an attachment.";
$attachment = "image.jpg";
$attachment_MIME_type = "image/jpeg";
422 PHP: The Complete Reference
Now you can work on the attachment, encoding it for inclusion in the message. This is
where it takes a little work, because you have to create a multipart form. You can start by
reading in the attachment's data into a variable named $data:
<?php
$to = "[email protected]";
$subject = "Web mail";
$message = "This email has an attachment.";
$attachment = "image.jpg";
$attachment_MIME_type = "image/jpeg";
Now we're going to work on creating our multipart form, starting with the boundary
that separates the e-mail message from the attachment data:
<?php
$to = "[email protected]";
$subject = "Web mail";
$message = "This email has an attachment.";
$attachment = "image.jpg";
$attachment_MIME_type = "image/jpeg";
$boundary = "-Multipart_Boundary-";
Now you have to encode the binary attachment data into text that e-mail uses, and you
can do that using the PHP chunk_split and base64_encode functions:
<?php
$to = "[email protected]";
$subject = "Web mail";
$message = "This email has an attachment.";
$attachment = "image.jpg";
$attachment_MIME_type = "image/jpeg";
Chapter 11: Sessions, Cookies, and FTP 423
$boundary = "-Multipart_Boundary-
$data = chunksplit(base64_encode($data));
Then you can assemble the text of the message, including the text-encoded attachment,
and mail the whole like so:
*
<?php
$to = "[email protected]";
$boundary = "-Multipart_Boundary-
$data = chunk_split(base64_encode($data) ) ;
Finally, you can report to the user what happened, like this in phpemailattachments
php:
<html>
<head>
<title>
424 PHP: The Complete Reference
<body>
<hl>
Sending email with attachments
</hl>
<?php
$to = "[email protected]"; '
$subject = "Web mail";
$message = "This email has an attachment.";
$attachment = "image.jpg";
$attachment_MIME_type = "image/jpeg";
$boundary = "-Multipart_Boundary-";
$data = chunk_split(base64_encode($data));
}
?>
<body>
</html>
Cool. You can see the results in Figure 11-16, where the e-mail, including the attachment,
was sent.
Chapter 11: Sessions, Cookies, and FTP 425
session_start();
To store data in the session, use the $_SESSION array. For example, here we're storing
"Rear Window" under the key "movie":
session_start();
$_SESSION[’movie 1] = "Rear Window";
Now in another page access (either of the same or a different page), you can access the
data under the key "movie" using $_SESSION again:
session_start();
$movie = $_SESSION[1 movie 1] ;
426 PHP: The Complete Reference
So as you can see, you're able to preserve data between page accesses. That data isn t
preserved forever—it times out at some point, typically 30-180 minutes, depending on your
PHP installation.
Session behavior is affected by these settings in the PHP initialization file, php.ini note
for example that you can set how long session data is stored by setting a value for session
,cache_expire in minutes:
• session.save_path "/tmp"
• session.name "PHPSESSID"
• session.savejhandler "files"
\
• session.auto_start "0"
• session.gc_probability "1"
• session.gc_divisor "100"
• session.gc_maxlifetime "1440"
• session.serialize_handler "php"
• session.cookie_lifetime "0"
• session.cookie_path"/"
• session.cookie_domain""
• session.cookie_secure ""
• session.use_cookies "1"
• session.use_only_cookies "0"
• session.referer^check""
• session.entropy_file ""
• session.entropy_length "0"
• session.cache_limiter "nocache"
• session.cache_expire "180"
• session.use_trans_sid "0" PHP_INI_SYSTEM | PHP_INI_PERDIR
In particular, you might note that all data for a particular session will be stored in a file
in the directory specified by the session.save_path item. A file for each session (whether or
not any data is associated with that session) will be created.
Okay, time for an example, phpsession.php, which stores the purchase total the user has
made in the session data. First, you start with session_start:
<?php
session start();
■? >
Chapter 11: Sessions, Cookies, and FTP 427
Then you can store the user's purchase total with the session key "purchase":
<?php
ses.sion_start () ; (
$_SESSION['purchase'] = "39.25";
<html>
<head>
<title>
Storing data in sessions
</title>
</head>
<body>
<hl>
Storing data in sessions
</hl>
<?php
sessionstart();
$_SESSION['purchase') = "39.25";
?>
You can see the results in Figure 11-17, where the user's purchase total was stored in the
session.
This script, phpsession.php, has a hyperlink to another page, phpsession2.php, which
reads the session data and displays it. In phpsession2.php, you start with session_start:
<?php
session start!);
?>
The information you want is stored with the key "purchase"—but before trying to
display it, you should check if an entry exists in the $_SESSION array with that key to avoid
errors:
<?php
session start!);
428 PHP: The Complete Reference
v
^ Local intranet
yg
if(isset($_SESSI0N["purchase"])){
} '
?>
If the data you're looking for exists, you can display it like this:
<?php
session_start();
if(isset($_SESSION["purchase"])){
echo "Welcome. You have purchased \$" . $ SESSION[1 purchase1] . " worth.";
}
?>
<html>
<head>
<title>
Retrieving data from sessions
</title>
</head>
<body>
<hl>
Retrieving data from sessions
</hl>
Chapter 11: Sessions, Cookies, and FTP 429
<?php
session_start();
if(isset($_SESSION["purchase"])){
echo "Welcome. You have purchased \$" . $_SESSION['purchase1] . " worth.";
}
?>
</body>
</html>
And you can see the results in Figure 11-18, where the data stored in the session was
successfully retrieved.
<?php
session start();
430 PHP: The Complete Reference
If the user has been here before, the page will have stored data in the session under the
key "count", so you can check if there is any such data:
<?php
session_start();
if (lisset($_SESSION['count'])) {
}
?> iv
If there is not any data in the session under the key "count", you can store data in the
session, setting it to 0:
<?php
session_start();
if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
?>
i
Otherwise, you can increment the value stored in the session. Then that value is
displayed by the page:
<html>
<head>
<title>
A session hit counter
</title>
</head>
<body>
<hl>
A session hit counter
</hl>
Hello there. You have been here
<?php
session_start();
if (lisset($_SESSION['count'])) {
$_SESSION['count'] = 0;
} else {
$_SESSION['count']++;
}
echo $_SESSION['count'];
Chapter 11: Sessions, Cookies, and FTP 431
?>
times before.
<body>
</html>
And you can see the results in Figure 11-19, where the user has just browsed to the page,
and the hit counter is set to 0.
After the user reloads the page a few times, you can see the results in Figure 11-20,
where the hit counter data was saved in the session.
CHAPTER
-————————————
Ajax
A jax is a hot topic, and the foundation of what's been called Web 2.0. Using Ajax
techniques, you can create Web-based applications that have the look and feel of
desktop applications. The primary difference is that Ajax applications don't refresh
the entire browser display every time the user does something, which is a very Web-centric
way of doing things. Using Ajax, you can communicate with the server behind the scenes,
download data, and display it in some specific part of the Web page, without having to
reload the whole page.
Ajax (the name stands for Asynchronous JavaScript and XML) relies on using JavaScript
in the browser. The most common language on the server to use with Ajax is PHP, so this
technology merits our attention.
IWWHMMWMIMlilWMWWWWWriMTTIlWIljlirOTWr'IllWWWWIW) . • xi -x
433
434 PHP: The Complete Reference
An Ajax demo
Fetch the message |
longer does the whole page have to be reloaded when the user does something and you
need to interact with the server. The entire interaction with the server can take place behind
the scenes, downloading and uploading data, and just specific sections of the Web page will
be updated instead of the whole page being reloaded.
WeTl take a look at how to work with Ajax, using it to fetch the contents of a text file,
before moving on to using Ajax with PHP, seeing how to send data to PHP scripts using
Ajax techniques, and reading what those scripts send back to you.
Writing Ajax
Here's what our first example, index.html, looks like—we'll spend a little time understanding
how Ajax Works with this example: 1
<html>
<head>
<title>An Aja3p<Jemo</title>
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
»
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
obj.innerHTML = XMLHttpRequestObj ect.responseText;
}
XMLHttpRequestObject.send(null);
}
}
</script>
</head>
<body>
<hl>An Ajax demo</hl>
<form>
<input type = "button" value = "Fetch the message"
onclick = "getData(1 data.txt', 'targetDiv')">
</form>
<div id="targetDiv">
<p>The fetched message will appear here.</p>
</div>
</body>
</html>
436 PHP: The Complete Reference
Okay, it's time to take this example apart—you're going to learn how to write full Ajax/
PHP applications here. The action here takes place when the user clicks the button with the
caption "Fetch the message", and here's what that button looks like in the HTML form in
index.html:
<body>
. • >
<form>
cinput type = "button" value = "Fetch the message"
onclick = "getData(1 data.txt1, 1targetDiv1)">
</form>
</body>
This button is connected to a JavaScript function, getData, and passes two arguments to
that function—"data.txt", the name of the file on the server to fetch, and "targetDiv", which
is the name of the <div> element to display the downloaded text in. Here's what that <div>
element, which currently displays "The fetched message will appear here.", looks like in
index.html:
<body>
<form>
<input type = "button" value = "Fetch the message"
onclick = "getData('data.txt', 1targetDiv1)">
</form>
<div id="targetDiv">
<p>The fetched message will appear here.</p>
</div>
</body>
When the text in data.txt is downloaded, it'll be displayed in this <div> element, targetDiv,
as you can see in Figure 12-2.
The real action in this application takes place in the JavaScript, including the getData
function.
</script> * ‘ *
Now you've got to create the XMLHttpRequest object—a process that differs, depending
on what browser you're dealing with. You can start out by attempting to create this object in
the Netscape Navigator (version 7.0 and later), Apple Safari (version 1.2 and later), and
Firefox using window.XMLHttpRequest, if that object exists, which you can test this way:
if (window.XMLHttpRequest) {
}
</script>
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest() ;
}
</script>
That takes care of Firefox, Navigator, and Safari. You now have an XMLHttpRequest object,
ready to use in those browsers.
What about the Internet Explorer? In Internet Explorer, you create XMLHttpRequest
objects as an ActiveX object, so you first test to see if you can create ActiveX objects:
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
}
</script>
438 PHP: The Complete Reference
If you can create ActiveX objects, you can create a new XMLHttpRequest object using
the expression ActiveXObject(' Microsoft.XMLHTTP") in Internet Explorer:
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new v
ActiveXObject("Microsoft.XMLHTTP");
}
</script>
At this point, then, you've been able to create an XMLHttpRequest object for all major
browsers. The major properties and methods of this object are the same across the browsers—
you can see all properties and methods of this object by browser in Tables 12-1 to 12-6.
Property Description
onreadystatechange Contains the name of the event handler that should be called when
the value of the readyState property changes. 'Read/write.
responseBody Contains a response body, which is one way HTTP responses can be
returned. Read-only.
Method Description
abort Aborts the HTTP request.
Property Description
channel Contains the channel used to perform the request. Read-only.
readyStSte Contains state of the request. Read-only.
responseText Contains the response body as a string. Read-only.
responseXML Contains the response body as XML. Read-only.
1 * 4
status Contains the HTTP status code returned by a request. Read-only.
statusText Contains the HTTP response status text. Read-only.
Table 12-3 XMLHttpRequest Object Properties for Mozilla, Firefox, and Netscape Navigator
Method Description
abort Aborts the HTTP request.
Table 12-4 XMLHttpRequest Object Methods for Mozilla, Firefox, and Netscape Navigator
Property Description
onreadystatechange Contains the name of the event handler that should be called
when the value of the readyState property changes. Read/write.
Method Description
Okay, now you have an XMLHttpRequest object—the next step is to open it, preparing
you to interact with the server.
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new
ActiveXObj ect("Microsoft.XMLHTTP");
}
function getData(dataSource, divID)
{
} '
</script>
Now you can check if the XMLHttpRequest object-creation code has been successful in
creating an XMLHttpRequest object. That creation code, being outside any JavaScript
function, runs as soon as the page loads, so you can test if you've been able to create an
XMLHttpRequest object this way in the getData function:
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
function getData(dataSource, divID)
{
if(XMLHttpRequestObject) {
}
}
</script>
Chapter 12: Ajax 441
It's time to open the XMLHttpRequest object, which configures it for use with the server
(it does not connect the object to the server); here's how you use that method:
• method This js the HTTP method used to open the connection, such as GET,
POST, PUT, fdEAD, or PROPFIND.
• URL This is the requested URL.
• asyncFlag A Boolean value indicating whether the call is asynchronous. The
default is true.
• userName The user name.
• password The password.
Here's how to open the XMLHttpRequest object in this example, index.html, configuring
that object to use the GET method to connect to the server, and to download data.txt (which
is passed to the getData function in the dataSource argument):
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new
ActiveXObj ect("Microsoft.XMLHTTP");
}
XMLHttpRequestObject.open("GET", dataSource);
}
</script>
You've configured the XMLHttpRequest object, which sets it up to work with the server.
Next, you have to make provisions to handle the data downloaded from the server.
You connect the callback function to the XMLHttpRequest object by using that object's
onreadystatechange property A function assigned to that property will be called when data
download events occur.
Here's how you assign a function to the XMLHttpRequest object's onreadystatechange
property:
. V ■ 1
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
XMLHttpRequestObject.onreadystatechange = function()
{
}
}
</script>
When this function is called, the download status of your data has changed, and you
check that using two additional XMLHttpRequest object properties—readyState and status.
The readyState property tells you how the data downloading is coming. Here are the
possible values for this property—a value of 4 is what you want to see, because that means
that the data has been fully downloaded:
• 0 uninitialized
• 1 loading
• 2 loaded
• 3 interactive
• 4 complete
The status property is the property that contains the actual status of the download.
This is actually the normal HTTP status code that you get when you try to download
Web pages—for example, if the data you're looking for wasn't found, you'll get a value
of 404 in the status property. Here are some of the possible values—note that you'll want
to see a value of 200 here, which means that the download completed normally:
Chapter 12: Ajax 443
• 200 OK
• 201 Created
• 20£ No Content /
• 205 Reset Content
• 206 Partial Content
• 400 Bad Reqi^st
• 401 Unauthorized
• 403 Forbidden
• 404 Not Found
• 405 Method Not Allowed
• 406 Not Acceptable
• 407 Proxy Authentication Required
• 408 Request Timeout
• 411 Length Required
• 413 Requested Entity Too Large
• 414 Requested URL Too Long
• 415 Unsupported Media Type
• 500 Internal Server Error
• 501 Not Implemented
• 502 Bad Gateway
• 503 Service Unavailable
• 504 Gateway Timeout
• 505 HTTP Version Not Supported
In the function connected to the onreadystatechange property, then, you can check if
your data has been downloaded by checking if the readyState property equals 4:
XMLHttpRequestObject.open("GET", dataSource);
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
} ’
}
}
</script>
444 PHP: The Complete Reference
And you can check if everything went okay by seeing if the status property holds 200:
XMLHttpRequestObject.onreadystatechange ^ function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
1
}
}
}
</script>
If you got the data from the server, you can display it in the targetDiv element in the
Web page with just a little Dynamic HTML, no page refresh needed. Here's how targetDiv
is defined in the Web page:
<body>
<form>
<input type = "button" value = "Fetch the message"
onclick = "getData(1 data.txt1, 1targetDiv1)">
</form>
<div id="targetDiv">
<p>The fetched message will appear here.</p>
</div>
</body>
You can get a JavaScript object corresponding to that <div> element like this:
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
Chapter 12: Ajax 445
XMLHttpRequestObject.send(null);
}
}
</script>
And when your data is downloaded successfully, you can display that data in the
<div> element—when you use XMLHttpRequest objects, your text is downloaded to the
responseText property, so this is how you handle that download in this example:
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
obj.innerHTML = XMLHttpRequestObject.responseText;
XMLHttpRequestObj ect.send(null);
}
}
</script>
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
446 PHP: The Complete Reference
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) t
obj.innerHTML = XMLHttpRequestObject.responseText;
i ;
}
XMLHttpRequestObj ect.send(null);
}
</script>
That connects to the server and starts the download. As you're going to see, when you use the
POST method, you pass the data you want to send to the server, if any, to the send method.
That completes this example—you've initializes the XMLHttpRequest object, set up a
callback function to handle the data download, and started the data access.
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new
ActiveXObj ect("Microsoft.XMLHTTP") ;
}
</script>
try {
XMLHttpRequestObj ect = new ActiveXObject("MSXML2.XMLHTTP");
</script>
try {
XMLHttpRequestObject = new ActiveXObject("MSXML2.XMLHTTP");
} catch (exceptionl) {
try {
XMLHttpRequestObject = new
ActiveXObj ect("Microsoft.XMLHTTP");
</script>
And if that didn't work, you can make sure that XMLHttpRequestObject is set to false:
try {
XMLHttpRequestObject = new ActiveXObject("MSXML2.XMLHTTP");
} catch (exceptionl) {
try {
XMLHttpRequestObject = new
ActiveXObj ect("Microsoft.XMLHTTP");
} catch (exception2) {
XMLHttpRequestObject = false;
}
}
</script>
If XMLHttpRequestObject is left holding FALSE after all that code, you're not dealing
with the Internet Explorer, and you can create an XMLHttpRequest object for other browsers
like this:
try {
XMLHtfepRequestObject = new ActiveXObject("MSXML2.XMLHTTP");
} catch (exceptionl) {
try {
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
} catch (exception2) {
XMLHttpRequestObject = false;
}
}
This code will create an MSXML2.XMLHTTP XMLHttpRequest object if it can in the Internet
Explorer, or a Microsoft.XMLHTTP if it can't.
So far, you've just downloaded a text file, but Ajax is most often used with PHP on the
server, so let's get to some of that.
<?php
echo 'This text was fetched from the server with Ajax and PHP.
?>
You can download the echoed text using Ajax like this in a new version of index.html,
index2.html:
<html>
<head>
<title>An Ajax and PHP demo</title>
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new
ActiveXObj ect("Microsoft.XMLHTTP") ;
}
if (XMLHttpRequestObject.readyState == 4 &&
fr. . XMLHttpRequestObj get. status == 200) {
obj.innerHTML = XMLHttpRequestObject.responseText;
<body>
<form>
<input type = "button" value = "Fetch the message"
onclick = "getData('data.php1, 'targetDiv')">
</form>
<div id="targetDiv">
<p>The fetched message will appear here.</p>
</div>
</body>
</html>
<?
if ($_REQUEST["data"] == "1") {
echo 'You sent the server a value of 11;
}
450 PHP: The Complete Reference
On the other hand, if the data you send is "2", the script choosem.php echoes this
message:
if ($_REQUEST["data"] == "1") {
echo 'You sent the server a value of
}
if ($_REQUEST["data"] == "2") {
echo 'You sent the server a value of
} V
When you use the GET method of fetching data from the server, data is sent from Web
pages back to the server using URL encoding, which means that data is appended to the URL
that is read from the server. For example, if you were using the GET method and you had
a standard Web page with a text field named "a" that contained the number 5, a text field
namedj'b” that contained the number 6, and a text field named "c" that contained the text
"Now is the time", all that data would be encoded and added to the URL you're accessing.
The names of the text fields, a, b, and c, are the parameters you're sending to the server, and
the text in each text field is the data assigned to each parameter.
When data is URL encoded, a question mark (?) is added to the end of the URL, and the
data, in name=data format, is added after that question mark. Spaces in text are converted
to a plus sign (+), and you separate pairs of name=data items with ampersands (&). So to
encode the data from the "a", "b", and "c" text fields and send it to http://www.servername
.com/user/scriptname, you'd use this URL:
http://www.servername.com/user/scriptname?a=5&b=6&c=Now+is+the+time
That means that to send the data parameter holding "1" to choosem.php, you can use an
URL like this:
choosem.php?data=l
You can modify the Ajax page you've seen so far in this chapter to interact with
choosem.php if you put in two buttons—the first sends the data parameter with "1" using
URL encoding:
<form>
<input type = "button" value = "Fetch message 1"
onclick = "getData(’choosem.php?data=l1, 1targetDiv1 >
</form>
<form>
<input type = "button" value = "Fetch message 1"
onclick = "getData(’choosem.php?data=l1, 1targetDiv’)">
Chapter 12: Ajax 451
ft. . I
Here's what all this looks like in index3.html:
<html>
<head>
<title>Sending i?jax data with GET</title>
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
>
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
obj.innerHTML = XMLHttpRequestObject.responseText;
}
}
XMLHttpRequestObject.send(null);
}
}
</script>
</head>
<body>
<form>
<input type = "button" value = "Fetch message 1"
onclick = "getData(1choosem.php?data=l1, 1targetDiv1)">
<input type = "button" value = "Fetch message 2"
onclick = "getData(1choosem.php?data=21, 1targetDiv1)">
</form>
452 PHP: The Complete Reference
<div id="targetDiv">
<p>The fetched message will appear here.</p>
</div>
</body>
</html>
You can see the result in Figure 12-3, where the user clicked the "Fetch message 1" button.
In Figure 12-4, the user clicked the "Fetch message 2" button.
<?
if ($_REQUEST["data" ] == "1") {
echo 1 You sen}:. £he server a value of 11 ;
}
if ($_REQUEST["data"] == "2") {
echo 1 You sent the server a value of 2 1 ;
}
That means that chhosem.php is set to be used with the POST method, not just GET. But
how do you send data to PHP scripts using POST?
First, because you're not sending data URL-encoded anymore, you have to change the
two buttons in the form from this:
<form>
<input type = "button" value = "Fetch message 1"
onclick = "getData(1choosem.php?data=l1, 1targetDiv1)">
cinput type = "button" value = "Fetch message 2"
onclick = "getData(1choosem.php?data=21, ’targetDiv1)">
</form>
to this, where the data—"1" or "2"—is sent to the getData function as the function's
third argument:
<form>
cinput type = "button" value = "Fetch message 1"
onclick = "getData(’choosem.php1, 'targetDiv', 1)">
cinput type = "button" value = "Fetch message 2"
onclick = "getData('choosem.php', 'targetDiv', 2)">
c/form>
Nov/ you've got to modify the getData function to take three arguments:
}
And you've also got to change this line, which specifies the GET method:
{
if(XMLHttpRequestObject) { '
var obj = document.getElementByld(divID);
XMLHttpRequestObj ect. open ( "POST" , dataSource),;
There's more to switching to the POST method than just that, however—you also have
to indicate to the server-side code that you're going to be encoding data the way POST
encodes that data, which means you have to include this line of code:
}
}
Finally, you use the send method to send the data to the server. You send the server a
data string that is the same as the one you'd append to the end of the URL withJhe GET
method, but when using POST, you pass that string to the send method:
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
obj.innerHTML = XMLHttpRequestObject.responseText;
}
Chapter 12: Ajax 455
XMLHttpRequestObject.send("data=" + data);
}
}
Here'S "what it all looks like in index4.html:
<html>
<head>
<title>Sending. Ajax data with POST</title>
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new
ActiveXObj ect("Microsoft.XMLHTTP");
}
function getData(dataSource, divID, data)
{
if(XMLHttpRequestObject) {
var obj = document. getElementByld (divID)
XMLHttpRequestObject.open("POST", dataSource);
XMLHttpRequestObj ect.setRequestHeader(1 Content-Type 1,
’application/x-www-form-urlencoded1 ) ;
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
obj.innerHTML = XMLHttpRequestObject.responseText;
}
}
XMLHttpRequestObject.send("data=" + data);
}
}
</script>
</head>
<body>
<form>
cinput type = "button" value = "Fetch message 1"
onclick = "getData(1choosem.php1, 'targetDiv1, 1)">
<input type = "button" value = "Fetch message 2"
onclick = "getData(1choosem.php', 'targetDiv', 2)">
</form>
456 PHP: The Complete Reference
<div id="targetDiv">
<p>The fetched message will appear here.</p>
</div>
</body>
</html>
You can see the result in Figure 12-5, where the user clicked the "Fetch message 1"
button, sending "1" to the server via POST.
So far, you've simply downloaded straight text, using the responseText property of the
XMLHttpRequest object. But doesn't Ajax stand for Asynchronous JavaScript and XML?
How about handling some XML? That's coming up next.
Handling XML
Say that you wanted to set up an online store that sold various items—a book on PHP, a
television, a radio, and so on. You could store the items for sale in various XML files—
productsl.xml, products2.xml, and so on, and then download their contents using Ajax.
For example, here's what productsl.xml might look like. You start with an XML
declaration, as all XML files must have:
This XML declaration says that the document is an XML document, and that it's written
in XML version 1.0. Next, all XML documents need a document element—that is, an XML
element that contains all the other elements in the document. You make up your own elements
Chapter 12: Ajax 457
in XML, so you might use a document element named <items> to store the items you have
for sale like this:
</items>
And you can store the actual items for sale inside <item> elements like this:
That completes productsl.xml. You can also have other lists of items for sale, as here in
products2.xml, which lists Soda, Cheese, and Salami:
Okay, now you have the two XML files that store the items for sale. How about
downloading those XML files using Ajax? We'll put this to work in a page called store.html.
You can display two buttons in the store.html page—one for the first list of products,
and one for the second list of products. For example, the first button would download
products.lxml by calling a JavaScript function named getproductsl:
<form>
<input type = "button" value = "Select products 1"
onclick = "getproductsl()">
</form>
And the second button will download the second list of items, products2.xml, by calling
a JavaScript function named getproducts2:
<form>
cinput type = "button" value = "Select products 1"
onclick = "getproductsl()">
<input type = "button" value = "Select products 2"
onclick = "getproducts2()">
</form>
458 PHP: The Complete Reference
In addition, we might display the downloaded items for sale in a <select> drop-down
list control named productsList:
<form>
<select size="l" id="productsList">
<option>Select an item</option>
</select>
<br>
<br>
<input type = "button" value = "Select products'1"
onclick = "getproductsl()">
cinput type = "button" value = "Select products
onclick = "getproducts2()">
</form>
And when the user selects a displayed item, you can indicate which one they selected in
the page, which we'll do in a JavaScript function named setproducts, called when the user
makes a selection in the <select> control:
<form>
<select size="l" id="productsList"
onchange="setproducts()">
<option>Select an item</option>
</select>
<br>
<br>
<input type = "button" value = "Select products 1"
onclick = "getproductsl()">
<input type = "button" value = "Select products 2"
onclick = "getproducts2()">
</form>
Okay, that sets up the controls in the page. Time to get to some Ajax, starting by creating
the XMLHttpRequest object we're going to use to communicate with the server in JavaScript:
<html>
<head>
if (window.XMLHttpRequest) {
XMLHttpRequestObj ect = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP");
Chapter 12: Ajax 459
We're going to use a function named getproductsl to fetch productsl.xml and display
the items in that XML document in the <select> control. The getproductsl function starts by
checking if the XMLHttpRequest object exists:
/'■ I
function getproductsl()
{
if(XMLHttpRequestObject) {
}
}
If the XMLHttpRequest object exists, you can open it, indicating that you want to fetch
productsl.xml:
function getproductsl()
{
if(XMLHttpRequestObject) {.
XMLHttpRequestObject.open("GET", "productsl.xml");
}
}
Now you can download the XML here just as you downloaded text earlier—except this
time, the downloaded data is XML, which means you use the responseXML property of the
XMLHttpRequest object, not the responseText property:
function getproductsl!)
{
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", "productsl.xml");
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
var xmlDocument = XMLHttpRequestObject.responseXML;
}
}
}
}
The responseXML property holds your XML data in the form of a JavaScript XML
document object. You can extract the <item> elements from that document object by using
460 PHP: The Complete Reference
<html>
<head>
var products;
function getproductsl()
{
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", "productsl.xml");
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
var xmlDocument = XMLHttpRequestObject.responseXML;
products = xmlDocument.getElementsByTagName("item");
}
}
}
}
Alright, now the products variable stores an array of <item> elements. You can call a
new function, listproducts, we'll write that will display the text in those elements in the
<select> control in the page:
function getproductsl()
{
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", "productsl.xml");
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status ==200) {
var xmlDocument = XMLHttpRequestObject.responseXML;
products = xmlDocument.getElementsByTagName("item");
listproducts();
}
}
Chapter 12: Ajax 461
And the last step is to send a value of null to the XMLHttpRequest object to start
the download:
function getproductsl() /
{ ' ' '
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", "productsl.xml");
XMLHttpRequestObject.onreadystatechange = function!)
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
var xmlDocument = XMLHttpRequestObject.responseXML;
products = xmlDocument.getElementsByTagName("item");
listproducts();
}
}
XMLHttpRequestObject.send(null);
}
}
That completes the function getproductsl; the getproducts2 function downloads the
products2.xml document:
function getproducts2()
{
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", "products2.xml");
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status ==200) {
var xmlDocument = XMLHttpRequestObject.responseXML;
products = xmlDocument.getElementsByTagName("item");
listproducts();
}
}
XMLHttpRequestObject.send(null);
}
}
Excellent. Now you can write the listproducts function that lists the products for sale, as
stored in the products array. The products array holds these elements:
<item>PHP book</item>
<item>Television</item>
<item>Radio</item>
You can access them as products[0], productsjl], products[2]. But that's not the end
of the story—how do you access the text inside each element? That's one of the tricks of
462 PHP: The Complete Reference
working with XML in JavaScript—to access the text inside each XML element, say
products[0], you. have to use the expression products[0].firstChild. That expression returns
the first text node inside the element, and that text node holds the text we want. To access
the text inside the text node, you would use the expression products[0].firstChild.data.
Here, then, is how you can stock the <select> control with <option> elements whose
captions are the products for sale:
function listproducts ()
var looplndex;
var selectControl = document.getElementByld(1productsList1);
{
selectControl.options[looplndex] = new
Option(products[looplndex].firstChild.data);
}
}
We're almost done—all that's left is to write the setproducts function, which is called
when the user makes a selection in the <select> control displaying the items for sale. You
can display the item the user selected in a <div> element named targetDiv like this in
setproducts:
function setproducts()
{
document.getElementByld(1targetDiv1).innerHTML =
"You selected " + products[document.getElementByld
(’productsList1).selectedlndex].firstChild.data;
}
As you can see, it takes a little extra effort to handle XML in Ajax. You can see store.html
in Figure 12-6.
When the user clicks the "Select products 2" button, those products are downloaded
using XML and Ajax and displayed in the <select> control, as you can see in Figure 12-7.
And when the user selects an item, that item is displayed in the page, as you see in
Figure 12-8.
That gives you an indication of how to handle XML with Ajax. Now it's time to add
PHP to this picture.
To indicate which XML document you want, you can send a parameter, items, to
products.php. When items equals "1", the script will return the first XML document, when
items equals "2", the script will return the second XML document.
We'll write products.php first—which brings up the question: how exactly do you
return an XML document from a PHP script? The way to do that is to set the Content-type
header of the data sent to the browser to "text/xml", using the PHP header function:
<?php
header("Content-type: text/xml");
?>
This necessary step lets the browser know that XML is coming. Now you can read the
items parameter and load an array named $items accordingly:
<?php
header("Content-type: text/xml");
if ($_REQUEST["items"] == "1")
$items = array('PHP book', 'Television1, 'Radio');
if ($ REQUEST["items"] == "2")
$items = array('Soda', 'Cheese', 'Salami');
Now you've got to assemble a proper XML document to send to the browser, starting
with the XML declaration:
Chapter 12: Ajax 465
<?php
header("Content-type: text/xml");
?>
<?php
header("Content-type: text/xml");
if ($_REQUEST["items"] == "1")
$items = array('PHP book', 'Television', 'Radio');
if ($_REQUEST["items"] == "2")
$items = array('Soda', 'Cheese'; 'Salami');
echo '<items>';
echo ,</items>1;
?>
Now you can loop over the items for sale, creating an <item> element for each this way:
<?php
header("Content-type: text/xml");
if ($_REQUEST["items"] == "1")
$items = array('PHP book', 'Television', 'Radio');
if ($_REQUEST["items"] == "2")
$items = array('Soda', 'Cheese', 'Salami');
echo '<items>';
foreach ($items as $value)
{
echo '<item>';
echo $value;
echo '</item>';
}
echo '</items>';
?>
466 PHP: The Complete Reference
The modifications in store2.html are relatively minor; all you have to do is to make sure
you send the correct value for the items parameter to the products.php script 1 or 2 .
You make that change in the getproductsl and getproducts2 functions—for example, here's
how you send a value of "1" to products.php in the getproductsl function:
function getproductsl()
{
if(XMLHttpRequestObject) {
XMLHttpRequestObj ect.open("GET", "products.php?items = l");
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
var xmlDocument = XMLHttpRequestObject.responseXML;
products = xmlDocument.getElementsByTagName("item");
listproducts();
}
XMLHttpRequestObject.send(null);
}
}
And that's all you need—the rest of store2.html is the same as store.html. You can see
store2.html at work in Figure 12-9.
Very cool.
, • ..
CHAPTER
Advanced Ajax
T he preceding chapter got the ball rolling with Ajax and PHP, and this chapter turns to
some more required skills to use Ajax. For example, the preceding chapter used a
single XMLHttpRequest object to communicate with the server. But what if the user
clicks a button a second time before the first Ajax operation is complete? The code will
innocently use the same XMLHttpRequest object for another request to the server—before
the first request comes back.
That's not a big problem with the examples you've seen, since they download static
data, but what if you were connection to a changing database? Or what if you had twenty
Ajax-enabled buttons in your Web page, but used only one XMLHttpRequest object to fetch
your data? Clearly, you should create and use one XMLHttpRequest object for each server
request.
There's more coming up here as well. For example, Ajax is restricted to fetching data
from the same server that the Ajax-enabled Web page itself comes from. That is, if your Ajax
page is http://www.myajax.com/mypage.com, then you're going to have trouble accessing
data from any other domain than http://www.myajax.com using Ajax. We'll discuss this
behavior—and how to get around it—in this chapter.
There are other topics here as well. For example, besides downloading text or XML
using Ajax, a common thing to do with Ajax is to download JavaScript that you execute in
the browser. That's how you connect to a Google Ajax API (application programming
interface)—Google Suggest, which you're going to see here.
Besides all that, you're going to see how to use Ajax with HTTP head requests, allowing
you to check if files exist on the server, what their length and creation date is, and more.
And you'll also see how to defeat caching in browsers like the Internet Explorer, and many
other topics as you start getting into serious Ajax.
467
468 PHP: The Complete Reference
like in store.html—note that there's only one XMLHttpRequest object, and that same object
is used no matter what button the user clicks:
<html>
<head>
var products;
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP");
}
function getproductsl()
{
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", "productsl.xml");
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
var xmlDocument = XMLHttpRequestObject.responseXML;
products = xmlDocument.getElementsByTagName("item");
listproducts();
}
}
XMLHttpRequestObj ect.send(null);
}
}
function getproducts2()
{
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", "products2.xml");
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
var xmlDocument = XMLHttpRequestObject.responseXML;
products = xmlDocument.getElementsByTagName("item");
listproducts();
}
}
Chapter 13: Advanced Ajax 469
XMLHttpRequestObj ect.send(null);
}
}
function listproducts ()
{
var looplndex;
var selectControl = document.getElementByld('productsList');
/ * *
selectControl.options[looplndex] = new
Option(products[looplndex] .firstChild.data) ;
}
function setproducts()
{
document.getElementByld('targetDiv').innerHTML =
"You selected " + products[document.getElementByld
('productsList').selectedlndex].firstChild.data;
}
</script>
</head>
<body>
<form>
<select size="l" id="productsList"
onchange="setproducts()">
<option>Select an item</option>
</select>
<br>
<br>
<input type = "button" value = "Select products 1"
onclick = "getproductsl()">
cinput type = "button" value = "Select products 2"
onclick = "getproducts2()">
</form>
This is a problem we should address, and it's a common problem with Ajax applications.
Knowing how to deal with it is crucial to Ajax programming. There are several solutions,
which you'll see here. The first such solution is to use multiple XMLHttpRequest objects.
Here's how to modify store.html to use two XMLHttpRequest objects. The process is not
hard: all you have to do is to create two XMLHttpRequest objects—XMLHttpRequestObject
470 PHP: The Complete Reference
and XMLHttpRequestObject2—and then use one object in the functions that connect to the
server—getproductsl and getproducts2:
<html>
<head>
var products;
*
\
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP");
}
if (window.XMLHttpRequest) {
XMLHttpRequestObject2 = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject2 = new ActiveXObject("Microsoft.XMLHTTP");
}
function getproductsl()
{
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", "productsl.xml");
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
var xmlDocument = XMLHttpRequestObject.responseXML;
products = xmlDocument.getElementsByTagName("item");
listproducts();
}
}
XMLHttpRequestObject.send(null);
}
}
function getproducts2()
{
if(XMLHttpRequestObject2) {
XMLHttpRequestObject2.open("GET", "products2.xml");
XMLHttpRequestObject2.onreadystatechange = function()
{
if (XMLHttpRequestObject2.readyState == 4 &&
Chapter 13: Advanced Ajax 471
XMLHttpRequestObject2.status == 200) {
var xmlDocument = XMLHttpRequestObject2.responseXML;
products = xmlDocument.getElementsByTagName("item") ;
, listproducts (); /
'}
}
XMLHttpRequestObject2.send(null);
} "7
}
function listproducts ()
{
var looplndex;
var selectControl = document.getElementByld(1productsList');
function setproducts()
{
document.getElementByld('targetDiv').innerHTML =
"You selected " + products[document.getElementByld
('productsList') .selectedlndex] .firstChild.data;
}
</script>
</head>
<body>
<form>
<select size="l" id="productsList"
onchange="setproducts()">
<cption>Select an item</option>
</select>
<br>
<br>
<input type = "button" value = "Select products 1"
onclick = "getproductsl()">
cinput type = "button" value = "Select products 2"
onclick = "getproducts2()">
</form>
You can see the results in Figure 13-1, where each of the two buttons uses a different
XMLHttpRequest object.
This approach is an improvement, but it also has issues—what if you needed a
thousand such objects, would you want to add code to explicitly create each one? Hardly.
You might try creating an array of XMLHttpRequest objects instead, coming up next.
And then when you needed a new XMLHttpRequest object, you could create one,
adding it to the array with the JavaScript push method:
function getproductsl()
{
if (window.XMLHttpRequest) {
XMLHttpRequestObjects.push(new XMLHttpRequest());
} else if (window.ActiveXObject) {
XMLHttpRequestObjects.push(new ActiveXObject("Microsoft.XMLHTTP"));
}
Chapter 13: Advanced Ajax 473
Here's a new Ajax-enabled page, array.html, that puts this to work, creating the store
example using an array of XMLHttpRequest objects in case you have multiple concurrent
Ajax calls:
/'■ /
<html>
<head>
var products;
var index = 0;
var XMLHttpRequestObjects = new ArrayO;
function getproductsl()
{
if (window.XMLHttpRequest) {
XMLHttpRequestObjects.push(new XMLHttpRequest());
} else if (window.ActiveXObject) {
XMLHttpRequestObjects.push(new ActiveXObject("Microsoft.XMLHTTP"));
}
index = XMLHttpRequestObjects.length - 1;
if(XMLHttpRequestObjects[index]) {
XMLHttpRequestObjects[index].open("GET", "productsl.xml");
XMLHttpRequestObjects[index].onreadystatechange = functionO
{
if (XMLHttpRequestObjects[index].readyState == 4 &&
XMLHttpRequestObjects[index].status == 200) {
var xmlDocument = XMLHttpRequestObjects[index].responseXML;
products = xmlDocument.getElementsByTagName("item");
listproducts();
}
}
XMLHttpRequestObjects[index].send(null);
}
}
function getproducts2()
{
if (window.XMLHttpRequest) {
XMLHttpRequestObjects.push(new XMLHttpRequest());
} else if (window.ActiveXObject) {
XMLHttpRequestObjects.push(new
ActiveXObject("Microsoft.XMLHTTP"));
}
index = XMLHttpRequestObjects.length - 1;
474 PHP: The Complete Reference
if(XMLHttpRequestObj ects[index]) {
XMLHttpRequestObjects[index].open("GET", "products2.xml");
XMLHttpRequestObjects[index].onreadystatechange = functionO
{
if (XMLHttpRequestObjects[index].readyState == 4 &&
XMLHttpRequestObjects[index].status == 200) {
var xmlDocument = XMLHttpRequestObjects[index].responseXML
products = xmlDocument.getElementsByTagName("item");
listproducts(); ^ . ,
} } ;
XMLHttpRequestObjects[index].send(null);
}
}
function listproducts ()
{
var looplndex;
var selectControl = document.getElementByld('productsList');
function setproducts()
{
document.getElementByld('targetDiv').innerHTML =
"You selected " + products[document.getElementByld
('productsList').selectedlndex].firstChild.data;
}
</script>
</head>
<body>
<form>
<select size="l" id="productsList"
onchange="setproducts()">
<option>Select an item</option>
</select>
<br>
<br>
<input type = "button" value = "Select products 1"
onclick = "getproductsl()">
cinput type = "button" value = " Select products 2
onclick = "getproducts2()">
Chapter 13: Advanced Ajax 475
</form>
You can see the results in Figure 13-2, where each of the two buttons uses a different
XMLHttpRequest object from the array.
This technique works, but you may end up with large arrays of XMLHttpRequest
objects, and it's up to you to delete unused objects. Both the techniques you've seen—
multiple XMLHttpRequest objects and XMLHttpRequest object arrays—work, and you'll
see them used, but perhaps the best solution to handling concurrent Ajax requests is to use
JavaScript inner functions, coming up next.
function outer(data)
{
var variablel = data;
function inner(variable2)
{
alert(variablel + variable2)
}
}
476 PHP: The Complete Reference
Now say you call the outer function with a value of 4 like this: outer(4). That sets the
variable variable! in this function to 4. It turns out that the inner function has access to the
outer function's data—even after the call to the outer function has finished. So if you were now
to call the inner function, passing a value of 5, that would set variable2 in the inner function to
5—and variablel is still set to 4. So the result of calling the inner function would be 4 + 5 = 9,
which is the value that would be displayed by the JavaScript alert function in this case.
Here's the good part: Every time you call the outer function, a new copy of that function
is created, which means a new value will be stored as variablel. And the inner function will
have access to that value. So if you make the shift from thinking In terms of variablel and
start thinking in terms of the variable XMLHttpRequestObject, you can see that each time a
function like this is called, JavaScript will create a new copy of the-function with a new
XMLHttpRequest object, and that object will be available to any inner functions.
That's what you want in this case, because the code you've been writing already uses an
anonymous inner function, connected to the onreadystatechange property in the getData
function. To make this work like the preceding example, where a new XMLHttpRequest
object is created each time you call the functionsgetproductsl or getproducts2, all you have
to do is to put the code that creates and fills the variable XMLHttpRequestObject inside the
getproductsl and getproducts2 functions. Once you've done that, a new XMLHttpRequest
object will be created each time you call the function, and the anonymous inner function
will use that new object automatically. That means the whole solution to the problem of
multiple concurrent requests looks like this in inner.html:
<html>
<head>
var products;
function getproductsl()
{
var XMLHttpRequestObject = false;
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP");
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", "productsl.xml");
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
var xmlDocument = XMLHttpRequestObject.responseXML;
products = xmlDocument.getElementsByTagName("item");
listproducts();
Chapter 13: Advanced Ajax 477
}
}
XMLHttpRequestObject.send(null);
}
}
function getproducts2()
{
var XMLHttpRequestObject = false;
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest() ;
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP");
}
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", "products2.xml");
P
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
var xmlDocument = XMLHttpRequestObject.responseXML;
products = xmlDocument.getElementsByTagName("item");
listproducts();
}
}
XMLHttpRequestObject.send(null);
}
}
function listproducts ()
{
var looplndex;
var selectControl = document.getElementByld('productsList1) ;
{
selectControl.options[looplndex] = new
Option(products[looplndex].firstChild.data);
function setproducts()
{
document.getElementByld(1targetDiv').innerHTML =
"You selected " + products[document.getElementByld
('productsList').selectedlndex].firstChild.data;
}
</script>
478 PHP: The Complete Reference
</head>
<body>
<form>
<select size="l" id="productsList"
onchange="setproducts()">
<option>Select an item</option> ( , ,
</select>
<br> |
<br>
<input type = "button" value = "Select products 1"
onclick = "getproductsl()">
cinput type = "button" value = "Select products 2"
onclick = "getproducts2()">
</form>
You can see the results in Figure 13-3, where the example uses inner functions to
automatically create a new XMLHttpRequest object for each Ajax request.
Besides downloading text and XML in Ajax, you can download other types of data as
well. You're going to see how to download JavaScript—a commonly used technique—in
this chapter, as well as images.
Note Images? Isn't Ajax limited to downloading text data such as XML? It turns out that when
you download images, you actually download the name of the image, and rely on Dynamic
HTML in the browser to actually download the image.
<?php
if ($_REQUEST["image"] == "1"){
echo "Imagel.jpg";
}
if ($_REQUEST["image"] == "2"){
echo "Image2.jpg";
}
?>
And you can add two buttons to the page, "Show image 1" and "Show image 2". Each
button is connected to the JavaScript function getData, which we've been using to
download data using Ajax. The first button calls imageName.php with the image parameter
set to "1", and the second button calls imageName.php with the image parameter set to ”2":
<form>
<input type = "button" value = "Show image 1"
onclick = "getData(1imageName,php?image=l1, callback)">
<input type = "button" value = "Show image 2"
onclick = "getData(1imageName.php?image=21, callback)">
</form>
So how do you use the downloaded image name to force the browser to download an
image? You do that by writing an <img> element in the Web page. For that reason, image,
html includes a target <div> element, targetDiv:
<div id="targetDiv">
<p>The fetched image will appear here.</p>
</div>
In JavaScript, there's a function named callback that is passed the name of the image file
to download. It writes the new <img> element in the targetDiv <div> element like this:
function callback(text)
{
document.getElementByld("targetDiv").innerHTML =
"<img src= " + text +
}
480 PHP: The Complete Reference
When the new <img> element appears in the page, the browser downloads the required
image. Here's how it all looks in image.html:
<html>
<head>
<title>Downloading images using Ajax</title>
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", dataSource);
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
callback(XMLHttpRequestObj ect.responseText);
delete XMLHttpRequestObject;
XMLHttpRequestObject = null;
}
}
XMLHttpRequestObj ect.send(null);
}
}
function callback(text)
{
document.getElementById("targetDiv").innerHTML =
"<img src= " + text + ">";
}
</script>
</head>
<body>
<form>
<input type = "button" value = "Show image 1"
onclick =
Chapter 13: Advanced Ajax 481
"getData('imageName.php?image=l', callback)">
cinput type = "button" value = "Show image 2"
onclick =
"getData('imageName.php?image=21, callback)">
</form>
<div id="targetDiv">
<p>The fetched image will appear here.</p>
</div>
</body>
</html>
You can see the results in Figure 13-4, where the user has clicked the Show image 1
button, and the application has loaded Imagel.jpg. Clicking Show image 2 would display
Image2.jpg.
Now you're downloading images using Ajax and PHP. Not bad. Now let's take a look at
handling JavaScript downloads.
JavaScript function named display, and javascript.php simply echoes that function call as a
JavaScript statement:
<?php
echo 'display()';
?>
When the code in javascript.html reads this JavaScript statement, "displayO", it'll
execute that statement, which will call the display function, displaying a message.
You start javascript.html with a button calling the getData function, which we've been
using to download Ajax data, passing it the name of the PHP script to access, javascript.php:
<form>
cinput type = "button" value = "Download the JavaScript"
onclick = "getData(’javascript.php1)">
</form>
Here's the key—when you download JavaScript from a PHP script, you can use the
JavaScript eval function to execute that JavaScript. That JavaScript will be downloaded into
the XMLHttpRequest object's responseText property, so you can execute it like this in
getData:
function getData(dataSource)
{
if(XMLHttpRequestObject) {
XMLHttpReguestObject.open("GET", dataSource);
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
eval(XMLHttpRequestObj ect.responseText);
}
}
XMLHttpRequestObj ect.send(null);
}
Finally, you need to write a display function in javascript.html that will be called when
the JavaScript downloaded from javascript.php is executed. That looks like this in our
complete Ajax application, javascript.html, where the display function displays the message
"Success" in the page:
<html>
<head>
<title>Downloading JavaScript with Ajax</title>
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = /new ActiveXObject("Microsoft.XMLHTTP");
function getData(dataSource)
{
if (XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", dataSource);
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
eval(XMLHttpRequestObject.responseText);
}
}
XMLHttpRequestObj ect.send(null);
}
}
function display()
{
var targetDiv = document.getElementByld("targetDiv");
targetDiv.innerHTML = "Success";
}
</script>
</head>
<body>
<form>
cinput type = "button" value = "Download the JavaScript"
onclick = "getData('javascript.php')">
</form>
<div id="targetDiv">
<p>The data will go here.</p>
</div>
</body>
</html>
You can see the results in Figure 13-5, where javascript.html appears.
When the user clicks the button, the JavaScript is downloaded from javascript.php and
executed, giving you a message of success, as you can see in Figure 13-6.
484 PHP: The Complete Reference
So how can you connect to Google Suggest? Say that you've stored the partial search term
in a variable named searchTerm—you could then connect to Google Suggest at this URL:
How does Google Suggest communicate with you? It will send back JavaScript code that
calls a function named sendRPCDone. Here are the parameters passed to that function:
"ajax fc", "ajax Ontario", "ajax grips", "ajax football club", "ajax public
library", "ajax football", "ajax soccer", "ajax pickering transit"), new
Array("3,840,000 results", "502,000 results", "710,000 results", "275,000
results", "8,860 results", "573,000 results", "40,500 results", "454,000
results", "437,000 results" , "10,700
results"), new Array(""));
You take it from there, writing your own sendRPCDone function that will display the
results sent back to you from Google Suggest.
We're going to write an example, google.html, that will connect to Google Suggest using
Ajax and PHP. Why is PHP needed here? That has to do with an Ajax issue—using Ajax,
you can't access domains other than the domain the page came from without having the
browser display warnings. More on this is coming up.
You can see our version of a Google Suggest page in Figure 13-9. It looks and acts just
like the real thing, except that we're going to do it ourselves, putting Ajax to work with the
help of some PHP.
The google.html example starts with a text field that calls a JavaScript function named
connectGoogleSuggest each time a typed key is released by tying it to the text field's
onkeyup event:
<body>
<hl>Connecting to Google Suggest</hl>
</body>
In the connectGoogleSuggest function, you can check if there's any text to send to
Google Suggest, and if so, send that text to google.php as the parameter qu (for query). You
can get the text to send using the text field's value property:
function connectGoogleSuggest(keyEvent)
{
var input = document.getElementByld("textField");
Chapter 13: Advanced Ajax 487
if (input.value) {
getData("google.php?qu=" + input.value);
} '
}
On the other hand, if there's nothing to send, the user has presumably deleted all text in
the text field, in which case you want to clear the displayed drop-down list of matches from
Google Suggest. Those matches are actually going to be displayed in a drop-down list,
which is actually an HTML table, inserted into a <div> element, targetDiv, right under the
text field:
<body>
<hl>Connecting to Google Suggest</hl>
<div id = "targetDiv"><divx/divx/div>
</body>
488 PHP: The Complete Reference
In the connectGoogleSuggest function, you can clear the drop-down list if the user has
deleted all search text, like this:
function connectGoogleSuggest(keyEvent)
{
var input = document.getElementByld("textField");
if (input.value) {
getData("google,php?qu=" + input.value);
}
else {
var targetDiv = document.getElementByld("targetDiv");
targetDiv.innerHTML = "<div></div>";
}
So when the user enters some search text, that text is passed to google.php by the
getData function—and when Google Suggest returns JavaScript to execute, we'll execute
that JavaScript using the JavaScript eval function:
function getData(dataSource)
{
var XMLHttpRequestObject = false;
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest () ;
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP");
}
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", dataSource);
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
eval(XMLHttpRequestObject.responseText);
}
}
XMLHttpRequestObject.send(null);
}
}
Alright, it's time for google.php to take over. This is the script that connects to Google
Suggest and downloads JavaScript for the application to execute.
Here's the key to this application: why not just connect to Google Suggest directly
from google.html? Why do you have to go through the intermediary of google.php? You
need google.php because of the mentioned quirk in Ajax: using Ajax, you can't access any
Chapter 13: Advanced Ajax 489
other domain other than the one your page comes from without seeing warning dialogs
from the browser. Those warning dialogs are there for security—the browser thinks your
page is doing something it shouldn't.
To avAJid those warning dialogs, add still connect to other domains using Ajax, you need
to relay your request through some server-side code. That way, the browser only sees you
accessing a script in the same domain as your main page. But that script can connect to
another site, and the browser won't know a thing about it.
The URL you wanPto access Google Suggest is http:/ / www.google.com/complete/
search, and you send it the user's partially typed search term using the parameter qu. And
you can open that URL from PHP using fopen. So here's how you send Google Suggest the
partially typed search term the user has typed, getting a file handle that represents the
response in google.php:
<?php
$filehandle =
fopen("http://www.google.com/complete/search?hl=en&js=true&qu=" . $_GET["qu"],
"r ") ;
Now you've got a file handle that represents Google Suggest's JavaScript response to
the partially typed search term you sent it. You can loop over that response using a while
loop and feof:
<?php
$filehandle =
fopen("http://www.google.com/complete/search?hl=en&js=true&qu=" . $_GET["qu"],
"r") ;
while (!feof ($filehandle)){
}
?>
And you can download, and echo, Google Suggest's response to your query line by line
like this:
<?php
$filehandle =
fopen("http://www.google.com/complete/search?hl=en&js=true&qu=" . $_GET["qu"],
"r" ) ;
while (!feof($filehandle)){
$download = fgets($filehandle);
echo $download;
?>
490 PHP: The Complete Reference
<?php
$filehandle =
fopen ( "http://www.google.com/complete/search?hl=en&js=true&qu=" . $_GET["qu"] ,
"r") ;
while (!feof($filehandle)){
$download = fgets($filehandle);
echo $download; ( . t
}
fclose($filehandle);
?>
Okay, that uses PHP to solve the problem of not being able to access other domains than
your page's home domain with Ajax. This script connects to Google Suggest and gets
Google's response to what the user has typed.
That response is in JavaScript form, as you've seen, something like this:
And the google.html page executes that JavaScript with the eval function:
XMLHttpRequestObject.onreadystatechange = functionO
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
eval(XMLHttpRequestObj ect.responseText);
}
}
You're responsible for writing sendRPCDone yourself. Here's how Google defines the
parameters of this function:
}
Chapter 13: Advanced Ajax 491
This information is going to be displayed in an HTML table inside the targetDiv element
in the page's body:
<body>
<hl>Connecting to Google Suggest</hl>
>
<div id = "targetDiv"><divx/divx/div>
</body>
The purpose of the sendRPCDone function is to create the HTML table in a variable
named data showing the results and display it:
data += "</table>";
You can loop over the results from Google this way:
if (arrayResults.length != 0) {
for (var looplndex = 0; looplndex < arrayResults.length;
loop!ndex++) {
492 PHP: The Complete Reference
} ’
data += "</table>";
targetDiv.innerHTML = data;
}
In each line of the HTML table, you can display a hyperlink to the search term (in case
the user decides that's the term they want to search for) and the number of matches Google
found for that term:
if (arrayResults.length != 0) {
for (var looplndex = 0; looplndex < arrayResults.length;
loopIndex++) {
data += "<trxtd>" +
"<a href=1 http://www.google.com/search?g=" +
arrayTerm[looplndex] + "+ arrayTerm[looplndex] +
1 </ax/tdxtd> 1 + arrayResults [looplndex] + "</tdx/tr>" ;
}
}
data += "</table>";
targetDiv.innerHTML = data;
}
You can also style the targetDiv element with a background color like this in a <style>
element to make it stand out:
<head>
<title>Connecting to Google Suggest</title>
<style>
#targetDiv {
background-color: #FFAAAA;
width: 40%;
}
</style>
</head>
Chapter 13: Advanced Ajax 493
And that completes google.html—with this page and google.php, you've been able to
connect to Google Suggest, download JavaScript, and run that JavaScript. Here's the full
google.html:
/'• /
<html>
<head>
<title>Connecting to Google Suggest</title>
<style>
#targetDiv { ' *
background-color: #FFAAAA;
width: 4 0%;
}
</style>
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP");
}
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", dataSource);
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
eval(XMLHttpRequestObject.responseText);
}
}
XMLHttpRequestObj ect.send(null);
}
}
function connectGoogleSuggest(keyEvent)
{
var input = document.getElementByld("textField");
if (input.value) {
getData("google.php?qu=" + input.value);
}
else {
var targetDiv = document.getElementByld("targetDiv");
{
var data = "<table>";
var looplndex;
if (arrayResults.length != 0) {
for (var looplndex = 0; looplndex < arrayResults.length;
loopIndex++) {
data += "<trxtd>" + v >
"<a href='http://www.google.com/search?q=" +
arrayTerm[looplndex] + Ml>" + arrayTerm[looplndex] +
1 </ax/tdxtd> 1 + arrayResults [looplndex] "</tdx/tr>" ;
}
}
data += "</table>";
targetDiv.innerHTML = data;
}
</script>
</head>
<body>
<hl>Connecting to Google Suggest</hl>
</body>
</html>
One of the key issues here was getting around the Ajax restriction of not being able to
connect to other domains.
<?php
$filehandle =
fopen ( "http://www.google.com/complete/search?hl=en&js=true&qu=" . $ GET["qu"],
" r" ) ;
Chapter 13: Advanced Ajax 495
while (!feof($filehandle)){
$download = fgets($filehandle);
echo $download;
} . I
fclose($filehandle);
/ • *
<body>
<Hl>Choose a username</Hl>
<div id = "targetDiv"><divx/divx/div>
</body>
The checker function calls the getData function with the URL log.php, sending the
username the user is entering to log.php using the parameter name qu :
function checker()
{
var targetDiv = document.getElementByld("targetDiv");
targetDiv. innerHTML = "<divx/div>";
if (document.getElementByldP'textField").value) {
getData("log.php?qu=" + i ' '
document.getElementByld("textField").value);
} l
}
The getData function connects to the server and downloads the results:
function getData(dataSource)
{
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", dataSource);
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
}
}
XMLHttpRequestObj ect.send(null);
}
}
The PHP script in this case is going to return "OK" if the chosen username is okay, and
"notOK" if the username has already been taken. If the username has already been taken,
this example displays the message "Sorry, that username is not available." in a <div>
element:
function getData(dataSource)
{
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", dataSource);
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
if(XMLHttpRequestObject.responseText == "notOK"){
var targetDiv = document.getElementByld("targetDiv");
targetDiv.innerHTML =
"<div>Sorry, that username is not available.</div>";
Chapter 13: Advanced Ajax 497
}
}
}
' XFlLHttpRequestObj ect. send (null) ;
}
}
The PHP script, Jog.php, checks the username passed to it using the parameter qu and
returns the text "notOK' if the username has already been taken:
<?php
if ($_GET["qu"] == "steve"){
echo "notOK";
}
<?php
if ($_GET["qu"] == "steve"){
echo "notOK";
}
else {
echo "OK";
}
?>
Server: Microsoft-IIS/5.1 Date: Mon, 28 May 2007 17:57:54 GMT Content-Type: text/
html Accept-Ranges: bytes Last-Modified: Mon, 28 May 2007 17:57:49 GMT ETag:
"3c058b451alc71:a2f" Content-Length: 1266
It's worth taking a look at working with head requests in Ajax, and this example, head,
html, shows how they work. This example starts with the button you see in the figure, tied
to the getData function:
<body>
<form>
<input type = "button" value = "Get header data"
onclick = "getData('head.html1, 'targetDiv1)">
</form>
<div id="targetDiv">
<divx/div>
</div>
</body> v • t
In the getData function, you specify that you want head information by specifying that
you want to open the document using the HEAD method (not GET or POST):
And when your data is downloaded, you can recover the head data using the
XMLHttpRequest object's getAllResponseHeaders method:
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
targetDiv.innerHTML =
XMLHttpRequestObject.getAllResponseHeaders();
}
}
XMLHttpRequestObject.send(null);
This code gives you the results you see in Figure 13-11. Cool.
You can use the getAllResponseHeaders method to read all headers from the server, but
you can also use getResponseHeader method to read the value of any particular header.
Here's an example, lastModified.html, that checks its own last-modified date and displays
it, as you can see in Figure 13-12.
Chapter 13: Advanced Ajax 499
<html>
<head>
<title>Getting a document's last-modified date</title>
This document was last modified on Mon, 28 May 2007 18:46:32 GMT
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP");
{ if(XMLHttpRequestObject) {
var targetDiv = document.getElementByld(divID);
XMLHttpRequestObject.open("HEAD", dataSource);
v
XMLHttpRequestObject.onreadystatechange = function ()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
targetDiv.innerHTML = "This document was last modified on " +
XMLHttpRequestObj ect.getResponseHeader(
"Last-Modified");
}
}
XMLHttpRequestObject.send(null);
}
}
</script>
</head>
<body>
<form>
<div id="targetDiv">
<divx/div>
</div>
</body>
</html>
/
CHAPTER
Drawing Images on the Server
T his chapter is all about using PHP to create graphics on the server. Using PHP, you
can draw just about anything and send it back to the browser in a variety of graphics
formats—JPEG, PNG, etc.
To make this work, you have to install support for GD2 in PHP. That happens in a
variety of ways—check the PHP install directions for your operating system. For example,
you might have to check the CD2 check box when asked what options you want to install.
Just what graphics functions are available? Here's the list:
Function Description
gd info Retrieve information about the GD library
getimagesize Return size of an image
image type to extension Return file extension for image
i m age_ty pe_to_m i me_ty pe Return Mime-Type for image-type returned by getimagesize,
exif read data, exifjhumbnail, exifjmagetype
image2wbmp Send image to browser or file
imagealphablending Set the blending for an image
imagecolorclosest Return the index of the closest color to the given color
imagecolorclosestalpha Return the index of the closest color to the given color and
alpha setting
501
502 PHP: The Complete Reference
Function Description
imagecolorclosesthwb Return the index of the color that has the hue, whiteness,
and blackness nearest to the given color
imagecolorexactalpha Return the index of the given color and alpha setting
imagecolorresolve Return the index of the given color or its closest possible
alternative
imagecolorresolvealpha Return the index of the given color and alpha setting or its
closest possible alternative
imagecreatefromgd2part Create a new image from a given part of GD2 file or URL
Function Description
imagefiil Flood fill
~ .
imagefilledarc Draw a partial ellipse and fill it
imagefilledellipse Draw a filled ellipse
imagefilledpolygon Draw a filled polygon
imagefilledrectangle 4 Draw a filled rectangle
imagefilltoborder Flood fill to specific color
imagefilter Apply a filter to an image
imagefontheight Return font height
imagefontwidth Return font width
imageftbbox Give the bounding box of text
imagefttext Write text to the image
imagegammacorrect Apply a gamma correction
imagegd Send GD image to browser or file
imagegd2 Send GD2 image to browser or file
imagegif Send image to browser or file
imageinterlace Enable or disable interlace operations
imageistruecolor Determine whether an image is a true color image
Function Description
imagesavealpha Set the flag to save full alpha channel information when
saving PNG images
Creating an Image
To create an image in memory to work with, you start with the GD2 imagecreate function:
imagecreate{x_size, y_size)
$image_height = 100;
$image_width = 300;
Next, to set colors to be used in the image, you use the imagecolorallocate function:
To send a JPEG image back to the browser, you have to tell the browser that you're
doing so with the header function to set the image's type, and then you send the image with
the imagejpeg function like this:
$image_height = 100;
$image_width = 300;
header(’Content-Type: image/jpeg1);
imagejpeg($image);
Here are some of the image-creating functions for various image formats you can use:
After sending the image, you can destroy the image object with the imagedestroy
function; all this is shown in phpimage.php:
<?php
$image_height = 100;
$image_width = 300;
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
•? >
You can see the results in Figure 14-1. As you see, all that appears is a background box
in this example. However, we've made progress—that's a real image you see in the figure.
On the other hand, it's a rare Web page that displays simply an image. Usually, that
image appears in an HTML page.
<img src="image.jpg">
In the same way, you can give the name of the script that generates a JPEG image,
phpimage.php, as the src attribute like this:
<img src="phpimage.php">
Chapter 14: Drawing Images on the Server 507
Here's what a Web page, phpimage.html, that displays the blank box created by
phpimage.php looks like:
<html>
<head>
<title>
Embedding created images in HTML pages
</title>
</head>
<body>
<hl>
Embedding created images in HTML pages
</hl>
This is a blank image created on the server:
<br>
<img src="phpimage.php">
</body>
</html>
You can see the results in Figure 14-2, where the JPEG image created by phpimage.php
appears, embedded in an HTML page. Not bad.
Okay, that creates a basic image and displays it. How about drawing some actual graphics?
ii ii i iiiiiinniiiiTmnia«a»a8?ii^^ t i;t«—wr»i
Drawing Lines
You can draw lines with the imageline function:
This function draws a line from (xl, yl) to (x2, y2) (the top left of the image is (0, 0), and
all measurements* are in pixels) in image image using drawing color color.
Time to draw some lines in a new script, phpline.php. This example starts by creating
the same background in the image you've already seen:
<?php
$image_height = 100;
$image_width = 300;
v ■ »
$image = imagecreate($image_width, $image_heignt);
>
Now we'll set the drawing color for the lines. In this case, we'll use black, which has a
red, green, and blue color value of 0:
<?php
$image_height = 100;
$image_width = 300;
?>
<?php
$image_height = 100;
$image_width = 300;
/ r- • /
And you can send the image back to the browser and then destroy the image this way:
<?php
$image_height = 100;
$image_width i=#300;
$draw_color = imagecolorallocate($image, 0, 0, 0) ;
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
?>
Here's what a Web page, phpline.html, that displays the lines created by phpline.php
looks like:
<html>
<head>
<title>
Drawing lines
</title>
</head>
<body>
<hl>
Drawing lines
</hl>
These lines were drawn on the server:
<br>
<img src="phpline.php''>
</body>
</html>
You can see the results in Figure 14-3, where the lines created by phpline.php appear in
an HTML page. Cool.
You can adjust the parameters of lines like these; for example, you can draw thicker
lines, and that's coming up next.
510 PHP: The Complete Reference
imagesetthickness(image, thickness)
When you call this function and pass an image to it, it sets the drawing width for that
image, in pixels. For example, you might set the thickness of lines in phpline.php to 6 pixels
(instead of the default 1 pixel) like this in phpthickline.php:
<?php
$image_height = 100;
$image_width = 300;
imagedestroy($image);
?>
Chapter 14: Drawing Images on the Server 511
Here's what a Web page, phpthickline.html, that displays the thicker lines created by
phpthickline.php might look like:
<html>
<head>
<title>
Drawing thick lines
</title>
</head>
<body>
<hl>
Drawing thick lines
</hl>
These thick linos were drawn on the server:
<br>
<img src="phpthickline.php">
</body>
</htmi>
And You can see the results in Figure 14-4, where the thick lines appear in an HTML
page.
Drawing Rectangles
You can draw plenty of figures using lines alone, but there are far more GD functions to
consider. One of them, imagerectangle, draws rectangles:
This function creates a rectangle of color color in image image starting at upper-left
coordinate xl, yl and ending at bottom-right coordinate x2, y2.
Here's an example, phprectangle.php, which draws a number of rectangles:
<?php
$image_height = 100;
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
?>
And here's how you might embed those rectangles in a Web page, phprectangle.html:
<html>
<head>
<title>
Drawing rectangles
</title>
</head>
<body>
<hl>
Drawing rectangles
</hl>
These rectangles were drawn on the server:
<br>
<img src="phprectangle.php">
</body>
</html>
You can see the results in Figure 14-5, where the rectangles appear.
Chapter 14: Drawing images on the Server 513
Drawing Ellipses
Want to draw circles or ellipses? Use the imageellipse function:
Here's how it works. This function draws an ellipse centered at cx, cy in the image
represented by image. The w and h values specify the ellipse's width and height,
respectively. The color of the ellipse is specified by color. This function is pretty close to
imagerectangle, but instead of specifying the upper-left and lower-right corners, you specify
the center of the ellipse, and its width and height.
Here's an example, phpellipse.php, which draws ellipses:
<?php
$image_height = 100;
$image_width = 300;
header(’Content-Type: image/jpeg');
514 PHP: The Complete Reference
imagejpeg($image);
imagedestroy($image);
And here's how you can embed those ellipses in a Web page, phpellipse.html:
<html>
<head>
<title>
Drawing ellipses
</title>
</head>
<body>
<hl>
Drawing ellipses
</hl>
These ellipses were drawn on the server:
<br>
<img src="phpellipse.php">
</body>
</html>
You can see the results in Figure 14-6, where the ellipses appear.
Drawing Arcs
How about arcs? The imagearc function lets you draw arcs, which include partial circles
and partial ellipses, as well as complete circles and ellipses:
This function is designed to draw arcs centered at cx, cy in the image represented by
image. The w and h values specify the ellipse's width and height, respectively, while the
start and end points are specified in degrees indicated by the s and e arguments (here, 0° is
located at the three-o'clock position), me arc itself is drawn clockwise.
Here's how you can draw a smiley face using arcs:
<?php
$image_height = 100;
$image_width = 300;
$drawing_color = imagecolorallocate($image, 0, 0, 0) ;
imagejpeg($image);
imagedestroy($image);
516 PHP: The Complete Reference
Here's what the HTML page, phparc.html, that displays these arbs looks like:
<html>
<head>
<title>
Drawing arcs
</title>
</head>
<body>
<hl>
Drawing arcs
</hl>
These arcs were drawn on the server:
<br>
<img src="phparc.php">
</body>
</html>
Drawing Polygons
If you want to draw your own figures, you can trace them together using multiple lines if
you want, but there's an easier way; you can use the imagepolygon function to draw a
polygon simply by passing it an array of points. Here's how you use this function in
general:
This function creates a polygon in an image. The points parameter is an array containing the
polygon's vertices, (points[0] = xO, points[ 1] = y0, points[2] = xl, points[3] = yl, and so on).
The num__points parameter holds the total number of points in the polygon, and color is the
drawing t:blor you want to use.
This is a good function for drawing complex figures—all you have to do is to supply the
vertices of the polygon in an array, such as an array named $points:
$points = arrer/(
0 => 120, 1 => 60,
2 => 130, 3 => 60,
4 => 150, 5 => 80,
6 => 170, 7 => 40,
8 => 150, 9 => 40,
10 => 110, 11 => 20,
12 => 110, 13 => 90
) ;
Here s what that array looks like in phppolygon.php, which uses imagepolygon:
<?php
$points = array(
0 => 120, 1 => 60,
2 => 130, 3 => 60,
4 => 150, 5 => 80,
6 => 170, 7 => 40,
8 => 150, 9 => 40,
10 => 110, 11 => 20,
12 => 110, 13 => 90
) ;
$image_height = 100;
$image_width = 300;
header(’Content-type: image/jpeg1);
imagejpeg($image);
imagedestroy($image);
?>
Here's what the HTML page, phpolygon.html, that displays this polygon looks like:
<html>
<head>
<title>
518 PHP: The Complete Reference
Drawing polygons
</title>
</head>
<body>
<hl>
Drawing polygons
</hl>
This polygon was drawn on the server:
<br>
<img src="phppolygon.php">
</body>
</html>
Filling in Figures
In addition to just drawing figures in outline, you can also fill in figures with color using
various functions that draw filled-in figures, such as these:
This function creates a filled rectangle of color color in image image starting at upper-left
coordinate xl, yl and ending at bottom-right coordinate x2, y2.
Here's an example putting imagefilledrectangle to work, modifying our earlier example
phprectangle.php into phpfilledrectartgle.php. The difference is that this version fills its
rectangles in color—red in this case. Here's what the code looks like:
<?php
. , t ‘ 4
$image_height = 100;
$image_width = 300;
imagejpeg($image);
imagedestroy($image);
?>
Here's the HTML page, phpfilledrectangle.html, that displays these filled rectangles:
<html>
<head>
<title>
Drawing filled rectangles
</title>
</head>
<body>
<hl>
Drawing filled rectangles
</hl>
These filled rectangles was drawn on the server;
<br>
<img src="phpfilledrectangle.php">
</body>
</html>
The filled rectangles that this example draws appear in Figure 14-9. They're in black and
white here, but on the screen, they're red. Nice.
520 PHP: The Complete Reference
imagesetpixel(image, x, y, color)
As you'd expect, this function draws a pixel at x, y in image image of color color.
Here's an example, phppixel.php, which draws a dotted line using imagesetpixel. To
draw that line, this example simply uses a for loop:
}
Here's what this for loop looks like in phppixel.php:
<?php
$image_height = 100;
$image_width = 300;
}
Chapter 14: Drawing Images on the Server 521
header("Content-type: image/jpeg");
imagejpeg($image);
And here is the HTML page, phppixel.html, that displays these pixels:
/• *
<html>
<head>
<title>
Drawing pixels
</title>
</head>
<body>
<hl>
Drawing pixels
</hl>
These pixels were drawn on the server:
<br>
<img src="phppixel.php">
</body>
</html>
Drawing Text
How about drawing text? There are a number of functions that draw text, such as
imagestring:
This function draws the string s in the image specified by image with the upper-left corner at
coordinates x, y in color color. The graphics package comes with Ipuilt-in fonts—it font is 1, 2,
3, 4, or 5, a built-in font is used. You can also register your own fonts with the GD2 package
using the imageloadfont function. Note that since we're working with graphics, this text is
drawn as an image, not as editable text such as would appear in a text field.
Say you wanted to display some text centered in an image in an example, phptext.php.
You might want to use font number 4, and display the text "No troubles.":
<?php
$fontnumber = 4;
■p >
How can you adjust the size of the image to center this text? You can make the image
twice as wide as the text, using the imagefontwidth function to determine the width of each
character in your font, and multiplying by 2 * strlen(Stext) to find the width the image
should be:
<?php
$font_number = 4;
■? >
And you might make the image three times as high as the text is—which you can find
out with the imagefontwidth function:
<?php
$font_number = 4;
/'■ /
?>
Next, you can create the image and the background and drawing colors:
<?php
$font_number = 4;
$height = 3 * imagefontheight($font_number);
»
?>
Next, you can find the x and y positions at which to start the text so that it will appear
centered in the image:
?php
$font_number = 4;
$height = 3 * imagefontheight($font_number);
And then you can draw the text, like this in phppixel.php:
<?php
$font_number =4; v . t
$height = 3 * imagefontheight($font_number);
imagejpeg($image);
imagedestroy($image);
?>
And here is the HTML page, phptext.html, that displays the new text:
<html>
<head>
<title>
Drawing text
</title>
</head>
<body>
<hl>
Drawing text
</hl>
This text was drawn on the server:
Chapter 14: Drawing Images on the Server 525
<br>
<img src="phptext.php">
</body>
</html>
The centered text that this example draws appears in Figure 14-11.
This function draws the string s vertically in the image specified by image at coordinates
x, y in color color. If font is 1, 2, 3, 4, or 5, a built-in font is used. You can also register your
own fonts with the GD2 package using the imageloadfont function.
Here's an example, phpverticaltext.php, which draws some vertical text. It starts by
selecting a font number and setting the text to display:
<?php
$font_number = 4;
$text = "No troubles.";
9>
526 PHP: The Complete Reference
You have to then determine the dimensions of the image in which to display the text.
For example, you. can make the image width three times the height of the font you ve
selected, and make the image height twice the width of the text that's going to be displayed,
as well as selecting a red drawing color:
<?php
$font_number = 4;
$text = "No troubles.";
k 1
$width = 3 * imagefontheight($font_number);
?>
That creates the image and selects the drawing color. You can center the image with a
little math, and draw the text using imagestringup this way:
<?php
$font_number = 4;
$text = "No troubles.";
$width = 3 * imagefontheight($font_number);
And you can send the new image to the browser this way in phpverticaltext.php:
<?php
/r- •
$font_number = 4;
$text = "No troubles.";
imagejpeg($image);
imagedestroy($image);
?>
<html>
<head>
<title>
Drawing vertical text
</title>
</head>
<body>
<hl>
Drawing vertical text
</hl>
This text was drawn on the server:
<br>
<img src="phpverticaltext.php">
</body>
</html>
The vertical text that this example draws appears in Figure 14-12. Cool.
528 PHP: The Complete Reference
This is great when you want to embed images in Web pages but also want to add
something to them yourself, such as a copyright notice. You can add an image of yourself,
or a logo, inside another image. As an example, we'll use imagecreatefromjpeg here, loading
an existing JPEG image, image.jpg, and adding a smiley face and a border to it. Here's how
you use this function:
This function returns an image identifier representing the image obtained from the
given filename, and it returns an empty string on failure.
We're going to modify the JPEG image you see in Figure 14-3, image.jpg, adding the
smiley face you created earlier in the chapter, as well as a border around the whole image.
Chapter 14: Drawing Images on the Server 529
,r- 1
Hi there!
Figure 14-13 A JPEG image that will be modified
I 4
The PHP file, phpjpg.php, starts as you'd expect, by creating an image in memory from
the file image.jpg:
<?php
?>
That loads the image, image.jpg, into the object $image (in practice, don't forget to add
error-handling code in case PHP can't find your image file). You can draw a border inside
this image—but it would help if you knew the image's dimensions.
You can find those dimensions with the imagesx and imagesy functions, which return
the x and y size of an image. And you can use the imagerectangle function to create the
border; here's how to draw that border ten pixels inside the image:
<?php
?>
And you can add the smiley face to the image as well like this in phpjpg.php:
<?php
$image = imagecreatefromjpeg ("image.jpg");
imagejpeg($image);
imagedestroy($image);
Here is the HTML page, phpjpg.html, that displays the modified image:
<html>
<head>
<title>
Using images
</title>
</head>
<body>
<hl>
Using images
</hl>
This image was modified on the server:
<br>
<img src="phpjpg.php">
</body>
</html>
And you can see the result in Figure 14-14, where the original JPEG image was modified
as you wanted.
Chapter 14: Drawing Images on the Server 531
Tiling Images
You can also use one image to tile another image, by appearing repeatedly in the background,
with the imagesettile function. Here's how you use this function:
imagesettile(image, tile)
This function sets the tile image to be used by all region-filling functions (such as
imagefilledrectangle and imagefilledpolygon) when filling with the special color IMG_
COLOR_TILED.
How about an example? This script, phptile.php, starts by creating an image that will be
tiled. Here, we'll use imagecreatetruecolor to give the created image the full range of colors
possible, rather than imagecreate, which might inadvertently restrict the number of colors
available in the tiles (when there's any doubt about restricting colors, you should use
imagecreatetruecolor instead of the more simple imagecreate):
<?php
$image_width = 300;
$image_height = 200;
Now we'll create the tile. Stile, that will appear inside the image stored in $image. In
this case, we can tile the smiley-face image you just sa w created by first reading in image,
jpg with imagecreatefromjpeg:
<?php
$image_width =300;
$image_height = 200;
?>
You can add the smiley face to this tile with imagearc:
<?php
$image_width = 300;
$image_height = 200;
>
That completes the creation of the tile image, and you can set Stile as the tile for Simage
with imagesettile:
< ?php
$image_width = 300;
$image_height = 200;
imag^earc ($tile, 65, 42, 10j« 10, -10, 190, $drawing color);
imagesettile($image, $tile);
4
?>
And you can now draw a filled rectangle that will use this tile if you set the fill style to
IMG_COLOR_TILED:
<?php
$image_width = 300;
$image_height = 200;
imagesettile($image, $tile);
?>
All that's left is to display the image and then destroy it in phptile.php:
<?php
$image_width = 300;
$image_height = 200;
imagesettile($image, $tile) ;
Header("Content-type: image/jpeg");
imagejpeg($image);
imagedestroy ($image);
imagedestroy ($tile);
And here is the HTML page, phptile.html, that displays the tiled image:
V ' '
<html>
<head>
<title>
Tiling images
</title>
</head>
<body>
<hl>
Tiling images
</hl>
This image was tiled on the server:
<br>
<img src="phptile.php">
</body>
</html>
And you can see the result in Figure 14-15, where the tiled image appears.
Copying Images
There's more graphics manipulation power available; for example, the imagecopy function
lets you c6py all of, or part of, an image:
<?php
$image_original = imagecreatefromjpeg("image.jpg");
$image_width = imagesx($image_original);
$image_height = imagesy($image_original);
?>
Here's where you can flip the image, which the code does by copying the original image
over and flipping it, pixel by pixel, into the flipped image:
Here is the HTML page, phpflip.html, that displays the flipped image:
<html>
<head>
<title>
Flipping images
</title>
</head>
You can see the result in Figure 14-16, where the flipped image appears.
Creating XML
How do you create XML on the server and send it back to the browser? As you recall, we
tackled this problem in Chapter 12, where we created some XML and sent it to the browser.
We'll take a look at this script, phpitems.php, here.
The key point when creating XML in PHP is to set the content-type header to an XML
type, such as text/xml:
<?php
header("Content-type: text/xml");
9 >
This example let you construct two XML documents, depending on whether the items
parameter you pass to it holds "1" or "2". Here's what you get with "1":
537
538 PHP: The Complete Reference
<item>Cheese</item>
<item>Salami</item>
</items>
In phpitems.php, this is how you handle the items parameter—by using one of two
different arrays of data:
<?php
header("Content-type: text/xml");
v ' '
if ($_REQUEST["items"] == "1")
$items = array('PHP book', 'Television', 'Radio');
if ($_REQUEST["items"] == "2")
$items = array('Soda', 'Cheese', 'Salami');
?>
Now you have to echo the document's XML declaration, <?xml version="1.0" ?>,
required for all XML documents (legal versions currently are only 1.0 or 1.1):
<?php
header("Content-type: text/xml");
if ($_REQUEST["items"] == "1")
$items = array(1PHP book1, 'Television1, 'Radio');
if ($_REQUEST["items"] == "2")
$items = array('Soda', 'Cheese', 'Salami');
?>
The document element, <items>, contains all the other elements, as is always the case
for document elements in XML documents:
<?php
header("Content-type: text/xml");
if ($_REQUEST["items"] == "1")
$items = array('PHP book', 'Television', 'Radio');
if ($_REQUEST["items"] == "2")
$items = array('Soda', 'Cheese', 'Salami');
echo '<items>';
Chapter 15: XML and RSS 539
?>
/'• /
And you re free to echo the data in the $items array to the browser in <item> elements,
and then end the XML document by closing the document element with an </items> tag:
<?php t•*
header (" Content -type : text/xml") ;
if ($_REQUEST["items"] == "1")
$items = array('PHP book', 'Television', 'Radio');
if ($_REQUEST["items"] == "2")
$items = array('Soda', 'Cheese', 'Salami');
echo '<items>';
You can take a look at this script by passing it a value for the items parameter, as in this
URL: http://localhost/chl5/phpitems.php?items=l. The results appear in Figure 15-1,
where you can see our XML.
Cool.
Creating RSS
An XML dialect that is very common to use with PHP is RSS—Really Simple Syndication,
which lets you distribute news feeds that people can take a look at in RSS readers. That's
something you'll often see in PHP, because using PHP, you can automate the RSS-creation
process. For example, you can write a PHP script to scan your blog and create an RSS feed
from it.
Here's an example that creates an RSS feed, phprss.php. For simplicity, we'll embed the
RSS data in this example script, but of course it could scan a bjog or any other file to get the
news items.
This script has to supply a title, an URL, and a description fot each news item;
here's the RSS document we're going to create in this example, which will be readable
by RSS readers:
<item>
<title>Snow in August</title>
<link>http://url</link>
<description>It1s snowing in August. Is this still the northern
hemi sphere ?</description
</item>
<item>
<title>Trees are green</title>
<link>http://url</link>
<descriptionScientists determine that trees are green. Sky suspected to be
blue.</description>
</item>
<item>
<title>Stock market goes up and down</title>
<link>http://url</link>
<description>Yes, the stock market went up and down today. Like
always.</description>
</item>
</channel>
</rss>
Chapter 15: XML and RSS 541
You can create a multidimensional array, $items, to hold the data in the news items in
phprss.php:
<?php ,r. . /
$items[0] = array('Snow in August',
'http://url',
"It's snowing in August. Is this still the northern hemisphere?"
) ;
/ • *
?>
You can also set up the document by using the header function to make it XML, as well
as including XML and RSS declarations; in this case, we're going to use RSS version 2.0, the
current version:
<?php
$items[0] = array(1 Snow in August1,
'http://url',
"It's snowing in August. Is this still the northern hemisphere?"
) ;
header('Content-type: text/xml');
?>
And you can echo the <channel>, <title>, and other elements that start the document off:
<?php
$items[0] = array('Snow in August',
'http://url',
"It's snowing in August. Is this still the northern hemisphere?"
542 PHP: The Complete Reference
header('Content-type: text/xml1);
t • •
echo '<channel>';
Finally, you can echo the actual data in the feed, and end the document:
<?php
$items[0] = array('Snow in August',
'http://url',
"It's snowing in August. Is this still the northern hemisphere?"
) ;
echo '<webMaster>webmaster@url</webMaster>';
echo '</channel>';
You can see the RSS document this example, phprss.php, creates in Figure 15-2.
And you can take a look at our new RSS feed in an RSS reader in Figure 15-3.
Very cool. Now you re able to create RSS feeds using PHP that users can read in
RSS readers. 1' *
fc^^»WSa<^f*^g*iiiM8a88S8SS!S!i^«a«S83SS3S8883SSSa^!^ai^
You can use these functions to parse and edit XML documents on the fly. Here's the
XML document you'll see for the following few examples, event.xml. This XML document
lists an event, the National Awards event, and its attendees:
<?xml version="l.0"?>
<events>
<event type="fundraising">
<event_title>National AwardS</event_title>
<event_number>3</event_number>
<subject>Pet Awards</subject>
<date>5/5/2007</date>
<people>
<person attendance="present">
< firs t_name >June</first_name>
<last_name>Allyson</last_name>
</person>
<person attendance="absent">
<first_name>Virginia</first_name>
<1as t_name >Mayo </1a s t_name >
</person>
<person attendance="present">
<f irst_name>Jimmy</f irst__name>
<last_name>Stewart</last_name>
</person>
</people>
</event>
</events>
You can load this XML document into a SimpleXML object using the simplexmlJoad_
file function like this:
<?php
$xml = simplexml_load_file("event.xml");
?>
Now the document is loaded into the $xml object. Here's where the simple in SimpleXML
comes into play. Each element in event.xml—with the exception of the document element—
becomes a property of that object.
546 PHP: The Complete Reference
For example, say you wanted to extract the date from event.xml:
<?xml version="l.0"?>
<events>
<event type="fundraising">
<event_ti11e>National Awards</event_title>
<event_number>3</event_number>
<subject>Pet Awards</subject>
<date>5/5/2007</date>
<?php
$xml = simplexml_load_file("event.xml");
And you can see the results of this example in Figure 15-4, where the date has been
successfully extracted from event.xml.
The SimpleXML functions can also read XML data from a string if you pass that string
to the SimpleXMLElement constructor. For example, you might have a script that loads the
text in event.xml into a string named Sxmlstr:
<?php
$xmlstr = <<<XML
<?xml version="l.0"?>
<events>
<event type="fundraising">
<event_title>National Awards</event_title>
<event_number>3</event_number>
<subject>Pet Awards</subject>
<date>5/5/2007</date>
<people>
<person attendance="present">
<first_name>June</first_name>
<last_name>Allyson</last_name>
</person>
<person attendance^' absent">
<first_name>Virginia</first_name>
< 1 a s t^_name >Mayo < /1 a s t _name >
</person>
<person attendance="present">
<first_name>Jimmy</first_name>
<last_name>Stewart</last_name>
</person>
</people>
</event>
</events>
XML;
?>
<?php
include 'event.php';
o>
This introduces the $xmlstr into the code of phpxml2.php, and you can pass that string,
including the XML text it contains, to the SimpleXMLElement constructor:
<?php
include 'event.php';
?>
This creates the same object in $xml as if you had used the simplexml_load_file function,
passing that function event.xml. Now you can extract the data in the <date> element as before:
<?php
include 1 event.php';
echo $xml->event->date;
?>
How do you handle the case where a document has more than one of the same element?
For example, what if you wanted to extract the first and last names of each person from
these three <person> elements?
<?xml version="l.0"?>
<events>
<event type="fundraising">
< event_ti11e >Nationa1 Awards </event_ti11e >
<event_number>3</event_number>
<subject>Pet Awards</subject> '
<date>5/5/2007</date>
<people>
<person attendance="present">
<first_name>June</first_name>
<last_name>Allyson</last_naine>
</person>
<person attendances"absent">
<first_name>Virginia</first_name>
<last_name >Mayo</las t_name >
</person>
<person attendances"present">
<first_name>Jimmy</first_name>
<last_name>Stewart</last_name>
</person>
</people>
</event>
</events>
You can't just use the terminology $people->person—how would SimpleXML know what
<person> element you wanted? It turns out that SimpleXML handles this by letting you use
array terminology, like this: $people->person[0], $people->person[l], $people->person[2], and
so on, making things easy
You can loop over multiple elements of the same name using foreach as well. In this
example, we'll do exactly that to extract all the event attendees' names in phpparse.php.
This script starts by loading the event.xml file:
<?php
$xml = simplexml_load_file("event.xml");
?>
<?php
$xml = simplexml_load_file("event.xml");
echo "Here are the people who attended the event: <br>";
Chapter 15: XML and RSS 549
$event = $xml->event;
And you can get an object corresponding to the <people> element this way:
<?php ' 4
$xml = simplexml_load_file("event.xml");
echo "Here are the people who attended the event: <br>";
$event = $xml->event;
$people = $event->people;
?>
You can echo the people in an unordered list, so surround the code to display the people
with <ul> and </ul>:
<?php
$xml = simplexml_load_file("event.xml");
echo "Here are the people who attended the event: <br>";
$event = $xml->event;
$people = $event->people;
echo "<ul>";
echo "</ul>";
?>
And you loop over all <person> elements using a foreach loop, easily accessing the text
in the person's <first_name> and <last_name> elements this way ( is the HTML code
for a non-breaking space):
<?php
$xml = simplexml_load_file("event.xml");
echo "Here are the people who attended the event: <br>";
$event = $xml->event;
$people = $event->people;
echo "<ul>";
echo "</ul>";
?>
And you can see the results of this example in Figure 15-5, where people's names have
been extracted from event.xml.
Extracting Attributes
How about extracting attributes from a document using SimpleXML? Turns out that's
easy—you just use array notation.
For example, what if you wanted to extract the attendance attribute's value for each
<person> element?
<?xml version="1.0"?>
<events>
<event type="fundraising">
<event_title>National Awards</event_ti11e>
<event_number>3</event_number>
<subject>Pet Awards</subject>
<date>5/5/2007</date>
Chapter 15: XML and RSS 551
<people>
<perscn attendance="present">
<first_name>June</first_name>
r< , <last_name>AllyS)On</last_name>
</person>
<person attendance:"absent">
<first_name>Virgina</first_name>
<last_name>Mayo</last_name>
</pers<dr/>
<person attendance="present">
<first_name>Jimmy</first_name>
<last_name>Stewart</last_name>
</person>
</people>
</event>
</events>
You can extract the attendance attribute's value for a <person> element like this:
$person[’attendance'], where $person holds the <person> element. Here's an example,
phpattribute.php, that extracts the attendance attributes and displays them. As in the
previous example, phpparse.php, you can display each person—in this case, each person's
attendance—using an unordered HTML list:
<?php
$xml = simplexml_load_file("event.xml");
echo "Here are the people who attended the event: <br>";
$event = $xml->event;
$people = $event->people;
echo "<ul>";
echo "</ul>";
?>
<?php
$xml = simplexml_load_file("event.xml");
echo "Here are the people who attended the event: <br>";
$event = $xml->event;
$people = $event->people;
echo "<ul>";
552 PHP: The Complete Reference
You can see the results in Figure 15-6, where everyone's attendance attributes have been
extracted from event.xml. Cool.
Using XPath
XPath is an XML specification for a special language that lets you search XML documents.
A full discussion of XPath is beyond the scope of this book. Briefly, to use XPath, you consider
an XML document as a tree of nodes; here are the legal node types:
• element
• attribute
• text
• CDATA section
• entity reference
• entity
• processing instruction
Chapter 15: XML and RSS 553
When you execute an XPath expression on a node, that node is called the context node.
Here are a few XPath examples—say that you have this XML document:
<state>
<name>California</name>
<populati6n units="people">33871648</population><!--2000 census-->
<capital>Sacramento</capital>
<bird>Quail</bird>
<flower>Golden Poppy</flower>
<area units="square miles">155959</area>
</state>
<state>
< name >Massachusetts</name >
<population units="people">6349097</population><!--2000 census-->
<capital>Boston</capital>
<bird>Chickadee</bird>
<flower>Mayflower</flower>
<area units="square miles">7840</area>
</state>
<state>
<name>New York</name>
<population units="people">18976457</population><!--2000 census-->
<capital>Albany</capital>
<bird>Bluebird</bird>
<flower>Rose</flower>
<area units="square miles">47214</area>
</state>
</states>
Let's take a look at this in code. If you want to create an array of all <person>
elements—no matter where they are in the event.xml document—you can use the XPath
expression / /person. Here, then, is how you can loop over all <person> elements in event,
xml—without having to navigate to those <person> elements by working your way down
through the <event> and <people> elements:
<?php
$xml = simplexml_load_file("event.xml");
echo "Here are the people who attended the event: <br>";
echo "<ul>";
}
echo "</u1>";
?>
Chapter 15: XML and RSS 555
And you can list each person and their attendance at the event like this:
<?php
$xml = simplexml_load_file("event.xml");
echo "Here are the people who attended the event: <br>";
echo "<ul>";
echo "</ul>";
?>
You can see the results in Figure 15-7, where the XPath expression was successful in
extracting all <person>elements.
<?php
$xml = simplexml_load_file("event.xml");
echo "Here are the people who attended the event: <br>";
$event = $xml->event;
$people = $event->people;
?>
Then this example displays the text in each <person> element—which will be Myrna
Loy three times:
<?php
$xml = simplexml_load_file("event.xml");
echo "Here are the people who attended the event: <br>";
$event = $xml->event;
$people = $event->people;
echo "<ul>";
You can see the results in Figure 15-8, where every <person> element was indeed
changed to contain Myrna Loy.
As you can see, it's possible to make all elements contain Myrna Loy, but that's not the
best way to indicate that she attended the event. How about adding a Myrna Loy element,
instead of overwriting all the others?
Chapter 15: XML and RSS 557
<?xml version="1.0"?>
<events>
<event type="fundraising">
<event_title>National Awards</event_title>
<event_number>3</event_number>
<subject>Pet Awards</subject>
<date>5/5/2007</date>
<people>
<person attendance="present">
<first_name>June</first_name>
<last_name>Allyson</last_name>
</person>
<person attendance="absent">
<first_name>Virginia</first_name>
<1a st_name >Mayo</1a s t_name >
</person>
<person attendance="present">
<first_name>Jimmy</first_name>
<last_name>Stewart</last_name>
</person>
<person attendance="present">
< fir s tname>Myrna</firs t_name>
<1astname>Loy</1ast_name>
558 PHP: The Complete Reference
</person>
</peoplKe>
</event>
</events>
You start this new example, phpadd.php, by getting an object corresponding to the
<people> element:
<?php
$xml = simplexml__load_f ile ("event .xml") ; * '
echo "Here are the people who attended the event: <br>"
$event = $xml->event;
$people = $event->people;
You can add a <person> element as a child of the current <people> element using the
addChild method:
<?php
$xml = simplexml_load_file("event.xml");
$event = $xml->event;
$people = $event->people;
?>
And you can add <first_name> and <last_name> child elements to the new <person>
element like this, specifying the text data for each new child element:
<?php
$xml = simplexml_load_file("event.xml");
echo "Here are the people who attended the event: <br>";
$event = $xml->event;
j t. I
$people = $event->people;
$person = $people->addChild('person') ;
$person->addChild*(1firstname1, 'Myrna1);
$person->addChild(1lastname', 'Loy');
>
Finally, you can add a new attendance attribute to the <person> element with the
addAttribute method, and then display all the elements:
<?php
$xml = simplexml_load_file("event.xml");
echo "Here are the people who attended the event: <br>";
$event = $xml->event;
$people = $event->people;
$person = $people->addChild('person');
$person->addChild('first_name', 'Myrna');
$person->addChild(1last_name', 'Loy');
echo "<ul>";
You can see the results in Figure 15-9, where the new Myrna Loy <person> element
was added.
560 PHP: The Complete Reference
<?php
$xml = simp1exml_load_file("event.xml");
$event = $xml->event;
$people = $event->people;
$person->addChild('first_name', 'Myrna');
$person->addChild('last_name', 'Loy');
$person->AddAttribute('attendance', 'present');
header("Content-type: text/xml");
echo $xml->asXML();
Chapter 15: XML and RSS 561
You can see the results in Figure 15-10, where this script did indeed send the complete
XML document to the browser. Very useful.
<?php
$dom = new domDocument;
?>
Then it loads an XML text string into the DOM object using the loadXML method:
<?php
$dom = new domDocument;
562 PHP: The Complete Reference
$dom->loadXML(
' <people>*gersonxf irst_name>Myrna</f irst_name></personx/people>') ;
>
You can check if the DOM object was indeed created successfully:
$dom->loadXML(
' <peoplexpersonxf irst_name>Myrna</f irst_namex/personx/people> ') ;
if (! $dom) {
echo 'Error';
exit;
}
?>
That creates a DOM object, with its own methods and properties. You can convert that
into a SimpleXML object using the simplexml_import_dom function, and then dump the
object as XML back to the browser:
<?php
$dom = new domDocument;
$dom->loadXML(
1 <peoplexpersonxf irst_name>Myrna</f irst_namex/personx/people> ') ;
if (!$dom) {
echo 'Error';
exit ;
$xml = simplexml_import_dom($dom);
header("Content-type: text/xml");
echo $xml->asXML();
?>
You can see the results in Figure 15-11, where this script converted a PHP XML DOM
object into a SimpleXML one.
Chapter 15: XML and RSS 563
<?php
$file = "event.xml";
9 >
One thing that the XML Parser functions don't handle is the XML declarations at the
beginning of each XML document, so we'll print out a standard XML declaration (the PHP
documentation for the XML Parser functions say that you can use a default handler—
coming up soon—to read XML declarations, but in fact that does not work):
<?php
$file = "event.xml";
Next, you create an XML parser object, using the xml_parser_create function:
<?php
$file = "event.xml"; /
/ r‘ •
Next, you have to register your callback functions with the XML parser object. These are
the functions that will handle the elements, attributes, text, and so on encountered by the
parser as it reads through the XML document.
For example, to set the handler functions that will handle the beginning and end of
elements, you use the xml_set_element_handler function. You pass the XML parser object to
this function, as well as the callback function you want to handle the start of elements,
startElement here, as well as the function to handle the end of elements, endElement here:
<?php
$file = "event.xml";
$xml_parser_object = xml_parser_create();
9 >
To handle the text data inside the elements, you register a callback function with the XML
parser using the xml_set_character_data_handler function, and well use a function named
text here. And to handle any other data that the XML parser encounters that you haven't set
up a handler for, you can register a default handler with the xml_set_default_handler
function. That default handler for us is going to be a function called defaultHandler:
<?php
$file = "event.xml";
$xml_parser_object = xml_parser_create();
xml_set_default_handler($xml_parser_object, "defaultHandler");
v ' *
You're responsible for opening the XML document and feeding it to the parser, so you
start the process by opening the XML document and getting a file handle for it, $handle:
<?php
$file = "event.xml";
?>
Now you can read in some XML data, 1024 bytes at a time, with fread:
<?php
$file = "event.xml
xml_set_default_handler($xml_parser_object, "defaultHandler");
}
}
Chapter 15: XML and RSS 567
You pass the XML data to the XML parser's xml_parse function, passing it the XML
parser object, the text data to parse, and a TRUE/FALSE argument that indicates whether
or not you've passed all the XML data to xml_parse. You can determine if you've passed all
the data *6 xml_parse with feof, so hire's how you pass the XML data to the parser:
<?php
$file = "event.xml";
i ■ *
xml_set_defauit_handler($xml_parser_object, "defaultHandler");
}
}
9 >
If xml_parse returns a value of FALSE, there was an error. You can determine what the
error was with the xml_error_string function, to which you pass the error code—-and you
can get the error code by passing the XML parser object to the xml_get_error_code function.
You can also get the line number in the XML document at which the error occurred with the
xml_get_current_line_number function, and display that as well:
< ?php
$file = "event.xml";
}
}
568 PHP: The Complete Reference
At this point, the parser will call your callback functions. All that's left—besides writing
those callback functions—is to finish with the parser by calling xml_parser_free and closing
the XML document with fclose:
<?php
$file = "event.xml";
}
}
xml_parser_free($xml_parser_object);
fclose($handle);
?>
We'll start with the defaultHandler function, which handles any XML data not handled
by the other handlers you may have set up. We've registered a default handler function
named defaultHandler with the XML parser; the defaultHandler function is passed the
parser object and the unhandled XML text, so we'll just echo that text to the browser:
<?php
$file = "event.xml";
That handles any XML data not handled by our other handlers. You can set up the
startElement and endElement handlers next. The startElement handler is called when the
parser encounters the opening tag of an XML element. The parser object, name of the
element, and a hash containing its attributes is passed to startElement.
Chapter 15: XML and RSS 569
We're going to indent the parsed XML, and we'll keep track of the indentation level
with a variable named $indent. The first order of business in startElement is to echo the
indentation whitespace—two non-breaking spaces for each level of indentation:
<?php '
$file = "event.xml";
$indent = 0;
!■*
}
?>
The XML parser converts all element names to uppercase, but they're actually
lowercase in event.xml, so we'll convert the name of each element back to lowercase
with strtolower:
<?php
$file = "event.xml";
$indent = 0;
{
global $indent;
for ($i = 0; $i < $indent; $i++) {
echo " ";
}
$lower = strtolower($name);
}
?>
The attributes of the current XML element, if any, are passed to startElement in a hash
we've named $attrs, where the keys are the names of the attributes and the values are the
570 PHP: The Complete Reference
attribute values. You can loop over that hash like this, assembling a text string that holds
the attributes and their values like this: "attrl = valuel attr2 = value2 ...":
<?php
$file = "event.xml";
$indent = 0;
}
?>
All that's left is to echo the opening tag of the current element—complete with
attributes and their values—to the browser, and then increase the indentation level for
any nested elements:
<?php
$file = "event.xml";
$indent = 0;
}
echo "<${lower} ${att_string}> <br>";
$indent++;
}
Chapter 15: XML and RSS 571
That handles the start tag of elements—how about the end tag? That's handled by a
function we've called endElement, which is called when the parser encounters the end tag
of an element. First, we display the indentation string in endElement:
<?php
function endElement($parser, $name)
{
global $indent;
$indent--; / < *
for ($i =0; $i < $indent; $i++) {
echo " ";
}
?>
Then we display the element's closing tag, after first converting the element name back
to lowercase:
<?php
function endElement($parser, $name)
{
global $indent;
$indent--;
for ($i =0; $i < $indent; $i++) {
echo "
}
$lower = strtolower($name);
echo "</${lower}> <br>";
}
?>
Okay, we've handled opening and closing tags for XML elements. The final task in
this example is to handle the text inside every element, which is done in the function
we've called text. This function is passed the parser object and the text the parser has
encountered:
<?php
function text($parser, $text)
?>
572 PHP: The Complete Reference
The text method gets passed all the non-markup text in' the XML document—and that
includes the whitespace used for indentation in that document. For example, take a look at
event.xml:
<?xml version="l.0"?>
<events>
<event type="fundraising">
< event_ti11e >Nationa1 Awards </event_ti11e >
<event_number>3</event_number>
<subject>Pet Awards</subject> v . i
<date>5/5/2007</date>
<people> i
<person attendance="present">
<first_name>June</first_name>
<1a s t_name >A1lys on</1as t_name >
</person>
</events>
Note the whitespace between the <events> tag and the <event> tag—that's reported as
text to our text function. As is the text between the <event> and <eventtitle> tags, and so on.
We don't want to display this whitespace in our parsed version of this file—we're handling
the indentation ourselves. To avoid responding to text that's purely whitespace, you can use a
regular expression. In particular, you can insist that at least one non-whitespace character
(which you can check with the regular expression "/S") must appear in the text passed to us
before we'll display it like this:
<?php
function text($parser, $text)
{
if(preg_match("/\S/", $text)){
}
}
Now you can echo the indentation string and echo the non-whitespace text the
parser found:
<?php
function text($parser, $text)
{
global $indent;
if(preg_match("/\S/", $text)){
Chapter 15: XML and RSS 573
Okay, that completes the XML parser. You can see it at work in Figure 15-12, where the
entire parsed version of event.xml appears. Excellent.
That completes this example, and that also completes our book on PHP. Happy
programming!
'
.
/
Index
Symbols access modifiers, 253
$a & $b operator, 52 accessor methods, 252
$a A $b operator, 52 acos function, 43
$a | $b operator, 52 acosh function, 43
$a « $b operator, 52 action attributes, 162
$a » $b operator, 52 Adabas, 361
$items array, 541 addAttribute method, 559
%= operator, 47 addChild method, 558
&= operator, 47 addcslashes function, 82
*= operator, 47 addslashes function, 82
.= operator, 47 advanced e-mails, 418-421
/= operator, 47 Ajax (Asynchronous JavaScript and XML),
\n control character, 17 433-500
A= operator, 47 concurrent requests
| = operator, 47 JavaScript inner functions,
~ $a operator, 52 475-479
+= operator, 47 multiple XMLHttpRequest
«= operator, 47 objects, 467-472
-= operator, 47 XMLHttpRequest arrays,
»= operator, 47 472-475
connecting to other domains, 494-496
downloading
images, 479M81
abort method, 438-439
JavaScript, 481-484
abs function, 43
GET method, 450-453
abstract classes, 294-297
Google Suggest, 484-494
access
handling downloaded data,
class member, 264-266
441M45
MySQL database
head requests, 497-500
closing connection, 376-377
logging in, 495-497
connecting to database, 372
overview, 433-434
connecting to server, 371-372
PHP and, 448-449
displaying table data, 374-376
POST method, 453-456
overview, 370-371
starting downloads, 445-447
reading tables, 372-374
warning dialogs, 489
to properties and methods, 253-257
575
576 PHP: The Complete Reference
PROGRAMMING/PHP
$49.99 usa
Osborne £28.99 UK
www.osborne.com $54.95 CAN