Web Application Design and Implementation
Web Application Design and Implementation
and Implementation
www.allitebooks.com
•• e T ..
~I t 807 ~
=1~WlLEY:
:12007 ;
-;
• '
. l e . . . T ..... I ...
.
r
<S achgeneration has its unique needsand aspirations. When Charles Wiley first
opened his small printing shop in lower Manhattan in 1807, it was a generation
of boundless potential searching for an identity. And we were there, helping to
define a new American literary tradition. Over half a century later, in the midst
of the Second Industrial Revolution, it was a generationfocusedon building the
future. Once again, we werethere,supplyingthe criticalscientific,technical,and
engineering knowledge that helped frame the' world. Throughout the 20th
Century, and into the :new millennium, nations began to reach out beyond their
own borders and a new international community was born. Wiley was there,
expanding its operationsaround the world to enable a global exchangeof ideas,
opinions, and know-how.
For 200 years, Wiley has been an integral part of each generation's journey,
enablingthe flowof information and understanding necessaryto meet their needs
and fulfill their aspirations. Today, bold new technologies are changing the way
we live and learn. Wiley will be there, providing you the must-have knowledge
you need to imaginenew worlds, new possibilities, and new opportunities.
Generations come and go, but you can always count on Wiley to provide you the
knowledge you need,when and whereyou need it!
Lu~';'~~.~ ~~u~
WILLIAM .... PESCE PETER BaaTH WILEY
PRESIDENT AND CHIEF' EXECUTIVE DFFlCER CHAIRMAN OF" THE BOARD
www.allitebooks.com
Web Application Design
and Implementation
Apache 2, PHP5, MySQL,
JavaScript, and Linux/UNIX
Steven A. Gabarro
Stevens Institute of Technology
Hoboken, New Jersey
IEEE
~computer
SOciety
60TH anniversary
"'
BICENTENNIAL
it807~
.
=~WILEY=z
.-
z
:2007~
,.~
BICENTENNIAL
WILEY-INTERSCIENCE
A John Wiley & Sons, Inc., Publication
www.allitebooks.com
Copyright © 2007 by John Wiley & Sons, Inc. All rights reserved.
Limit of Liability/Disclaimer of Warranty: While the publisher and author have used their
best efforts in preparing this book, they make no representations or warranties with respect
to the accuracy or completeness of the contents of this book and specifically disclaim any
implied warranties of merchantability or fitness for a particular purpose. No warranty may be
created or extended by sales representatives or written sales materials. The advice and
strategies contained herein may not be suitable for your situation. You should consult with a
professional where appropriate. Neither the publisher nor author shall be liable for any loss
of profit or any other commercial damages, including but not limited to special, incidental,
consequential, or other damages.
For general information on our other products and services or for technical support, please
contact our Customer Care Department within the United States at (800) 762-2974, outside
the United States at (317) 572·-3993 or fax (317) 572-4002.
Wiley also publishes its books in a variety of electronic formats. Some content that appears
in print may not be available in electronic formats. For more information about Wiley
products, visit our web site at www.wiley.com.
www.allitebooks.com
Contents
Preface xiii
About the Author / xiii
Before We Get Started I xiii
Who Should Read This Book? I xiv
About the Examples I xiv
How to Read This Book I xiv
Acknowledgments xv
www.allitebooks.com
vi CONTENTS
1. Fundamentals 5
The Origins of the Internet I 5
The World Wide Web I 6
The Web Browsers I 7
The Web Servers I 7
TCP/IP BASICS I 8
The Internet Layer I 9
The Transport Layer I 11
The Application Layer I 11
The Toolbox I 12
Browsers I 12
FTP I 13
Email Clients I 14
Programming Tools I 14
Other Useful Tools I 15
3. Introduction to HTML 27
What Do You Need to Get Started? I 27
How Does HTML Work? I 28
Syntax Basics / 28
File Structure I 28
Tag Parameters I 30
Basic Text Formatting I 30
External References I 32
Links I 32
Images I 33
www.allitebooks.com
CONTENTS vii
Organizing Data / 34
Lists / 35
Tables / 36
Frames / 39
Special Characters I 43
4. Work Environment 45
Introduction I 45
Downloading the Software I 45
Installing the Apache Server I 46
Installation Steps I 46
Checking the Installation I 47
Possible Errors I 47
Configuring Apache I 48
Installing PHP5 I 48
Testing PHP I 50
Installing MySQL I 50
Adding a MySQL User I 51
How Do I Know if MySQL is Running? I 51
Installing PhpMyAdmin I 51
Installing a Bulletin Board: phpBB I 52
Installation Steps I 52
Basic Security Considerations I 54
Conclusion I 55
www.allitebooks.com
viii CONTENTS
Multidimensional Arrays / 71
Array Functions / 74
PHP Program Structure and Flow of Control / 77
Conditions / 77
Loops / 80
Functions / 82
www.allitebooks.com
CONTENTS ix
www.allitebooks.com
X CONTENTS
www.allitebooks.com
CONTENTS xi
Bibliography 269
Index 271
Preface
Steven Gabarr6 was born in 1979 and raised in Alicante, Spain. He started
programming early, learning BASIC (Beginner's All-purpose Symbolic
Instruction Code) at age 9. Later on, in high school, he learned Turbo Pascal
and C. At that point it was pretty obvious that he was going to end up as a
computer scientist. He ended up studying for a master's degree in computer
science in the Ecole Pour l'Informatique et les Techniques Avancees, where
he specialized in advanced multimedia and Web technologies, graduating
with honors, finishing third in his class. He went to the United States in
January 2002, enrolling in the Masters of Science in Information Systems at
the Stevens Institute of Technology, in Hoboken, New Jersey. There he quickly
advanced from teaching assistant to full-time instructor. On his appointment
as full-time faculty, he created the first Web programming course at Stevens,
based on his personal experiences. This book is the result of that course, and
is a close reflection of what Steven teaches his students.
The way this book is organized, it should be ideal for anyone trying to learn
how to create complete Websites with no previous knowledge of any of the
languages presented. It does require some minimum knowledge of program-
ming in general, as well as object-oriented programming basics to understand
Chapter 8.
It is also a good read for Web designers that know about making pages
look nice, but have no knowledge of how to create dynamic pages built
through a database or anyone who would like to pick up on the art of pro-
gramming pages. Realize: that I have never been a good graphic designer, so
this book will not tell you how to do things like making decisions regarding
the proper colors, fonts, or sizes to use, or other cosmetic details. I will deal
with how to set those features up, but will not tell you how to pick your layout
or color schemes, because I am definitely not good at it. Instead, I will con-
centrate on how to actually program useful pages with loads of functionality.
All the examples have been tested, and if any are not compatible with a spe-
cific browser, this will be stated in the text. You can find all the example files,
as well as an example solution for the mini exercises and the indexer/searcher
case study at ftp://ftp.wiley.com/public/sci_tech_med/web_application. I will
also work on extra examples that I will make available to illustrate other areas
of the book that did not get a full example. I would have included many more
examples, but then you would need two or three volumes this size. Instead, I
will just put everything in a Website for you to download and test. I hope you
enjoy it all!
The book is organized to be read front to back, but you may skip chapters as you
see fit, or use the book as a reference. The Introduction is a summary of Chapter
19 and should be used by people already experienced in Web development. It is
basically meant as a guide to using this book as a "Web programming cook-
book." You may read this Introduction for brief guidelines or go straight to
Chapter 19 if you need an in-depth explanation with a practical example.
Acknowledgments
I'd like to express great thanks to my family first for always being there for
me. I wouldn't be where I am without them, and I'll never manage to thank
them enough for that. To my very close (and special, a.k.a. N.B.) friends, I
thank you for your support and patience over the years; it is not easy putting
up with me for so long, but you have always given me some of the best times
I could hope for. Quick "howdy" to my online friends at COTW and BF2C
for helping me steam off when I had too much work and needed a break.
Thanks to Larry Bernstein for allowing me the opportunity to write this
book, and of course thanks to the people at John Wiley & Sons for getting
my first book published even though I'm still "a kid." Special thanks to
Whitney, Paul and Melissa for all of their help and patience; and to Ben for
the cover image. ©
xv
Introduction
OVERVIEW
You might be wondering why you are reading an "Introduction" chapter and
why this chapter is called "Web Application Recipe." Well, this chapter is
your quick guide to professional Web application design and implementation.
It is in essence a summary of the last chapter of the book (Chapter 19),
created mainly for people with enough experience in Web programming to
skip some of the chapters presented. This chapter will give you the rundown
of the major steps in the lifecycle of a Web project, and will refer to the chap-
ters where you might find more in-depth information on the topics covered.
I call it the "recipe" because it gives you the general layout of what needs to
be done, before getting into the specific details that each individual chapter
will cover. For a more in-depth guideline with a practical example, be sure to
read Chapter 19.
PROCEDURE
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavtiScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
1
2 WEB APPLICATION RECIPE
Step 4-Backside
Once the core of the project is up and running, you need to implement the
back end of the project. This is the section of the project that will be used by
administrators to manage the Website after it has been published, and it is a
good idea to have it up and running before the regular users start meddling
with the Web application. If you need some information on writing scripts in
PHP, check out Chapters 5-9.
Step 8-Presentation
Assuming that you are not writing the application for yourself and there is
money involved, you will need to present your final project to your project
sponsor. The key here is to be relaxed and be confident that your project
is rock-solid. If you follow the guidelines in this book, this should not be
a problem. If you are presenting to a nontechnical person, start by showing
the general features of the project, getting into details only when asked to
do so. If you are presenting to a fellow developer, go straight to the
functionalities.
Step 9-Publication
When the project has been approved, it is time to release it. Place it in your
desired host and make sure that everything is set up properly so that users
worldwide can access it. This phase should be fairly fast.
4 WEB APPLICATION RECIPE
Not that long ago, in a galaxy pretty close by, men and women used to live
without practical means of communication. Paper was the main medium used
for information sharing and horses the main carrier for that medium. But
science kept working, and in 1831 Joseph Henry invented the first electric
telegraph. Four years later, Samuel Morse invented the Morse code, and
worked on the very first long-distance electric telegraph line, which he fin-
ished in 1843. A bigger leap in communication progress was made by Alex-
ander Graham Bell, who patented the electric telephone in 1876.Long-distance
communication was finally a reality, but still archaic compared to what was
to be achieved. With the arrival of computers in the midtwentieth century,
people realized the potential of storing and processing data in those amazing
new machines. Furthermore, the United States and the Soviet Union were
deep in the Cold War, and the fear of a possible strike was constantly present
in the military's mind. One of the main concerns was the possibility that all
communication between remote locations could be interrupted by an attack.
Telephone and telegraph lines were out in the open, and could be easily
damaged, so the National Security Agency (NSA) thought of a way to
preserve communications. Emulating the principles of telephone commu-
nication, in the 1960s, the NSA thought of connecting computers through
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
www.allitebooks.com
6 FUNDAMENTALS
wide-area networks (WANs), so that if the phone lines went down, they would
still be able to send orders to detachments across the country, through the
use of computers. In order to make this idea a reality, the Advanced Research
Project Agency (ARPA) created the first computer network in 1969, and
named it the ARPANET. It was composed of only four computers, located
in the University of California at Los Angeles (UCLA), the University of
California at Santa Barbara (UCSB), the University of Utah, and the Stan-
ford Research Institute (SRI). Three years later, in 1972, the use of routers
allowed the ARPANET to have 20 nodes and 50 host computers, which could
all communicate through tools such as the tel net and FTP (File Transfer
Protocol). In 1974 Vincent Cerf, from the SRI, and Robert Kahn, from the
Defense Advanced Research Project Agency (DARPA), presented the Trans-
mission Control Protocol/Internet Protocol (TCP/IP) basics, forever chang-
ing the waycomputers would communicate. In 1983the Defense Communication
Agency (DCA) took control of the ARPANET and separated the military
section to form the MILNET, which would be used for military purposes only.
In the mid-1980s the two main existing networks, the ARPANET and the
NSFNET (created by the National Science Foundation), merged to create a
massive computer network. That merge motivated a trend that brought more
and more computers to the network, and this network of networks was then
named "the Internet." By 1990 the Internet had 3000 subnets and over 200,000
host computers. The estimated number of host computers in the year 2004
was approximately 234 million, and growing.
After creation of the Internet, great potential could be seen way beyond the
actual work that was being done. Computers were destined to do more than
utilize telnets and FTP; it was great to be able to link one computer to
another in order to send files, but the problem of communication was not yet
totally solved. Scientists doing research had to connect to a remote computer
and send their research results one at the time through FTP. This was faster
than sending manuscripts through "snail mail," but it was still not the best
option, so in 1989 Tim Berners-Lee presented the World Wide Web project
to the Conseil Europeen de Recherche Nucleaire (CERN; European Orga-
nization for Nuclear Research, based in Switzerland). The idea was to come
up with a set of standards for information sharing that scientists. around the
world would be able to use. The goal was to be able to have all research
documents in a format and location accessible to all interested regardless of
the platform being used . In 1994 the World Wide Web Consortium (W3C)
was created to lead the World Wide Web (WWW) to its full potential by
developing common protocols that would promote its evolution and ensure
its operability. You can find out more about the W3C visiting their Website,
www.w3c.org.
THE WEB SERVERS 7
Right at this point we have seen what lead to the creation of the computer
network known as "the Internet," and the reasoning behind the apparition of
the World Wide Web. But we still have a main problem that we haven't
answered yet-how do we use all this to communicate? First the Internet
brought us the media through which the information would flow, then the
WWW provided a standard format for information formatting, but there
was still the problem of how to read that information. To solve that problem,
some tool had to be created that would use the current standards and decode
Web documents and format them in such a way that would be intelligible
to the user. The Web browsers came to the rescue and solved that pro-
blem. The first graphical user interface (GUI) with the WWW to appear
was Mosaic, created by the National Center of Supercomputer Applications
(NCSA) at the University of Illinois in 1993. In 1994 Norway entered in
the pages of Internet history by creating the still-used Opera. Soon after-
ward Netscape appeared, followed by Microsoft's Internet Explorer, which
appeared along Windows 95. From that point on, the browsing market
has done nothing but evolve and-Fortunately for us, the users-improve.
Nowadays the two main browsers used are Internet Explorer and Mozilla
Firefox.
Now that we know what the Internet is, the purpose of the World Wide Web,
and why we use Web browsers, another question may arise: "Where are all
these data stored?" It is definitely enlightening to know how we access all the
information that the World Wide Web has to offer, but where is all that infor-
mation? Well, the answer is pretty simple; it is in all the computers that form
the Internet. Some people become alarmed, believing that any computer con-
nected to the Internet will automatically make all of its files accessible to the
entire world. Not to worry, that is not how it works. In order to share informa-
tion in a specific computer, some software has to be installed on the computer,
making it a "Web server." The server creates a list of folders that will be
shared when someone attempts to connect to the computer using standard
Web protocols. There are two main competitors in the Web server market.
The first one, my personal favorite and the one used throughout this book, is
Apache, developed by the Apache Software Foundation (www.apache.or~).
Apache has the great advantage of being totally free of charge and works on
every platform. It is an open-source program, which means that you can actu-
ally see the code behind the server and even participate in the improvement
of Apache. It is reliable and vastly used around the world, and pretty much
the only reliable option on UNIX/Linux. The other main server is Microsoft's
Internet Information Services (lIS, www.microsoft.com/iis). lIS is not open-
8 FUNDAMENTALS
TCP/IP BASICS
THE TOOLBOX
To conclude this chapter, I will list some programs that I believe all Web
developers should know about. All opinions are entirely personal, and you
are more than free to disagree with me.
Browsers
As mentioned earlier, browsers are essential in the use of the Internet and
choosing the right one for you is an important decision to make. Throughout
this book we will discuss some of the differences between these browsers,
especially during the JavaScript coverage. The most commonly used by
Microsoft Windows users is obviously Internet Explorer (http://www.micro-
soft.com/ie/), since it comes with the operating system. MSIE is a very user-
friendly browser, and perfect for Mr. or Mrs. Anybody that just wants to
browse the web. As a developer you must know that it is a dangerous tool,
since no matter how disgusting your HTML code might be, MSIE will manage
to make the output look decent, especially when using tables or frames. So
do not assume your page is perfectly written just because MSIE displays it
nicely. One of the advantages of MSIE is that JavaScript works perfectly well
with it, so you will probably love it when we are working on that language. It
also contains many plug-in that are required in many websites, so you might
actually be required to use it to fully appreciate some websites. The major
flaw it has as far as I'm concerned, and a reason why I stopped using it, is the
number of security holes it contains. Granted, in most cases no one will ever
attack your computer using those security holes, but as a computer scientist,
I like being protected.
Another browser that had great influence in the world of browsing is
Netscape (http://browser.netscape.com/ns8/), which had a great growth in the
late 90s. Unfortunately for Netscape, it has been going downhill for few years
now, and personally it will never cross my mind to use it again until they
improve it greatly. I actually stopped using NS when they released their
version 6, mostly due to JavaScript incompatibilities that will be mentioned
in further chapters. But basically Netscape had a set of Netscape-specific
HTML tags that were both useful and necessary for the use of JavaScript on
that browser, but they decided to wipe those out on version 6, which pretty
THE TOOLBOX 13
FTP
If you are trying to install an FTP server on a Windows machine, I would
have to recommend Serv-U FTP (www.serv-u.com).Itis a great server soft-
ware that will probably allow you to do anything you want to with it. If you
are looking for an FTP server for UNIX, there are so many good, and free,
ones that I won't even bother mentioning them (there was probably one
included in your UNIX/Linux distribution).
If you are trying to get a nice FTP client, one of the most commonly used
(or at least it was when I discovered FTP) is Cute-FTP (www.cuteftp.com).
There are many others free and not free, but my favorite would have to be
LeechFTP, which allows the use of multiple threads, which speeds up the
transfer of multiple files. Unfortunately, the development of LeechFTP has
not been continued for over a year, so there are no really recent (as of 2006)
versions. I still like myoId version, though, since it never gave me any prob-
lems. It would seem (at the time of this writing) that the people working on
LeechFTP are now working on a new client called BitBeamer (www.bit-
beamer.com). I have never tried that software, so I cannot vouch for it, but it
is supposed to have all the features that LeechFTP had.
14 FUNDAMENTALS
Email Clients
One of the most widely used email clients is Outlook Express, which comes
standard with every copy of Windows (since Windows 95). It is simple and
works well, and is preinstalled with Windows, so no need to add extra soft-
ware if that is your platform. There is also the more complicated version
called Outlook, which does all Outlook Express does but adds in a calendar,
nicer agenda, but also heavier software to run. Personally I prefer the Express
version.
Another survivor of the old ages, and the first email client I ever used in
my life, is Eudora (www.eudora.com).Ihaven·tuseditsince19970rso.so I
am not really in a position to tell you how good the latest versions are.
Many users simply like using the clients that come with their browsers,
such as Netscape mail, or directly with Web-based email clients like Hotmail
(www.hotmail.com). or Yahoo (http://mail.yahoo.com), which allow you to
view emails directly on a browser. Personally I'd recommend you use Gmail
(www.gmail.com)createdbythepeoplefromGoogle.Itis by far the best
Web-based email tool I have used in over 10 years of Internet use, and it is
still in its Beta version, so Google can still improve it. The only problem is
that you can create an account only if you are invited to do so by a current
user.
If what you use is lJNIX or Linux, the two main email clients I know
and have used are "Pine" (Program for Internet News & Mail) and "Elm"
(Electronic Mail), but I would have to vouch for Elm. It is a very small simple
application that runs straight from your shell and lets you choose your text
editor. They are both usuallyincludedwith the major UNIX/Linux distributions.
Programming Tools
Whenever you start programming Webpages, you will have to choose which
software to use, and you might think you need a lot of money for licenses and
so on. Well, think again, because you have excellent tools that will be more
than enough to program Websites (and I strongly recommend that you use
these when working with this book). On Windows platform you have two
great tools called Notepad and Wordpad. I personally prefer the first one
because it is much simpler and does not have all the unnecessary things that
Wordpad has. On UNIX you have "vi" and "emacs," which is pretty much
like choosing between Red Sox and Yankees (or between Real Madrid and
Fe Barcelona), since in most cases people that like one hate the other. In my
case it is true: I love emacs and hate vi. But it is only a question of taste.
If you think those tools are too basic for you and you would like to see
some colors in your code when you type it, you might want to choose some-
thing like HomeSite by Macromedia (www.macromedia.com/software/home-
site). It is a simple text editor adapted to Web development, so it recognizes
the syntax and highlights special words and tags. It also allows you to preview
THE TOOLBOX 15
the page and comes with a great tool for the creation of style sheets. Similar
to HomeSite but a bit simpler is UltraEdit (www.ultraedit.com). which allows
you to import or create your own set of syntax rules and colors associated
with those rules.
Another well-known editing tool is Macromedia's DreamWeaver (www.
macromedia.com/software/dreamweaver). The basic way to use Dream-
Weaver is to simply drag and drop the elements you wish to have in the page.
You can also type directly in a "preview" of the page, having DreamWeaver
take care of all the actual coding. Because of this feature, I do not recommend
it for this course, since it promotes laziness, and adds too much useless code.
If you really want to use it, please use the split view and type in the code
directly. (The split view will allow you to see both the preview and code at
the same time).
Finally, we have Microsoft's FrontPage (www.microsoft.com/frontpage).
which is definitely not my favorite tool for Web programming. It creates a
large amount of unnecessary folders and files when you are just trying to
create a simple Website, and adds useless code in the pages that you create.
It might be a great option for people wanting to create a Webpage without
having to understand any of the code, like web designers, for example. If you
are a Web developer, code should be your number one priority, making Front-
Page my last choice. Last, and least, is Microsoft's Word "Export to HTML"
feature, which should be used only by non-Web-savvy people to quickly create
pages from Word documents. It is very problematic, and I discourage its
use.
www.allitebooks.com
2
The Different
Approaches of Web
Programming
BEFORE WE GET STARTED
Before I head on and start explaining the different languages available in the
Web programming market, let me stress that all the opinions stated are exclu-
sively my personal views. I tend to be very opinionated, but I will try to justify
both my criticism and praises of the different languages presented.
THE BASICS-HTML
The very first programming language that must be mentioned when discuss-
ing Web programming is obviously HTML. The WWW could not be what it
is today if it weren't for this language. The HTML (Hypetrext Markup Lan-
guage) is, as the name indicates, a "markup" language, which generally means
that it is based on the use of tags to provide functionality. The "code" in an
HTML file is simply text containing those tags that provide functionality and
different looks to the page. It is an interpreted client-side language, meaning
that for an HTML page to be viewed, a browser must first download it from
a server into a client machine and then execute the code line by line.
HTML relies strongly on the use of Universal Resource Identifiers (URI).
Each URI represents a way to refer to a page, an image, or even an email
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6 .
Copyright © 2007 by John Wiley & Sons, Inc.
17
18 THE DIFFERENT APPROACHES OF WEB PROGRAMMING
mydomain.com (I)
images
t mypic.jpg
myotherpic.jpg
t
files
foobar.html
otherfile.html
yetanotherfile.html
As you noticed, relative paths usually start with "..1", which means "go to
parent directory" or "'/", which means "current directory." Relative paths
are an easy way to make a Website more portable since they are independent
of the domain that the pages are in. It is especially useful if, like me, you
test all your pages in a local computer before uploading the files to your
host.
The use of URIs is pretty much a necessity in HTML because they allow
you to embed images to a page, send information from a form to a processing
script, create an image map, link to an external style sheet, create frame docu-
ments, cite an external reference, or also refer to metadata conventions to
describe the page.
THE CREATOR-SGML
Because the output produced by browsers when opening a basic XML file
tends to provide too much information, and it does not have a flexible appear-
ance, XSL was created. The eXtensible Style sheet Language is used as a
20 THE DIFFERENT APPROACHES OF WEB PROGRAMMING
In order to link our .XML file to the XSL file, you would simply add the
following line right after the «Yxml. . . . ?> line of the XML file:
SOMETHING DIFFERENT-JavaScript
Here comes one of the greater sources of confusion among young developers.
Despite the name "JavaScript," this programming language is very different
from Java. First, it is a compact, object-based scripting language, generally
used to develop client-side scripting pages, and sometimes server Internet
applications. In many cases, JavaScript is code that is embedded directly in
the HTML code of a page, to be executed by the client. This means that the
code is downloaded at the same time as is the rest of the page, making it
entirely visible. It is then interpreted line by line at the same time as are the
HTML tags. Again, it is different from Java; some of the major differences
are listed in Table 2.1.
THE SAVIOR-PHP
Well, you are probably wondering about the title I gave this section, but let
me explain my logic behind it. I am one of those old-school developers who
believe that C language is one of the best programming languages ever,
because of its flexibility and how easy it is to learn. C is a language that, with
a small toolset, can allow you to achieve pretty much anything you wish to
achieve. Well, for me, PHP is pretty much "C for the Web." The syntax is very
similar, with less syntax restrictions, as we will see little by little, but follows
the two concepts of C that I like the most: flexibility and ease of use. It is
really easy to learn; an experienced programmer can pick it up in a couple of
days. Another great asset of PHP is the fact that it runs server-side, meaning
that the code is executed before the client has access to it, but we shall discuss
this later on. Let us talk about the basics.
PHP is a recursive acronym of Hypertext PreProcessor and, as the name
indicates, works like many preprocessors found in other languages. This
means that the code is read line by line and interpreted as it goes, or at least
that was how PHP started. It is an open-source scripting language, so you will
be able to find many sites enhancing its development. It also means that the
PHP project is created and maintained by developers who wish to invest their
free time in making the product better, yet free.
PHP was designed to work for the Web, and its code is embedded directly
in HTML pages, although, as we shall see later, it is possible to separate
HTML and PHP through the use of templates. Interestingly, PHP is not
limited to work on the Web, and can actually be used to create command-line
scripts that you could run from a shell, or even GUI (Graphical User Inter-
face) applications through the use of the PHP-GTK library.
PHP is also designed to work closely with a wide variety of databases,
including Oracle, MySQL, PostgreSQL, ODBC, and Sybase among others,
making it an excellent choice for database-driven Websites, regardless of the
database you wish to use. It also includes an extensive set of libraries that
allows developers to interact with a wide range of other technologies. PHP
developers can write applications that will generate images, PDF documents,
work LDAP authentication servers, communicate with flash animations, and
many other things that unfortunately we will not be able to discuss, since it
would probably take several volumes.
THE RIVAL-ASP.NET'
Active Server Pages (ASP) and now ASP.NET are probably among the major
sources of confusion among developers. ASP used to be an actual program-
ming language developed by Microsoft that worked similarly to PHP; it was
a server-side scripting language, hence the title "the rival." With the arrival
of the .NET platform, ASP.NET received an entirely new meaning, referring
ANOTHER BIG OPTION-Perl 23
THE MYTH-CGI
Now, here is a good source of laughter among recruiters who know about Web
programming. Many people think that CGI (Common Gateway Interface) is
an actual programming language and tend to "beef up" their resumes, adding
it to their list of known programming languages, without really understanding
what CGI is. CGI is a common gateway interface, and is definitely not a pro-
gramming language. It is a standard for interfacing external applications with
information servers, or, if you prefer, a "magical door" that will allow you to
run your normal executable files in a Webpage. CGI applications are executed
in real time, allowing a dynamic output, such as, for example, generating a
Webpage adapted to a set of received inputs. The way it works is simple; you
first write an application in your favorite language and compile it to an execut-
able rename it to "file.cgi" (note that this is technically optional, and many
developers leave script names as "file.exe"; I personally discourage this).
Some of the most common allowed programming languages are etc++,
FORTRAN, Perl, TCL, UNIX Shell script, Visual Basic, and Apple script.
Of course, to make your application more useful for the Web, it is usually
written to receive a set of parameters and produce HTML code that will be
displayed as the page's output on the browser.
Even though I used Perl only when I was a computer science student, and
considering that it is never in my list of languages to use, I have nothing nega-
tive to say about it. Perl is a very powerful programming language, and also
very flexible, if anything, it is more complicated to learn and use than PHP.
It is also open-source, and one of the best options if your application is meant
to work extensively with text manipulation. Some of the most powerful regular
expression tools were created for Perl, and then exported to other languages,
24 THE DIFFERENT APPROACHES OF WEB PROGRAMMING
THE FUTURE?-C#
C# was a language created to work with .NET as a simple yet powerful object-
oriented programming language, mixing a programming interface similar to
the old Visual Basic, yet having the object-oriented features you could find
in C++. It is Microsoft's answer to Sun's Java. Java became increasingly
popular through J2EE, so Microsoft decided to create a language following
the same principles on their version of the three-tier architecture program-
ming platform, .NET. It strongly relies on XML as information exchange
format, and it is gaining popularity for programming Web services. As do
other .NET languages, it requires code to be compiled, yet it follows the
principle of Java's byte codes, by compiling into a platform-free language,
that will be interpreted by clients.
The reason behind the question mark is that even though C# is a fairly
recent language it is meant to be the flagship in the .NET revolution-or at
least that is what Microsoft representatives were announcing when they pre-
sented .NET. The reality is that its acceptance is still growing, but many .NET
developers prefer relying on older programming languages that they are more
familiar with ..NET is still gaining importance, and who knows, maybe it will
be the most predominant platform for Web services, not only on Microsoft
applications and Websites, but as a more global solution. If that happens,
surely C# will become increasingly popular and will be the first choice of
programming language for new developers.
any calculations or actions that might take place, which allows programmers
to create Webpages that will change dynamically as the code is executed.
Server-side applications run in the server, as the term indicates. This means
that when a client attempts to access a script programmed that way, the query
is sent to the server along with any input that the script might need. The script
then runs on the server, utilizing server resources only, and then sends the
final output to the client, who can see only that result, and has no access to
the source code itself. This obviously is a great asset since it protects the code,
which is very important for security reasons. Another great advantage of
having scripts run directly on the server is that you need to worry only
whether the server knows how to run it properly. Unlike the scenario in client-
side applications, the script will run exactly the same way, producing the same
output regardless of the client's platform or browser. On the negative side,
each time you wish to do something dynamic, you must communicate back
and forth between client and server.
Now that we know the differences between both sides, it is generally the
time to choose your preference, by selecting the language to use. Most devel-
opers, and therefore most books out there, tend to choose only one side, but
not me. Even though it is possible to create Websites based on just one tech-
nology, taking advantage of server-side and client-side programming simulta-
neously gives much more flexibility and allows a greater set of functionalities.
Some features run better in client-side, some in server-side, so restricting
yourself to only one will potentially limit your final project. Throughout this
book we will learn when .it is better to use a client-side language such as
JavaScript, or a server-side language like PHP.
Now that we have seen some of the most common options that programmers
face when engaging in Web programming, we must choose which technologies
to use. In our case, the choices are obviously known. One question you might
ask is why those choices and not others.
First, we have PHP. It is one of the most powerful and flexible programming
languages for the Web. It is free, is easy to learn (making it ideal for a one-
semester course), and simplifies any database access you might want to use.
JavaScript, although I do not like it as much as a language itself as it is
much more restrictive syntaxwise than PHP, is a really useful programming
language. As we will see, it is important to have a client-side language to
couple with PHP to make our pages more lifelike, dynamically changing
without having to constantly communicate with the server, and JavaScript will
help us fulfill that need.
MySQL, even though we have not discussed it yet, is a free database that
can be installed in any platform, providing a reliable solution for information
handling. It is also extremely easy to use MySQL databases with PHP, which
26 THE DIFFERENT APPROACHES OF WEB PROGRAMMING
will make our job so much easier. My "second best" option for databases
would be PostgreSQL, similar to MySQL with even some extra features, but
again, we shall follow the path of simplicity for this book.
Finally, and pretty much most importantly, these are the languages that I
have been using for years, and I never had any problems with them. Knowing
how to properly mix these three programming languages should allow you to
create any professional database-driven Website you would like to. Also,
although you might use different technologies in the future, mastering these
three will give you the mindset needed for Web development. It is like learn-
ing how to play soccer; you must learn how to kick the ball, regardless of the
shoes you will wear or the team you will support. Web programming is much
the same; if you know how to properly design a Website, the language choice
will be only secondary.
www.allitebooks.com
3
Introduction to HTML
Before we start discussing HTML, let me give you a checklist of things you
should have with you when programming. First, you need a basic text editor
like Notepad or emacs. You can also use more advanced tools, like the ones
mentioned in Chapter 1, but if you really wish to learn the ins and outs of
HTML, you are better off with a basic editor. The next needed thing is a
browser, which will be used to test the pages and make sure that they look
the way you want. Third, you need, obviously, some basic HTML knowledge.
Last but not least, you need good music. People usually think I'm kidding
when I mention music as a necessity, but from my experience, the right music
can activate the brain to work more efficiently. The right music will depend
on your own personal taste, but I would recommend either classical if you
work better in a calm environment or hard rock, punk, and other fast-paced
music if, like me, you prefer the music tempo to drive your fingers into a typing
frenzy. This chapter will try to make sure you have element number three:
basic HTML knowledge.
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
27
28 INTRODUCTION TO HTML.
Syntax Basics
HTML is a markup language and, as such, works entirely through the use of
tags. Each tag is used to define different parts of the file, different styles, links,
images, embedded elements, forms, and so on. Each tag starts with the char-
acter "<" and finishes with ">". Keep this in mind because those characters
are restricted for tags, meaning that your page might behave in a strange way
if you attempt to use it in a normal string. If you wish to use that character,
refer to the special characters table shown in Appendix A. Now, some tags
require an opening and a closing tag in order to show the area of effect of the
tag. In those cases the closing tag will always start with "«I", followed by the
name of the tag it is closing (without the attributes list) and ">".
For example, to have some text appearing in white, you could use the
FONT tag, with the attribute color set to "white." To do so, your opening tag
would be <FONT color = "white"> and your closing tag would be </FONT>.
Your final portion of code would look like this:
Note that HTML is not case-sensitive, so you can mix uppercase and lower-
case letters. Nevertheless, I strongly advise everyone to capitalize all tags
since it makes code reading much easier.
Finally, remember to name your files with either .html or .htm as their
extension.
File Structure
It is very important to understand the basic structure of an HTML file,
knowing exactly where each part of your code must be written in. It is some-
thing fairly easy to remember, but unfortunately there are still people who
claim to be Web programmers but who misuse the file's main areas. Good
Web design and programming demands efficient and effective use of the
available tools. This book is designed to avoid these pitfalls.
The first thing is the full file, which must always start with the tag <HTML>
and finish with </HTMI~>. You should never have HTML tags before the
opening tag, nor after the closing one. One of the reasons for this occasional
error is the fact that most browsers can now ignore major errors like this one
and still manage to create a proper-looking output, but please always start
your files by setting up these two tags.
The next section to know is the header, limited by the tags <HEAD> and
</HEAD>. This section holds all information related to the file, including its
author, its keywords, its title, and sometimes even some JavaScript functions
that will be used in the page. Most basic pages use the header only to specify
HOW DOES HTML WORK? 29
the title that will appear on the browser window.To do so, use the <TITLE> ...
</TITLE> tags. Any text written between the opening and closing tags will
appear in the title bar of the browser.
The final area is the body, starting with <BODY> and finishing with
</BODY>. The body of a page is the actual content of the page, meaning that
the data that will appear inside the browser window. The body tag can accept
a set of properties that allow you to set up a background image (background)
or color (bgcolor); specify font colors for text (color), links (link), visited links
(vlink), active links (alink), and even action scripts to run on load or unload
of the page. There should always be a body section in a Webpage, unless you
are using the page as a frameset definition page (see discussion later).
Here is an example of what a "Hello world" HTML page should look
like:
<HTML>
<HEAD>
<TITLE>Hello World Page</TITLE>
</HEAD>
<BODY>
HELLO WORLD!!! <BR>
And have a nice day!
</BODY>
</HTML>
Note the indentation I have used. This is not required, but will improve the
readability of your code. You will also note the use of the tag <BR>, which
forces a break of line. It is important to realize that any group of white spaces
(whether it is a tab, a new line, or basic spaces) is always translated on the
screen as a single white space. This is important to know since the appearance
your code has will not necessarily be the same as in the output. Check the
following example:
<HTML>
<HEAD>
<TITLE>Hello World Page</TITLE>
</HEAD>
<BODY>
HELLO WORLD!!!
And have a nice day!
</BODY>
</HTML>
You probably noticed that this code is almost exactly the same as the previous
one except that there is no <BR> tag after "Hello World!! L" In this example,
the text "And have a nice day!" would show on the same line as "HELLO
30 INTRODUCTION TO HTML
WORLD!!!," even though it is written a line below it, because the "new line"
will be translated into a single white space.
As a teacher I enforce the use of the basic six tags needed for an HTML
proper structure, so I would recommend everyone to make it a habit to write
them all as soon as a page is created, and then fill in the blanks.
Tag Parameters
As we saw previously with the FONT and BODY tags, it is possible to add
attributes to an opening HTML tag to make it more effective. Each attribute
will affect the area after the opening tag and will finish with the closing tag.
Remember that there is no need to write the attributes in the closing tag.
Checking the W3C website (www.w3c.orG) can get you an exhaustive list of
all the attributes that tags can use, but I will give you the ones I consider most
important for the tags that I will teach you at the end of this chapter.
There are many ways to format text in HTML, but we will discuss only the
real basics right now. There will be more details on styles in Chapter 10. The
tags I am about to show you are considered to be deprecated and should be
replaced with the use of style sheets, but as much as this is true, you probably
want to get started without having to learn advanced formatting features. In
that case, the following tags are ideal.
The first basic tool commonly used for formatting text is the <P> ... </P>
tag, which stands for "paragraph." As the name indicates, it defines an area
that works as a single block, and most browsers will automatically break a new
line at the end of a paragraph. I try not to use this tag when writing normal text
since the output on the screen might be different depending on the browser, so
I prefer to handle my paragraphs manually. On the other hand, paragraphs are
really useful when using style sheets, as we will see in Chapter 10.
A very useful tool in HTML is the different heading styles that can be
used. There are six basic: levels of headings that can be used to easily write
titles, chapters, or sections. Each heading is treated as a paragraph, so a new
line is added automatically when the tag is closed. To use a heading, simply
wrap your title with «Hn» ... <IHn>, where "n" is the level of title you wish
to use from 1 to 6 (with HI the biggest heading and H6 the smallest). If you
wish to add extra linebreaks you can use, as seen earlier, the <BR> tag.
To change the appearance of text, you can use <I» ... <II> to italicize a
text, <B> . . . </B> to make it bold, or <V> . . . <IV> to underline it. As
always, these tags affect the text only between opening and closing tags. It is
also possible to use the <FONT> tag to specify colors, fonts, sizes, and back-
ground colors, for example, but it is considered poor programming practice
to use these in your HTML code since it makes it much more difficult to read.
Instead, you should use styles, which, again, we will see in Chapter 10.
BASIC TEXT FORMATTING 31
Most tags, including <P>, accept an attribute called ALIGN that allows
setting of the horizontal alignment of a block by setting it to "left," "center,"
"right," or "justify." It is also possible to center an area of the page by using
the <CENTER> . . . </CENTER> tag. The advantage of the <CENTER> tag
is that it will act on anything between opening and closing tags, regardless of
the type of element (form input, image, paragraph, button, etc.).
To do a basic enhancement on your page's look, you can use horizontal
rules. These are horizontal lines used mostly to separate sections and para-
graphs. To use it, just write <HR> with any of the following attributes:
ALIGN (left, center, or right), NOSHADE to remove the shade under the
line, SIZE (in pixels) to specify the height of the line, and WIDTH (length
in either pixels or percentage of the page) to specify the linewidth. An example
ofa nice-looking rule could be <HRALIGN=centerSIZE=l WIDTH=75%>,
which would create a line of 750/0 of the page's width, centered in the page,
and with 1 pixel height. Note that this tag does not need to be closed.
Finally, to conclude this set of basic formatting tools, I would have to add
the <BLOCKQUOTE> . . . </BLOCKQUOTE> tag. This tag was created
to be used to quote other people in a text, but it has a nice property. Any
text inside a <BLOCKQUOTE> tag is automatically indented, which is great
for a really fast indentation solution. I personally have used it in the past to
force a blank margin at the beginning of my pages, making the output
cleaner.
Here is an example using all these tags:
<HTML>
<HEAD>
<TITLE>Formatting example</TITLE>
</HEAD>
<BODY>
<BLOCKQUOTE>
All my text will show up with an indentation!
<P ALIGN=right>This is a first paragraph with right
alignment</P>
<P ALIGN=left>And this is a separate left-aligned
paragraph with things written in <I>italic</I>, <B>bold</B>,
<U>underlined</U> and even <U><B><I>all mixed up</I></B></U></P>
<CENTER>
<HR size=l width=75%>
<Hl>Headingl</Hl>
<H2>Heading2</H2>
<H6>Heading6, and like the others I'm centered!</H6>
</CENTER>
</BLOCKQUOTE>
</BODY>
</HTML>
32 INTRODUCTION TO HTML
EXTERNAL REFERENCES
Two of the most common features in Webpages are links and images. They
are two ways of referring to an external file. One places an image in the
middle of the page, while the other sets up a clickable area that will open any
type of file, or even open your default email client to send an email.
Links
Let us start with the links. Any text or image can be turned into a link by
wrapping it with the <A> . . . </A> tag. The attributes for the <A> tag are
essential for its proper functioning. The first attribute to set should be HREF,
which will hold the URL that the link will refer to. The address could be an
absolute or relative URI, or a call to a mail client by entering mailto:any-
email@address.here. You can also select a target for the link, which specifies
where the link should be open. This is done by using TARGET followed by
the name of the window or frame where you wish the link to open. If the
name has been set to a window or frame, it will work without complications,
but if it has not been set yet, the link will pop up a new window that will
receive the name written in the target parameter. From this point on, any link
targeting the same name will open on that new window. Instead of providing
a name, it is also possible to enter _blank to always open the link in a new
popup window, _self to open the link in the current window or frame, _parent
to open the link in the parent frame (see the section on frames), or _top to
open the link in the parent of all parents (top frame). Here is a link
example:
Another interesting use of the <A> tag is to create linking points in the
page. This means creating a point in the page that can be linked to, allowing
fast scrolling of long pages. To use this feature, write <A NAME="anyname">
... </A>. To then link to that area, just add #anyname at the end of the
address of the file you are linking to, or directly enter #anyname as the HREF
if you wish to move inside the current file. Here is an example:
<HTML>
<HEAD><TITLE>Link Examples</TITLE></HEAD>
<BODY>
<A NAME="top">This</A> is the top of the page!<BR>
Here is a normal. <A HREF= ..http://www.google.com ..
target= n_blank">link</A><BR>
Now I'm going to add loads of BRs to make this page
really long!<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>
EXTERNAL REFERENCES 33
<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>
<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>
<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR> <B R>
<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>
<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR> <B R>
<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>
<BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>
This should be pretty low on the page so take me <A
HREF="#top">to the top!</A>
</BODY>
</HTML>
Images
Using images in Websites is like using table salt when cooking. Without it,
the site is too bland, but include too many images, and it becomes hard to
enjoy. I must say, as most people discovering animated GIF images for the
first time, my first HTML page was an array of ridiculous images, including
the "all-star" work-in-progress animation, email-me image, and other classics
found in virtually all "I'm learning HTML" Websites. In retrospect, I can say
that that page was certainly the ugliest page I ever wrote in my life, but people
learn from past mistakes. So here is my advice to all of you-keep it simple
and don't overdo images!
Another important thing about images is size and format. People seldom
realize that the bigger the image, the longer it will take to load, especially for
those people out there who still use dialup connections. Generally images
should be kept under 100 kB. Another important factor is the format. Most
browsers accept a vast variety of image formats; however, for example includ-
ing a BMP image is strongly discouraged, simply because as in all noncom-
pressed formats, the images will tend to be unnecessarily huge. The most
commonly used formats are GIF, JPG, and PNG, and you should try to limit
your images' formats to either one of these three. Keep in mind that GIF
images allow animations, but are limited to 256 colors. Generally, use JPG
for images that require higher quality and GIF for icons and such. Also keep
in mind that even though you can add an image as a background for the page,
you do not necessarily need an image as big as the contents of the page. A
technique I regularly use when creating my background images is to utilize
the fact that background images are shown as a mosaic, filling the entire page
with as many copies of the image as needed. For example, if there is a color
you really want to use but it cannot be defined with the standard hexadecimal
red-green-blue notation, you can create a picture of 1 pixel by 1 pixel (1 x 1
pixel) filled with the color you wish to use. When using it as a background,
that pixel will be used all over the page to fill in the background, but will need
to be downloaded only once to the client. Another nice technique is to include
34 INTRODUCTION TO HTML
images of just a few pixels in height and very large width (I usually make the
format 1600 pixels wide and 1-10 pixels tall depending on the effect I wish to
achieve). The idea is to create a pattern that will be repeated line by line on
the left side of your page. A nice image I created was for a school example
where I decided to elicit that "bluebook" feeling. To do so I had an image
that was all white, with a blue horizontal line and a red vertical line to create
the margin. Just by selecting that image as the BACKGROUND property of
my <BODY> tag created the desired effect, with an image that was less than
lkB.
To include an image in the middle of a page, simply use the <IMG> tag,
which does not need to be closed. The parameters to use include first SRC,
which defines the URI of the image to be shown. It is also possible to specify
the size of the image through WIDTH and HEIGHT. Note that if you do not
set the size of the image, it will be displayed in its original size, but if you set
both attributes your image might be distorted if you do not respect the image's
aspect ratio. The best way to set a new size for an image that you wish to
portray as either bigger or smaller is to simply set up one of the parameters
as a number of pixels or a percentage of the original size. By writing only one
of the attributes and omitting the other, you will be able to preserve the aspect
ratio while changing the size of the image. The last but not least attribute is
ALT, which takes a string, usually describing the image. This is extremely
important if you wish to make your Website compatible with nongraphical
browsers like Links, for example. When an image cannot be displayed by a
browser, only the name will appear where the image should be. If you write
the description of the image in the ALT attribute, instead of the picture's
name, you will see that description. A good example of why this is useful
would be Websites that are mainly picture-based, meaning that all menu
options are actually pictures with text inside them. In these cases, the ALT
should be whatever text the image holds. For example, if menul.gif is a picture
that says "register," the ALT for that picture should be "register" also. That
way, a person visiting the Website will still be able to use it even though the
images won't show up, as "register" will be much clearer to understand than
"menul.gif."
ORGANIZING DATA
Lists
Lists are a tool rarely used by developers on Webpages for reasons that
I do not fully understand. I have often seen students creating paragraphs
after paragraphs starting with a number or series of numbers to create
a topic list for example, when HTML provides the tools to do so
automatically.
There are two main types of lists: ordered and unordered. An ordered list
will always include the position of the current element in front of the text
itself, whereas unordered lists pretty much are the same as adding bullets in
front of the text. An ordered list is created with the tag <OL> . . . </OL> and
should always include TYPE as a parameter, with either one of the following
values:
Once you have defined an area to work as a list, you can add a new element
by starting its line with the tag <Ll». Think of this tag as a bullet or number
that you place in front of text, since it does not need to be closed. Each <Ll»
will either add a bullet or put the next number or letter following the last
«Ll» used in the same list. Note than you can use nested lists if you wish to
by simply using <UL> . . . </UL> or <OL> ... </OL> instead of a new <Ll»
tag. Each new nested list will be automatically indented, along with all its
contents, keeping the lists clean.
36 INTRODUCTION TO HTM'L
<HTML>
<HEAD><TITLE>Nested Lists</TITLE></HEAD>
<BODY>
<OL TYPE=I STAR'T=19>
<LI>I'm the iiret: element, yet I show up as 191!
<LI>Second Lirie
<LI>And now something different!
<UL TYPE=circ-le>
<LI>Aren't circles pretty?
<LI>Just wait until you try the other types!
</UL>
<LI>Where was I again?
</OL>
</BODY>
</HTML>
Tables
Tables are probably one of the most widely used systems for organizing pic-
tures and text. A table is a very efficient tool when used properly but can
cause painful results if not handled with care. Many programmers actually
base their entire Websites on really complex tables, which gives a consistent
look to their pages. Generally speaking, table fanatics tend to hate frames
(next section) and vice versa, I personally think they are both needed. I use
frames for the general layout of the site (header, menus, body, etc.), and I use
tables to organize individual pages. The reason for this is that, whereas many
people have pages that all start with the exact same several dozen lines only
for menus and headings that need to be loaded in every single page that is
opened, I just use a frame that loads it once, and stays open. Each page will
open only the new content, without necessitating reloading of the page's entire
layout. But anyway, let us see how to use tables!
The very first thing is to define an area that will be treated as a table. It is
very important to close it if you wish your page to have the desired look
regardless of the version of the browser. In the mid-1990s browsers would go
crazy when a table was not closed properly; nowadays browsers tend to solve
the problem and output the right aspect. Regardless, make sure that you close
the tags! This is also important when starting new rows and cells, as we shall
see. The official HTML syntax states that it is not necessary to close a row
or cell definition, but I would strongly recommend everyone to do so, since it
will make tables much easier to understand. To create a table, the tag used is
<TABLE> . . . </TABLl~>. This tag can take, among others, the following
parameters:
www.allitebooks.com
ORGANIZING DATA 37
Note that WIDTH and HEIGHT can be omitted if you want the table to
adapt to the size of the cells. Many graphic designers use these settings
to create restricted pages that appear to be a single box, allowing the page to
look exactly the same regardless of the resolution used by the client. The
BORDER parameter has to be used wisely; make it too big, and the page will
look goofy. I generally set it to 0 or 1 for either no border at all or just a small
one. A border of 0 is extremely useful when, for example, using images as
menu options. By having images of the exact same size placed in a table, you
can give many fancy effects to your pages, such as, for example, tabs in a
folder, or a set of buttons in a futuristic interface. It is all up to your imagina-
tion and your skills with image editors. Personally I am definitely not a
graphic designer, so I tend to keep it simple, or use text for my menus.
Once you have defined the general rules for your table, you must specify
the cells left to right and row by row. This means that the very first thing is
to define a row with the tags <TR> ... <ITR>. Each new row must start and
finish with these tags, which seldom take parameters (except maybe styles or
heights). Once you are inside a row, you must write the cells one by one, in
the order in which they will appear with either <TD> ... <lTD> for standard
cells or <TH> . . . <ITH> for header cells. The header cells are usually in the
first row, and will automatically center and render the text they contain in
boldface. Regardless of the cell type selected, you can use the following
parameters:
ROWSPAN and COLSPAN are probably two of the major sources of error
in tables among HTML developers. They are not complicated, but it is easy
38 INTRODUCTION TO HTML
to mess up if you do not watch out. The number they accept represents the
span that the cell should take rowwise or columnwise. For example, a
ROWSPAN=2 would mean that the current cell will use two rows. Obviously,
setting either parameter to 1 will do nothing to the cell. The dangerous thing
about these is that you must remember where you expanded a new row or
column in order to avoid extra cells popping out of the table. Note that expanded
cells use room on the following rows and columns, never the previous ones.
Check this bad example:
<HTML>
<HEAD><TITLE>Bad Tables</TITLE></HEAD>
<BODY>
<TABLE BORDER=2 WIDTH=500>
<TR>
<TD>Let's make a 3x3 table!</TD>
<TD COLSPAFl=2>I'm going to expand this cell!</TD>
<TD>So should I add a third cell ?</TD>
</TR>
<TR>
<TD ROWSPAN=3>What happens with a rowspan of 3?
I'm on second row and there's only supposed to be one
more!</TD>
<TD>This table is going to look horrible! </TD>
<TD>Let's just be done with i t . . . <lTD>
</TR>
<TR>
<TD>Last row! and the first cell I type in the
code </TD>
<TD>Wait a second . . . Didn't I rowspan? So even
though I'm the second set of TDs I appear third!!! Let
us avoid adding a new cell then</TD>
</TR>
</TABLE>
</BODY>
</HTML>
j :
TABLE 3.1 Desired Separation between Cells
I :and7 2and3 6
9
ORGANIZING DATA 39
My last little tip with tables is to always start drawing a normal table with
no expanded cells, and then figure out which ones need to be expanded. When
creating Webpages, paper and pen are still your biggest ally!
Frames
Here is another source of syntax errors, and widely hated by <TABLE> users.
Personally, as stated in the tables section, I tend to use frames on a regular
basis, since it allows me to have some sets of data to load to the client once
and only once, to then remain open. By doing so instead of systematically
creating my entire layout with tables, I can have content pages that are much
lighter and faster to load for the client. The idea behind a frame is to break
down your main window into several miniwindows, called "frames." Each
frame can independently open a separate Webpage, yet it is possible to com-
municate between them. Some important things to know about frames is that
you need a page to hold the frameset, which will define the aspect of each
frame, and then the files you will load in each one of those frames. Frameset
definitions replace the <BODY> . . . </BODY> tag, but some old browsers
cannot use frames, so you might want to create a "noframes" section.
Let's start with the basics. The very first thing to do, as stated above, is to
write the frameset right after the <HEAD> . . . </HEAD> in the page that
will be loaded. This page will have nothing displayed except the title, but is
extremely important. To create a frameset, use the tag <FRAMESET> . . .
40 INTRODUCTION TO HTML
<HTML>
<HEAD><TITLE>Frajmes example</TITLE></HEAD>
<FRAMESET Rows=n100, *,100" BORDER=2>
<FRAME NAME=~'title" SRC="about:blank">
<FRAMESET COLS="25%, *" BORDER=O>
<FRAME NAME="menu" SRC="links.html" SCROLLING=NO>
<FRAME NAME= "body" SRC= "goodtables. html" NORESIZE>
</FRAMESET>
<FRAME NAME="footer" SRC="nestedlists.html">
</FRAMESET>
</HTML>
ORGANIZING DATA 41
As stated earlier, some browsers are not capable of working with frames,
usually because the browser was of an older date than the addition of frames
in the HTML standards. The general behavior of a browser that is reading
an unknown tag is to ignore that tag. Obviously a browser that cannot process
frames will ignore our entire frameset and frame definitions, as it does not
recognize the tags. We can take advantage of that behavior and use another
frame-related tag to create an alternate version of our page that would not
employ frames, but instead would use tables, for example. To do so, you can
use the <NOFRAMES> ... <INOFRAMES> tag, and put a normal
<BODY> . . . <IBODY> block inside it. This new block should be included
right before the last </FRAMESET> tag. The way it will be processed is
simple. If the browser knows frames, it will ignore anything between
<NOFRAMES> and <INOFRAMES> and therefore skip the body you
added. If the browser does not understand frames, it will not understand the
<NOFRAMES> tag and ignore both opening and closing tags, but will still
parse what is between them. At that point it will find a <BODY> that will be
considered the normal beginning of the body section of a standard page. You
should always have a noframes section when working with frames, to at least
ask the user to get a browser supporting frames. Here is an improved version
of our previous example:
<HTML>
<HEAD><TITLE>Frames example</TITLE></HEAD>
<FRAMESET ROWS="100, *,100 H BORDER=2>
<FRAME NAME="title H SRC="about:blank H>
<FRAMESET COLS="25%, *H BORDER=O>
<FRAME NAME::;"menu H SRC="links.html" SCROLLING=NO>
<FRAME NAME="bodyH SRC="goodtables.html NORESIZE> H
</FRAMESET>
<FRAME NAME="footer H SRC="nestedlists.html H>
<NOFRAMES>
<BODY>
Please get yourself a good browser like <A
HREF=''http://www.getfirefox.comH>Firefox</A>
</BODY>
</NOFRAMES>
</FRAMESET>
</HTML>
There is another very curious type of frame called the "inline frame" (or
"iframe"), which is basically a frame that can be used as an image. It has the
advantage of being usable inside a normal body of a page, and does not
require any frameset definition. You can utilize this asset to, for example,
include it in a table, surrounding it by images of a TV frame to create a TV
effect. The TV screen would basically be the inline frame that would be used
42 INTRODUCTION TO HT~IIfL
to display the contents. 'You can top it off with a remote-looking menu that
will have links targeting that iframe. To create an iframe, use the tag
<IFRAME> ... </IFRA.ME>, where the space between the opening and
closing tags is used to enter the "alternate" version, in case the browser does
not support iframes (it is similar to the "noframes" section). The <IFRAME>
tag needs the following attributes:
<HTML>
<HEAD><TITLE>IFRAME in TABLE</TITLE></HEAD>
<BODY>
<CENTER>
<TABLE BORDER·=O>
<TR>
<TD ROWSPAN=3>I want <A HREF=''http://www.
getfirefox.com" tar~Tet="coolfrarne">Firefox</A>!</TD>
<TH> INLIN"E FRAME</TH>
<TD ROWSPAN=3> I want to look for <A
HREF= ..http://www.google.com ..
target="coolframe">something</A>!</TD>
</TR>
<TR>
<TD><IFRAME SRC= ..http://www.google.com ..
NAME="coolframe" WTDTH=400 HEIGHT=300 ALIGN=middle
FRAMEBORDER=O>The rframe is NOT WORKING! !</IFRAME></TD>
</TR>
<TR>
<TD align=center>This was cool</TD>
</TR>
</TABLE>
</CENTER>
</BODY>
</HTML>
SPECIAL CHARACTERS 43
SPECIAL CHARACTERS
The last piece of information necessary for now in order to start creating
Websites is how to use special characters. As mentioned at the beginning of
this chapter, you are not allowed to use the characters < and> except for tags,
but what if you wanted to use that symbol for a mathematical comparison?
Here is where special characters come in handy. Other typical example is
white spaces; as stated earlier, any large group of white spaces is translated
into a single white space by browsers, so what if you wanted to force five white
spaces between two words? Another final crucial example, at least for me, is
my last name, "Gabarr6." As you noticed, it contains an accent on the 0,
which few keyboards around the world have, and that, depending on the
regional settings, might not show up on the screen if I just use the character
"6." Many people would just ignore this and write "Gabarro," but as a proud
Spaniard, I need my accent, and luckily enough I can get it in HTML in a
way that will be printed in any computer, regardless of its settings.
All special characters in HTML start with an ampersand (&) and finish
with a semicolon (;). For example, the character "6" is written ó,
meaning that when writing my last name on a Webpage I have to spell it
Gabarró. White spaces are done with , < is &It;, and> is >.
You can find a large reference table such as that in Appendix A.
4
Work Environment
INTRODUCTION
In this chapter we will see step-by-step how to install all the software that we
will need for our Websites to run. This includes an Apache Web server, the
PHP engine, and a MySQL database. We will also see how to install and use
two powerful PHP-based applications: phpMyAdmin to manipulate data-
bases, and phpBB, a free bulletin board tool.
The installation guidelines are for Microsoft Windows based computers.
These tools also work on UNIX, but chances are you already have a Web
server and PHP installed as part of the UNIX/Linux distribution of your
choice. You can find more information on UNIX/Linux installation guide-
lines in Appendix B.
The first obvious thing to do is download all the necessary software that we
will use. The Apache Web server can be found at www.apache.org. Once
there, click on "HTTP server," find the latest stable release (the current
version at the time of this writing is 2.0.55 with a Windows installer and 2.2.0
as a UNIX source package), click on "download," and find the "Win32 binary
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavcScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
45
46 WORKENWRONMENT
(MSI Installer)," which will simplify the installation process. Download the
file somewhere safe along with all the files that we will download next.
To download PHP, go to www.php.net.click on "downloads," and choose
the newest stable Windows zip package (version 5.1.2 as of right now), choose
the download mirror closest to your geographic location, and save the file
with the Apache installer,
The MySQL server can be found at www.mysQl.com.Click on "developer
zone," and find the "MySQL server download" (current version is 5.0). Find
the Windows downloads sections and the file for "Windows (x86)" by picking
a mirror. At that point you may enter some personal information, although
this is optional.
The two last tools are phpMyAdmin and phpBB. The former can be found
at www.phpmyadmin.net. In the main page you should be able to see all the
different available versions; just download the latest stable version (2.7.0, p.
12, as of the time of this writing). Pick your favorite compression format,
choose a mirror, and download, PhpBB can be found at www.phpbb.com; go
to "download" and download the full package in zip, gzip or bz2 format,
depending on your favorite compressing tool. If you are unsure, just pick zip.
Choose the mirror again and save the file on your drive.
Installation Steps
To avoid problems, the first thing to do is stop any service that might use the
port 80, such as, for example, instant messaging tools like AIM or Skype. It
might also be a good idea to temporarily disable your computer's firewall
while you install this application.
Start by double-clicking on the installer file that you downloaded. Click
on "next," read and accept the terms in the license agreement, click "next"
again, read the description if you wish to, and then get to the "server informa-
tion" configuration page. All these settings can be modified later on, but you
might want to set them up right away. First you will see the "network domain."
If your computer is in a domain, enter that information there. If you are
unsure of your network: domain, simply type "localhost". The next field is
"server name," which represents your computer name in the domain written
right before. For example, if your domain was in.home.net, and your com-
puter name is mycomp, you would enter in.home.net in the first field and
mycomp.in.home.net in the second. As before, if you are unsure, just type
"localhost". Finally enter the email address to which users should send ques-
tions in case they encounter a problem accessing your sites.
You must then choose whether to install the application as a service for all
users on port 80, or just: for the current user on port 8080. The main differ-
ence between the two is that a service installation will basically start up your
server when the computer does, and will be working on the standard port
INSTALLING THE Apache SERVER 47
used by Web applications. The other option is to have the server running only
when you decide to launch it manually on a nondefault port. I recommend
the first option. Choose the "typical" installation, and select the folder in
which to install it (I will assume that you used the default folder in further
steps). Click "next" and then "finish."
Possible Errors
If for some reason Apache is not running at this point, chances are you will
see an error message saying "Service not installed." This is usually due to
other services running on port 80, which will prevent installation of other
services on the same port. Luckily, we can change Apache's standard port.
To do so, open a command console (click "start," then "run," and type
"cmd"), in the console access your Apache installation folder (C:/Program
Files/Apache Group/Apache2/bin), and type "apache -k install". That should
install the service, but you may still get an error saying "could not bind to
address 0.0.0.0:80". Note that ":" means "using the port." In that case, find
the file located in [ ... ]/Apache2/conf/httpd.conf and open it. This is the
most important file for Apache; it is its configuration file and is loaded auto-
matically each time the server is started. Find the line that says "Listen 80"
and replace it with "Listen 127.0.0.1:80", save the file, and again try to run
the "apache -k install" on your console. If that still does not work, again
replace that same line with "Listen 127.0.0.1:8080". The reasons for these
different errors are all related to Windows' services, and the way you access
the server. The line "Listen 80" means that Apache tries to accept incoming
requests through port 80 on the local computer. Sometimes the server is incor-
rectly installed, and there is no reference to what constitutes the "local"
computer. To force this binding, we add the 127.0.0.1 IP address, which always
represents the local computer. We are basically telling Apache which socket
to use to accept all communications. If there is another service running on
port 80, this will still not work; hence the need to change Apache's port to
something else. The port 8080 is the standard "Alternative" for Web servers.
www.allitebooks.com
48 WORKENWRONMENT
Configuring Apache
By now your basic Apache server should be running. You can check it by
opening a browser and accessing http://localhost/ (or http://localhost:8080/
if you changed the port that Apache uses). This should open a page telling
you that your installation was a success. Now it is time to set up your prefer-
ences. My first recommendation is to create a folder called "Web" on a sec-
ondary hard disk or partition of your choice. This will be the folder in which
all your Web applications will run. I will assume that your folder is "D:/Web".
Open [...]/Apache2/conf/httpd.conf and leave it open as we will be modifying
it when we install PHP.
The first thing to do is find the line that starts with "DocumentRoot" fol-
lowed by a path. Change the path to the one you will use; for example, change
the line to DocumentRoot "D:/Web." If you are afraid of messing up the
configuration file, you can comment out the existing line by placing the char-
acter # in front of the line, and typing a new line with your chosen Document
Root. Note that Apache uses forward slashes (/) instead of backslashes (\).
This allows your Apache to know which folder in your computer to go to when
trying to find Webpages. The next thing to do is set up the rights for that
folder; you may again use the basic settings, by finding the line that starts as
<Directory followed by the same path that was initially set as "Document-
Root." Replace that path with the same one you used for your "Document-
Root." Your new line should be <Directory "D:/Web">. This line represents
the opening tag for a set of rules that will be applied to that folder. It is
important to remember to set the rights to the folders you want to access, or
you may get a "forbidden" error message when trying to access it.
The next thing to set up is the list of files that will be opened by default
when trying to access a folder. This information can be found in the line that
starts as "Directorylndex index.html index.html.var." Here you may set up
any file that you would like to use as a directory index. I recommend adding
at least the following: index.php and index.htm, but you might want to add
index.php3 index.php4 index.php5 index.phtml if you are planning on running
old PHP applications.
Save the file and restart your Apache. Remember to keep your httpd.conf
file opened as we will be using it in a few minutes. If you did not make any
syntax errors, Apache should restart easily. In case of a typo, Apache should
inform you of the line with the problem. Find it and correct the typo. Access
your localhost through your browser once more. You should now see the
contents of your "Web" folder or one of the directory index files if there is one.
INSTALLING PHP5
Find the zip file you downloaded and extract it to C:\PHP\. Add C:\PHP
to your Windows PATlI. To do so, open your "system properties" window
by either right-clicking on "My Computer" and selecting "properties," or by
INSTALLING PHP5 49
selecting the option through your control panel. Click on "advanced" and
then "environment variables." In "system variables" you should see one called
"PATH"; select it, click on "Edit," go to end of the "Variable value:" field,
and add ";C:\PHP\" (without the double quotes). Do not delete any of the
other information in that field!!! Adding the PHP folder to the PATH will
help Windows find any file inside that folder. Accept all windows by clicking
on "Accept" or "OK" until they are closed.
Now go to your C:\PHP\ folder and rename the file "php.ini-recommended"
as "php.ini." You can also do a copy of that file and rename the copy. Open
the file and find the line that says ";extension=php_mysql.dll" and remove
the semicolon in front of the line. Do the same with the line containing
"textensionvphpjmbstring.dll? This will tell PHP to start up with the
MySQL and MBString extensions. The first is obviously needed to run
MySQL; the second one is needed for phpMyAdmin. Now look for the line
extension_dir = ".1" and replace it with extension_dir = c:lphplext.
One last thing you might want to do for development purposes is turn on
the error display on pages. By default, any script error is logged into a file but
does not show up on the screen. Find the section on error reporting and make
sure that you have the following lines:
error_reporting = E_ALL
; Print out errors (as a part of the output). For production web sites,
,. you're strongly encouraged to turn this feature off, and use error logging
; instead (see below). Keeping display_errors enabled on a production
web site
; may reveal security information to end users, such as file paths on your
Web
; server, your database schema or other information.
display_errors = on
Changing display_errors to ON will allow you to view any script error when
you attempt to run them. As you can read in the php.ini file, it is recom-
mended to turn this feature off for pages that will be publicly available, as it
may show information that should remain hidden to the user. For develop-
ment purposes, it's much easier if you can see all errors and notices so that
you can correct them before publishing your page.
Save the file and open your Apache's httpd.conf. Go to the end of the file
and add the following lines:
The first line tells Apache to load the PHP module when Apache starts,
which will allow PHP files to be executed. The second line adds a new type
50 WORK ENVIRONMENT'
Testing PHP
Go to your "document root" folder (D:\Web in our example) and create a
new folder called phpwork or something similar. This folder will be the one
in which all your PHP work should be saved. Inside that new folder, create a
file called index.php containing the following code:
INSTALLING MySQL
Locate the file you downloaded, decompress it, and launch Setup.exe. Choose
"typical" installation, let it copy all files, and skip signup. Make sure that the
option "configure the MySQL server now" is selected, and click on "finish."
Click "next" and choose "detailed configuration." Now through all the
windows, select "developer machine," "nontransactional database only"
(unless you are planning on using MyISAM, which I will not explain in this
book), "decision support" (assuming that the installation is for your work
computer and will be used only by a few programmers. If you are configuring
a Web server that will be accessed by many users, you might want to choose
one of the other options). Make sure that you enable TCP lIP networking, and
remember the port number (3306 by default), "enable strict mode," choose
your character set, and "install as window service." You may even choose
"include bin directory in Windows PATH" to make it easier for you to change
settings later on. Select a "root" password; this is very important, and never
forget that information. Choose whether you want to enable root access from
remote machines or not (I recommend "not" if you are going to be physically
working on the computer to prevent possible security breaches). Click on
"execute," which will configure your MySQL.
INSTALLING phpMyAdmin 51
INSTALLING PhpMyAdmin
Decompress the zip file you downloaded inside your document root, and
rename the folder to something easy for you to remember but hard for someone
to guess. This will prevent people from trying to access your administration
tool. Go to the folder and locate the file config.default.php. Either rename it
to config. inc.php or copy the file and rename the copy. Open the file (Wordpad
will probably output the text in a nicer way than Notepad), locate the line
$cfg['PmaAbsoluteUri'J = ";" and enter the absolute URI of your phpMy-
Admin folder. For example, if you called the folder "mysqIAdmin" and you
placed it in your document root, you should type "$cfg[PmaAbsoluteUri'J =
'http://localhost/mysqlAdmin';''. Next find the first line that says "$cfg
[tServers'][Si][tuser'] = 'root'; II MySQL user" and replace "root" with the
user you created with MySQL. In the following line enter the password for
that user and save the file. If you created a user "newuser" with "newpass"
as a password, your two lines should look like this:
Save the file and access the folder through your browser (e.g., http://
localhost/mysQIAdmin/). This should open up phpMyAdmin's interface. If
there is any error, it would show up in this window. Typical errors include bad
user/passwords and wrong absolute URIs.
52 WORK ENVIRONMENT
We will see how to use phpMyAdmin in Chapter 12, but for now let us
create a new database that will be used by phpBB. In the main page type the
name of the database you want to create (I will choose "forum") and click on
"create." If you look on the dropdown menu on the left menu, you should see
a new database called "forum" with 0 tables. Congratulations! This means
that your phpMyAdmin is working perfectly well.
Bulletin boards are spreading over the Internet to connect people with the
same interests in a discussion area. PHPBB is one of the most popular PHP
bulletin board solutions, mostly because of its simplicity. We will see how to
install this application and how to set it up. You will find more detailed infor-
mation in Appendix C.
Installation Steps
Start by decompressing the zip file inside your document root and rename
the folder, for example, as "forum," and access http://localhost/forum/install/
install.php. This is an automated PHP script that will configure your boards
to work with your database. Make sure that you select MySQL 4.x/5.x as your
database type (unless your host has a different database), method "install."
Your database configuration should be "localhost" for hostname and "forum"
for database name (or the name you chose when creating a test database in
the previous steps). Use the user and password you created when installing
MySQL (and the same that you used for phpMyAdmin). You should leave
the prefix with the default "phpbb_" as it will help you recognize the tables
used by phpBB. Enter your email address (for users to mail you about any
problem), enter your domain (localhost if running only locally, your com-
puter's name if you plan on using it on a local-area network only, or the
domain in which you are installing phpBB if phpBB will be used over the
Internet), your server port (80 by default), the folder in which you installed
the forums, and a user and password that you will use in the boards. It is
preferable to use a user/password different from the one in your database
settings. Each message you will write in the boards will have your username
attached to it, so you might want to use your favorite nickname.
Finish the installation by clicking on the "install" buttons until you see a
message telling you to delete two directories. Delete those two directories in
your forum/folder to prevent malicious attempts to reconfigure your boards.
Try to access http://localhost/forum/;thisshouldopenuptheboards'main
page, which should include one forum called "test forum I." Using phpBB is
very intuitive; clicking on a forum name will open the list of messages in that
category. Each message is a "thread" in which all users can discuss whatever
they feel like. Let us configure our boards and add new forums.
INSTALLING A BULLETIN BOARD: phpBB 53
Start by logging in with the user/password you entered during the install,
either by entering it at the bottom of the page or clicking on "log in." I do not
recommend selecting the "remember me" option if you are the administrator,
to avoid having someone log in as an admin through your computer and
change the forum settings. Now that you are logged in, you will notice that at
the bottom of the page there is a new link that says "go to administration
panel." Click on it, and reenter your user/password information (this is a
double-check for security reasons). The way this application works is through
the menus on the left. The main area shows the current configuration page.
When entering the administration panel, you can see the forum's statistics, as
well as who is online. PhpBB will also let you know if you have the latest
version installed.
On the left menu click on "management" to enter the forum administra-
tion. Here you can create new forums and categories. Let us start by editing
the existing one to make it look nicer. Next, to "test category 1," click on
"edit" and change the name to "announcements." Do to same with "test
forum 1" and rename it to "news," along with the description of your choice.
Leave everything by default and click on "update." You can use the two text-
boxes to create new forums and categories. Each forum will be attached to a
category. The order in which you see categories and forums is the same one
that the users will see.
The next menu ("permissions") allows you to change the rights of each
forum. Select a forum and then the rights you want to use. I recommend
selecting "advanced mode" for more flexibility. In advanced mode you can
determine who can view, read, post, reply, edit, delete, turn a thread into a
sticky thread (always remaining on top of a forum), turn a thread into an
announcement (like sticky threads, but with a different icon), vote in polls,
and create a poll. The options for each one of these categories are ALL to
allow use for everybody, REG to allow it only for registered users who have
created a user and a password, PRIVATE to only allow it for the users or
groups of your choice, MOD to only allow it for moderators, and ADMIN to
allow it only for administrators.
A little further down in the menu you will see "configuration." This
is where you can set all the settings for your boards, and is pretty self-
explanatory. While you are there, change the "site name" and "site descrip-
tion" to something more welcoming than "yourdomain.com" and "a_little_text
to describe your forum." If you wish to force users to enter valid email
addresses when creating a new account, select "user" in the "enable account
activation" option. I recommend that you also enable the visual confirmation
and disable user emails via the board. Change your system time zone [e.g.,
EST time is GMT (Greenwich Mean Time) -5].
Finally, at the end of the menu, you can see the "User Admin," where you
can manage users individually, create ranks, and set individual permissions
or moderator rights.
54 WORK ENVIRONMENT
Now that you have everything installed, keep everything safe!! Remember
that PHP is a server-side language, so any PHP script runs on your server and
can access any file on the server even if that file is not accessible through your
http://localhost/. Take advantage of this to store files that may contain secret
information in folders that are not in your document root if you are running
Windows. For example, if you have a file required by PHP that contains your
database information (user, password, domain, etc.), you can store it on
C:\UltraSecretStuff\, and later, when PHP needs to access it, just enter the
local path instead of an "http" address. This way, users will not be able to
attempt opening the file.
If you are running on a UNIX/Linux machine, use tools like chmod and
chown to your advantage. By default, PHP applications run with limited user
permissions on U'Nl Xrlinux servers, so that you can create folders and allow
only yourself the right to enter them. This way anyone trying to access the
folder through an ''http://'' will get a "forbidden" error page, whereas your
PHP will still be able to access the folder and its files. For example, if your
document root is located in -/web/ and you create a folder -/web/includes/
with important information needed by PHP, you might want to set that
folder's rights to read and execute only for the owner.
A file's rights on a lJNIX/Linux system is represented through a set of
letters (that you can see if you type "Is -I" in the folder containing the files).
The letter r stands for read, w for write, and x for execute. These letters appear
in groups of three and are either present or replaced by a dash (-). There are
three groups, the first for the owner of the file, the second for the people in
the same group as the owner, and the last for the rest. If, for example, a file
has -rwxr-xr-- before its name when doing "Is -I," this means the user can
read, write, and execute the file or directory; people in the owner's group can
read it and execute it; and the others can only read it. All folders inside the
document root that need to be accessible by all users should have the rights
-rwxr-xr-x or what we call "755." The number is basically the translation of
the rights into octal. Each group of three characters (r, w, and x) represents
a single bit set to 1 if the: letter is present or 0 if there is a dash. For example,
rwx would be binary 111, which equals to 7 in octal; r-x is 101, which equals
to 5. To change a file's rights, you need to type chmod rights file, for example,
chmod 755 myfile. When a folder contains secret information, you might want
to set it with a chmod 700 folder to allow yourself to read, write, and execute,
but forbid access to all others (except the root user, of course). PHP should
still be able to access those folders, but no one else would from their
computers.
CONCLUSION 55
You may also want to use chown, which allows you to change the owner
of a file. For example, typing chown myuser myfile will change the owner of
myfile to the user myuser.
CONCLUSION
If you have reached this step with no errors, congratulations!! You probably
survived the hardest part of working with PHP. Now let us start using what
we have installed and learn the PHP basics.
5
JPllJP--Lt Server-Side
Scripting Language
Web Application Design and Implementation: Apache 2, PHP5, MySQL, Javo Script, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
57
58 PHP-A SERVER-SIDE SCRIPTING LANGUAGE
Syntax Generalities
PHP code is usually inserted inside HTML code. This allows for small parts
of an HTML page to be executed before the page is downloaded to the user's
computer. To insert PHP code in any page, you must use <?PHP. For a long
time it was fine to just write <?, but the newer versions of PHP encourage the
use of the full «? PHP opening tag, to prevent all possible confusion in execut-
ing the scripts. Once the opening symbol has been written, you enter the
"PHP zone." Anything that you type will be executed by your PHP engine
before you send the final page to the user. When you are done writing your
script, or portion of script, you must close the "PHP zone" with Y». You actu-
ally already saw an example of this when we wrote our index.php file contain-
ing <?PHP phpinfo(); ?'>. This means that we start the PHP, and call the
function phpinfo(). This is the function that outputs all the configuration
settings of PHP. Each instruction in PHP must end with a semicolon, not
doing so will make the page not work, so be careful!
You can create comments in PHP by using the same symbols as in C lan-
guage. You can either select an area of comment, starting with 1* and finishing
with *1, or you can use II to comment anything from there until the end of the
line. Here is an example:
<?PHPI* --------- lNDEX.PHP FILE --------
---- This file checks the phpinfo ----*1
phpinfo(); I/This is the line that will be executed
II the rest are all comments
?>
INSTRUCTIONS
In PHP you may use instructions, functions calls, loops, and conditions (plus
objects with PHP5), but never forget the semicolon at the end of each function
call and every instruction.
A first easy function to use is echo, which allows printing on the page.
Remember that when you run PHP code, it runs in the server, and any output
that occurs will appear instead of the code where the instruction was called,
so if you wish to make an "echo" in an HTML page containing all proper
tags, you should place the PHP code between the opening and closing body
tags. Here is a clean example:
<HTML>
<HEAD>
<TITLE>Scriptl</TITLE>
</HEAD>
<BODY>
<?PHP echo "Hello World!"; ?>
<IBODY>
<IHTML>
www.allitebooks.com
INSTRUCTIONS 59
$a = 100;
$b = $a;
This would store the elementary expression 100 into the variable $a. Then
the elementary expression $a (containing the value 100) would be stored in
$b. In the end both $a and $b would be equal to 100.
Another type of expression consists of functions. Assuming that we have
a function called test() that returns the value of 100, doing $result = test();
would use the function test() as an expression and store it in $result making
that variable hold the number 100.
It is also possible to postincrement, postdecrease, preincrement, and pre-
decrease a variable. This is still considered an expression. Check this code:
<?PHP
$var = 100;
echo $var++; Ilechoes $var and" increments it by 1
echo ++$var; Ilincrements $var by 1 and echoes it
echo $var--; Ilechoes $var and decreases it by 1
echo --$var; Iidecreases $var and echoes it
?>
If you execute this code, you will note that it outputs 100102102100 with no
spaces between the numbers. This is due to the fact that we are only output-
ting numbers, without inserting white spaces or breaks of line. We will see
further on how to concatenate strings to variables.
PHP expressions can also be the values TRUE and FALSE. By default,
these two constants are equal to 1 and 0, respectively. Note that if you write
<?PHP
$var = TRUE;
echo $var;
?>
$a -= ($b + $c); will calculate $a - ($b + $c) and store the result in $a
$a *= $a; will multiply $a by $a and store the result in $a
$a /= 2; will divide $a by 2 and store the result in $a
The last basic type of expression is the conditional operator. This allows us
to check a Boolean value (TRUE or FALSE) and use an expression if the
value is true, a different one if it is false. The basic syntax is expression1 ?
expression2 : expression3;. In this example expression] will be checked as
true or false. If it is true, then expression2 will be evaluated. If it was false,
expression 3 will be evaluated. For example
<?PHP
$a = 100;
$b = 50;
$c ($a < $b) II will compare $a to $b i f
?' 50: 25;
~$a is less than $b, 50
//is evaluated. I f $a is greater or equal than $b,
Iithen 25 is evaluated.
echo $c;
?>
This example would output 25. Remember than an expression can be a func-
tion or even an operation, so you could use this to calculate a positive differ-
ence as follows:
MATHEMAnCALFUNcnONS 61
<?PHP
$a = 100;
$b = 12;
$positive_difference = ($a >= $b) ? ($a - $b) ($b - $a);
echo $positive_difference;
?>
OPERATORS
MATHEMATICAL FUNCTIONS
DATA TYPES
$a = 5;
$b = (double)$a;
64 PHP-A SERVER-SIDE SCRIPTING LANGUAGE
Remember that when using the "identical" (===) comparison, the types of
the compared variables must be the same!!
Here is an example code illustrating types:
<?PHP
$a = 5;
echo get type ($a)." H.,
$b = (double)$a;
echo get type ($b)." H.,
i f ($a -- $b)
echo "$a and $]:) are the same!! ";
else
echo "$a and $J":> are different!! ";
i f ($a --- $b)
echo " And the}' are identical! ";
else
echo " But the); are NOT identical!! H;
?>
This code will output integer double 5 and 5 are the same!! But they are NOT
identical!!
CONSTANTS
NULL: Same as 0
FILE__ Name of the current running PHP file
LINE__ Current line of PHP code being executed
VARIABLES 65
VARIABLES
<?PHP
i f (fisset($_POST["name"})) II I f the variable "name"
sent through
{ lithe POST method is not set
echo "You did not arrive here through the form f ";
exit o,
}
else
{ II regular code goes here
}
?>
66 PHP-A SERVER-SIDE SCRIPTING LANGUAGE
<?PHP
$a = 0;
while (isset ($a))
(
II do eometib iriq and at one point do the next line
unset ($a); II this will unset the variable, so the while
II condition will no longer be true
}
?>
of a static variable should always happen in the line that declares it as static;
this way the initialization will occur only the first time the function is called,
without overwriting its value in each successive call. Check this example:
<?PHP
function static_example ()
{
static $count = 0;
echo "You have called the function ".++$count." times";
}
?>
The first time the function is called, a variable $count is created as static,
and set to O. This will only happen the first time the function is called; the
next time, the program will understand that $count already exists. When we
echo the string "You have called the function," note that right after this string
we have placed a dot (.), allowing the concatenation of anything to the previ-
ous string. We concatenate ++$count, which will then be concatenated with
"times." Our total string will tell us how many times we accessed the function.
The preincrement is due to our initialization to 0 of the static variable. The
first time the function is called, the preincrement will modify $ count from 0
to 1. Next time the function is called, $count will still be holding 1, and will
be incremented to 2 before echoing the message.
6
PHP Arrays and
Flow of Control
ARRAYS
Basic Arrays
Arrays are sets of data stored as a single variable. You could imagine a set as
a cabinet with multiple drawers. Each drawer holds an element, and the posi-
tion of the element is called its "index." Unlike most programming languages,
where arrays hold values of the same type, arrays in PHP can hold any type
of data in each one of its elements. This makes PHP arrays much more flexible
but can potentially create many problems if you don't remember the types
used for each index. In order to store values inside an array, you need to place
the index to access between square brackets, right after the variable name
holding the entire array. For example, if $myArray is an array, you could
access the element at index 3 by writing $myArray[3}. Note that indices start
at 0, but you are not required to use consecutive indices. In other program-
ming languages you must use index 0, then 1, 2, 3, and so forth. In PHP you
may have an array with three elements positioned at indices 12, 42, and 51,
for example. It is not recommended but it causes no issues. Here is an example
that stores an integer, a string, and a double in the same array and then will
echo the types of those elements:
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
69
70 PHP ARRAYS AND FLOW OF CONTROL
<?PHP
$var[O] = 1;
$var[l] = "Two";
$var[2] = 3.00;
$i = 0;
while ($i < count ($var)) (
echo get type ($var[$i]) . u<BR>";
$i++;
}
?>
Don't worry about the while section, as we will discuss this a few sections
later. Note the use of the function count that returns the number of elements
inside an array. Also, doing $var[$i] simply reads the element at the index
$i.
It is also possible to define an array as a single line using the function array.
Check this example:
<?PHP
$ var = array(); Ilcreates an empty array, useful to
Ilavoid some notices
$var2 = array (1, "Two", 3.00); Iisame array as we had
Ilbefore
?>
Associative Arrays
It is also possible to create associative arrays. An associative array is basically
an array in which the index can be a word. It is important to realize that an
element in an associative array will actually have two indices. First you will
have the real index of the element, as indicated during its creation. This "real
index" is generally called the "key" of the element. The other index is a num-
bered index that is known internally by PHP, which basically holds the order
in which the elements are held in the array. Check this example:
<?PHP
$var[Unumber"] = 1;
$var[Ustring"] = "Two";
$var["secondnum H ] = 3.00;
?>
In this example we have created an associative array with three elements. The
keys of these elements will be "number," "string," and "secondnum," but you
will still be able to refer to the elements through the indices 0, 1, and 2,
ARRAYS 71
respectively. The numbered indices will always respect the order in which the
elements are in memory.
Another way to create an associative is through the array method, as we
used with regular arrays. The difference is that in this case you are to write
the entries using the format "key"=>element. For example, the previous asso-
ciative array would be written
Multidimensional Arrays
One final type of array is the multidimensional array. This basically repre-
sents an array that contains an array as one or more of its elements. This could
be used, for example, to hold information on different contacts for an address
book. Check this code:
<?PHP
for ($i=O; $i < 10; $i++)
$contacts [$i] = array (
"Name"=> "Name" . $i,
"Surname"=> "Surname" . $i,
"Tel "=>$i} ;
foreach ($contacts as $c=>$details) II loop 1
foreach ($details as $key=>$elemJ II loop2
echo $c.":" . $key."".$elem."<BR>"; II instruction
?>
0: Name Name 0
0: Surname Surname 0
0: Tel 0
1: Name Name 1
1: Surname Surname 1
1: Tell
2: Name Name 2
2: Surname Surname 2
2: Tel 2
[ ... J
and so on until number 9.
Let us see how the script works. First we use a "for" loop (which we will
study after a few pages) to create 10 entries in a regular array. Each entry
contains an associative array containing a name, a surname, and a telephone
72 PHP ARRAYS AND FLOW OF CONTROL
or
Each execution of the: code under the foreach is called an iteration of the
loop. In the first iteration, $elem will hold $arr[OJ; in the second iteration,
$elem will be the same as $arr[1J; and so on until there are no more elements
in the array, in which case the program will skip directly to the instruction
after the iterating statement. It is important to realize that your $ elem holds
an actual copy of the element in the array, not the element itself. Note that it
is possible to group several instructions in a same loop by simply surrounding
all the statements with curly braces. For example, the following code will run
two instructions in each iteration:
The second version of foreach allows the creation of two variables, one for
the current key, and one for the element associated with that key. Obviously
this is useful mostly with associative arrays, but you may still use it with
regular arrays, in which case your keys will be the indices of each element.
ARRAYS 73
In our contacts example, the first foreach loop will check the $contacts array.
Each entry in this array is an array, and the keys are simply numbers. The
foreach will fill the variable $c with the current index, and the variable
$details with the current entry, corresponding to the associative array with
all the information on the contact. Since $details is an array, we may check
its contents with another foreach. Our second foreach will parse the current
$details array and fill $key with the current key and $elem with the entry
associated to that key. Here is how the program runs:
After the $contacts array is filled up and we enter the first loop:
$c == 0; $details == $contacts[O];
We enter the loop 2, checking the contents of $details
$key == "Name"; $elem == "Name 0";
We execute the instruction.
Iteration 2 of the 100p2
$key == "Surname"; $elem == "Surname 0";
We execute the instruction.
Iteration 3 of loop 2
$key == "Tel"; $elem == 0;
We execute the instruction.
There are no more entries in $details so loop 2 is done
Iteration 2 of loop 1 starts
$c == 1; $details == Scontactsj l];
We start a new loop 2, checking the new contents of $details
$key == "Name"; $elem == "Name I";
[...] Similar execution for all the middle entries...
Iteration 10 of loop 1 starts
$c == 9; $details == $contacts[9];
We enter the loop 2, checking the new contents of $details
$key == "Name"; $elem == "Name 9";
We execute the instruction.
Iteration 2 of the 100p2
$key == "Surname"; $elem == "Surname 9";
We execute the instruction.
Iteration 3 of loop 2
$key == "Tel"; $elem == 9;
We execute the instruction.
There are no more entries in $details so loop 2 is done
There are no more entries in $contacts so loop 1 is done
Our program finishes its execution.
<?PHP
$friends[O] [0] = "Steven";
$friends[OJ [lJ ["father"] "Peter";
$ friends [0] [1] Irmotztiei:"l = "Jackie";
$friends[O] [lJ["sister"J = "Romina";
$friends[lJ [OJ = "Christian";
$friends[lJ[lJ["brother"J = "Daniel";
II and so on
?>
As you can see, we can utilize the flexibility of PHP to create entries that do
not necessarily hold the same information. The only common thing is that
for each friend indexed at $i, $friends[$i][O] will always be a name and
$friends[$i][l] will be an array holding an associative array with the rela-
tives. If you wanted to show the entire list of friends and their relatives you
could use the following code:
<?PHP
II we assume tzhet: we have a filled $friends array as
in the previous exempl.e
foreach ($friends as $oneFriend)
{ echo "Name: " . $oneFriend[O]. "<BR>";
foreach ($o11eFriend[lJ as $relation=>$name)
echo $relcl tion. " : " . $name. "<BR>";
echo "<BR>"/
}
?>
Array Functions
Here are some important functions useful for arrays manipulations. Realize
that each time you have an array there is an internal pointer that informs you
of the current position in the array. It basically refers to the current element's
index.
ARRAYS 75
<?PHP
II we are assuming we have an array $arr holding integers
I I we sort using our compare function (which will
produce a reverse sort)
II and we print the results
usort($arr, "compaxer ),
foreach ($arr as $key=>$elem)
echo "$key=>$elem H ;
function compare ($a, $b) {
i f ($a==$b)
return 0;
elseif ($a < $b)
return 1;
else
return -1;
}
?>
Conditions
You can have your program select different paths in your program depending
on your own conditions. You can do this using the if. . . elseif. . . else state-
ments. The basic structure is
78 PHP ARRAYS AND FLOW OF CONTROL
if (condition)
instruction},.
elseif (condition2)
instructions;
else
instructions;
<?PHP
if ($a < $b) II checks if $a is lower than $b
echo Sa. " is less than " . $b;
elseif ($a > $b) II we get here only if $a was NOT
Illess than $b
echo $b. " is less than " . $a;
else II $a is not lower nor greater than $b
echo Sa. " is equal to " . $b;
?>
Attention!! If you wish to compare for equality, make sure to use either
the double or triple equal sign to check for equality or identical variables.
Watch this example:
<?PHP
if ($i = 34567)
echo "This is always true!!! ";
?>
<?PHP
if ($a < 100) II first condition
if ($b < $100) II this if statement is the
Ilbeginning of the
II block that will run i f the first
Ilinstruction is true
echo "both numbers are· less than 100";
else I I this else refers to the previous if, and is
Iistill
II part of the same block inside the first
Ilcondition
echo "Only the first number is less than 100";
elseif ($a == 100) II the previous else finished the
Iisecond if
II block, so this elseif refers to the first
Ilcondition
echo "The first number was 100"
else I I this else refers to the elseif, and is part
Ilof the
II block started with the first condition
echo "The first number was greater tihen 100";
?>
You may avoid headaches and confusion' by simply using curly braces
for a better view of each block. The general structure would look like
this:
if (condition)
{ statements if true
}
elseif (condition2)
{ statements if condition is false and condition2 true
}
elseif (condition3)
{ statements if condition and condition2 are false but condition3 is true
}
else
{ statements if all conditions were false
}
switch ($variableToCheck) {
case valuel:
statements
break;
case value2:
statements
break;
default:
statements
The program will successively compare the $variableToCheck with all the
different values written next to the case keyword. If a match is found, the
program will run every instruction placed between the following colon symbol
(:) and either the first break statement or the closing brace (whichever happens
first). The case lines are not really considered instructions; you can think of
them as little labels in front of the code lines. Therefore you can put several
cases together, by listing many case value: lines before starting to write the
code. Note that if you omit the break statements, the program will continue
to execute the following instructions even if they were meant to be for a dif-
ferent case. The default case is run if no matches were found among the
values. Here is a small example:
<?PHP
$i = 2;
switch ($i) {
case 0:
case 1:
echo "i was either 0 or 1";
break; .
case 2:
echo "i was equal to 2";
break;
case 3:
echo "i was 3";
break;
default:
echo "I don't: know what i was, because I can't
count to more tha.n 3!";
}
Loops
A loop is a way to repeat one or more statements a determined number of
times. We already saw one type of loop adapted to arrays: the foreach.
PHP PROGRAM STRUCTURE AND FLOW OF CONTROL 81
The most basic loop is the while loop. It receives an expression that is tested
before starting each iteration. The loop will keep on going until the expression
becomes false. For example
<?PHP
$i = 0;
while ($i < 10)
{ echo $i++;
echo
}
?>
This loop will check whether $ i is less than 10. If it is, it prints $ i and incre-
ments it by one with the postincrement operator, prints a white space, and
checks $i again. The moment $i is no longer less than 10 (Le., when it reaches
10), the loop finishes. This code will show the numbers from 0 to 9 on the
page. This type of loop is excellent in testing for a specific value change, but
make sure that the statement can eventually be false, or you will enter an
infinite loop!! Note that if the condition is false before the first iteration, the
loop will never be entered and the body of the loop will never execute.
If you wish to make a loop that allows you to run its body at least once
before checking the condition, you may use do . . . while. This type of loop
works the in same way as a while but checks the condition after each iteration.
It will always run the body at least once. The general syntax is
do
( statements
) while (condition);
If you wish to count a specific amount of numbers, you can use a for loop.
This type of loop works similarly to a while but it allows you to run a set of
expressions before the first check of the condition, and you can have a set of
expressions to run after each iteration. The general syntax is
All the expressions before the first semicolon are run only once, before
entering the loop, the condition is tested before each iteration, and all the
expressions after the second semicolon will run at the end of each iteration.
Multiple expressions are separated by commas.
For example, the following loop would initialize $i to 0 and would then
check whether $i is less than 10; if it is true, it will print the value followed
by a white space and will increment $i by one-this loop will finish when $i
reaches 10:
82 PHP ARRAYS AND FLO~V OF CONTROL
Regardless of the typle of loop you are using, you may quit the loop by
typing break;. It is also possible to force a new iteration without letting the
loop finish the current one by typing continuet.
FUNCTIONS
Functions are usually written in include files or at the end of your program.
They don't require specifying a return type, since you may store any type in
any variable. The same goes for the parameters list. You do not need to
specify their types. Note that variables defined in a function, as well as the
names used for the parameters list, are local to the function. This means that
they have meaning only inside the function. To return a value from a function,
simply use return followed by the value to return. For example, you could
write and use a function called average to calculate the average of two numbers
with the following code:
<?PHP
$a = average(12,76}; //12 and 76 are called the
I/arguments sent to average
function average($:x~, $y) II $x and $y are called the
Ilformal parameters
{return ($x + $)1") I 2;
}
?>
<?PHP
$x = 5;
add_one ($x);
echo $x; / /this will echo 6
function add_one (&$a)
{ $a++; }
?>
7
Using Files, Folders, and
Strings in PHP
USING FILES
The first useful thing to do in PHP with files is to use include files. These are
files that are linked from any script through two possible techniques. Include
files usually hold data such as user and password information for database
connection, sets of functions commonly used, and headers and footers used
in every page.
One way to link to an external file is to use include(filename);. Note that
the filename could be a Web address of the type http://www.blabla.com/
myfile.php, a relative path ./includes/include.php, or an absolute path lusrl
home/sgabarro/includes/include.php. Note that PHP can access any file in the
server (assuming that the proper permissions were set) even if those files are
not accessible through the Web server. It is very important to exploit this
ability when including files containing important information such as data-
base settings, since it prevents malicious users from accessing those files
through their browsers.
Doing an include will insert the external file inside the including script. If
the called file has a return value, you may retrieve that value by storing the
return value of the function include. Note that this function can be used inside
loops.
The other method to link to files is require(filename). This will execute
the called file before inserting it in the script. It cannot use a return value,
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
85
86 USING FILES, FOLDEHS, AND STRINGS IN PHP
and it cannot be used in loops. I personally use require when I have sets of
pages with the same header and footer, to make my code easier to read. The
idea is to have a header.php file containing all initializations needed for your
scripts, as well as all the needed HTML tags; and a footer.php file with all
the closing instructions needed, as well as the closing HTML tags such as
-c/body> or -c/htmb-, Your pages would then look like this:
It is also possible to use files for things other than linking to include files.
One thing to remember is that any file written, modified, created, or destroyed
will be in the server since PHP is server-side. So it is a very bad idea to think
of doing a malicious PI-IP script that will erase important files such as your
windows.ini or php.ini files and putting the file in an accessible folder of your
Web server. This would allow anyone to run the script erasing your files, as
the script is in your server. So think carefully about what you are doing in
your scripts before running them.
The first thing to do when you want to use a file for reading or writing
purposes is to open it. To do so you may use the function fopen. This function
returns a file descriptor that will be used by all other reading and writing
methods. The function receives two parameters: the path to the file to open
(URL, relative path, or local path) and a flag specifying the opening mode.
The mode can be
"r" Read only
"r+" Read and write
"w" Write only
"w+" Read and write, erasing the file if it exists and creating it if it
doesn't
"a" Write-only but placing the internal pointer at the end of the file if it
exists and creating it does not exist
"a+" Read/write, placing the internal pointer at the end or creating the file
if it does not exist
In any case, you may add a b to indicate that you are using a binary file (e.g.,
"ba" will refer to a binary file opened as "append."
Realize that you may open a file for writing only if you have the proper
permissions on that file. Assuming that you have the proper rights, you could
create a new file for read/write doing
• fclose($fp)-closes the file. You should always close a file when you are
done with it.
• feof($fp)-checks whether the internal pointer is at the EOF (end of
file).
• fgetc($fp)-reads the character at the current location and moves the
internal pointer forward one character.
• fgetcsv($fp, $len, $sep)-reads a "comma-separated values" file and
returns a single line of that file as an array containing the comma-
separated values. $len and $sep are optional parameters. $len is the
maximum length of a single line; $sep is a single character used as
separator (set to "," by default).
• fgets($fp, $len)-reads a string of up to $len-l bytes from the current
location. Reading will also stop if there is a new line (\n) or the pointer
reaches the EOF. Returns FALSE if you try to read beyond EOF.
• fgetss($fp, $len)-same as fgets but strips all HTML tags in the line.
• fpassthru ($fp ) -outputs all the bytes from the current position until the
EOF.
• fputs($fp, $str) or fwrite($fp, $str)-writes the contents of $str.
• fread($fp, $len)-similar to fgets but stops only when up to $len have
been read or EOF is reached.
• fseek($fp, $ offset, $whence)-changes the location of the internal
pointer. The new location is calculated through $offset (a number),
depending of the value of $whence as follows. If $whence == SEEK_SET,
set position equal to $offset bytes. If $whence == SEEK_CUR, set posi-
tion to current position plus $ offset. If $whence == SEEK_END, set
position to EOF plus $offset (in this case you should make sure that
$offset is negative). If omitted, $whence is set to SEEK_SET.
• ftell($fp)-returns the position of the file pointer.
• rewind($fp)-places the internal pointer at the beginning of the file.
This is the same as doing fseek($fp, 0, SEEK_SET);.
fseek($fp, 0, SEEK_END);
$size = ftell ($fp);
If you wanted to read all the lines in a file and output them with the line
number in front of each of those lines, you could use the following code:
88 USING FILES, FOLDERS, AND STRINGS IN PHP
<?PHP
$path = ".Ifile.txt"; II our file path
$i = 1; I lour line counter
I f ($fp = fop en ($path, "r")) Iinote that we can use the
,II single = because fopen will return
,II FALSE i f there is a problem
{ echo "File Opened-ctst:» <BR> ";
while ($line z: fgets ($fp, 100)) II we assume that
Iino line is
I I longer than 100 characters
{
echo $i++.": ". $str."<BR>";
}
fclose($fp); II DON'T FORGET TO CLOSE THE FILE!!!
}
else
echo "Could not open file";
?>
Here are some file manipulation functions that can be used with a simple
path rather than a file handler $fp:
• copy($src, $dst)-mlakes a copy of the file in the path $src into the file
specified in the path $dst. Make sure that you have the proper rights to
create files in the folder you are trying to copy to.
• readfile($file)-readls a entire file and ouputs its contents. This is the
same as doing an [open followed by a fpassthru.
• rename ($oldpath, $newpath)-renames (or technically moves) a file
from the oldpath to the newpath.
• unlink($path)-fun yet dangerous function. It deletes the file specified
in $path.
It is also possible to retrieve information from the file system with the fol-
lowing functions (there are many functions, but I am going to list those that
I consider the most useful ones):
When testing these methods, you may realize that sometimes your PHP
code perceives a file as a directory or a directory as a file. This might happen
when trying to check the type of a file or directory that is not in the current
working directory. The current working directory is the location in your hard
drive from where the script is running (basically, wherever your PHP file is
stored). It is possible to change the current working directory in PHP by using
the method chdir($dir). This will continue executing whatever script you are
in, but will consider $ dir the actual current working directory. When checking
files or directories in PHP it is highly recommended that you do a chdir to
the containing folder before checking the types or even reading the contents
of that folder.
FOLDER MANIPULATION
Assuming that you have used chdir to access a folder that you want to explore,
it is possible to retrieve information on that folder through the following
methods:
Here is an example of how you could open a directory, check the free space
available, and display the directory's contents:
<?PHP
$path="D:/Web/";
chdir($path) ;
$folder = opendir($path);
$free = diskfreespace ($path);
echo "Let's check". $path. "contents<BR>";
echo $ free." byties free<BR> " ;
while ($file=readdJ~r($folder)) {
echo $file. "<BR>";
}
closedir($folder) /
?>
Changing a String
When manipulating strings received through forms, it is a common problem
to have many extra white spaces before and after the actual string. Another
common problem is special characters, such as single or double quotes or the
backslash character. These characters have a special meaning in database
BASIC STRING MANIPULATION 91
As we shall see in the indexer case study at the end of this chapter, we
sometimes need to make sure that all strings have the same casing. This can
simply be done by using strtolower($str) or strtoupper($str), which respec-
tively turn all letters to lowercase or uppercase. You can also format strings
to be used as nicer titles by either making the first letter in the string a capital
letter, or even better, capitalizing the first letter of each word (this looks
very nice in titles). You do this with either ucfirst($str) or ucwords($str),
respectively.
If you ever need to reverse a string, this can be easily done with
strrev ($str) -and finally, probably two of the most useful string manipulation
functions are explode and implode. As you can probably imagine with these
names, one is the reverse of the other. The goal of an explode is to breake a
string into an array. This works by providing a string and a separator, and it
returns an array containing all the entries that where separated by the separa-
tor. For example, explode("Let us explode this!", " "); would explode the
92 USING FILES, FOLDERS, AND STRINGS IN PHP
There are some alternatives to the explode method when you are trying to
extract words from a string that contains many special characters such as
double quotes, arithmetic symbols, new lines, tabs, or any such character. The
most efficient option would probably be regular expressions, but that section
will be covered in a much later chapter. The other alternative is to tokenize the
string. To do so, we use the function strtok($str, $sep). This function splits the
string $str into smaller strings called tokens, with each token delimited by any
of the characters from Ssep. The way it works is that each successive call to
strtok will return the next token. The $sep parameter needs to hold a string
with all the specialcharac:tersto be considered separators. When strtok cannot
find any more tokens, it will return false, which makes this method ideal for
use inside a while loop. Here is an example taken from www.php.net:
<?php
$string = "This .is\tan example\nstring"i
/* Use tab and newl ine as tokenizing characters as well
*/
$tok = strtok($string, " \n\t")i
while ($tok !== Lel.ee) {
echo "Word=$to:k<br />"i
$tok = et.rtzokt " \n\t")i
}
?>
In this example, the string $string is broken down into "this," "is," "an,"
"example," and "string." Even though there were no white spaces between
some of these words, a separator was found, causing strtok to recognize that
a nonword character was found. Each iteration of the loop will have a single
word. Note that only the first call to strtok needs to provide the string to use.
Any further call to strtok will remember what string was being tokenized and
the location where the previous called stopped. You may restart the tokeniz-
ing or tokenize a different string by providing the string as a parameter again.
BASIC STRING MANIPULATION 93
This function is obviously different from explode, but it can be used with an
array to make an advanced explode that will accept more than one separator.
Here is an example:
<?PHP
/* Function superExplode takes a string to be turned
into an array and a string with all characters to be
considered separators.
PRE-Conditions: both string are non-empty
POST-Conditions: An array will be returned containing
each token found */
function superExplode ($str, $sep)
{
$i = 0;
$arr[$i++} = strtok($str, $sep);
while ($token = strtok($sep))
$arr[$i++} = $token;
return $arr;
}
?>
would say that the second string is greater since 9 > 1, but strnatcmp
would say the first string is greater since 123 > 9; strnatcmp is also
case-sensitive.
• strnatcasecmp($strl, $str2)-natural, case-insensitive comparison.
• strpos($str, $tofind, $offset)-finds the first match of $tofind in $str,
starting the search on the character at position $offset ($offset will be
94 USING FILES, FOLDERS, AND STRINGS IN PHP
equal to 0 if you omit it). Returns the position of the found match in the
string or FALSE if it was not found. If you write this method in a while
loop, realize that this method might return 0 if the match is found on the
first character, but since FALSE == 0, your loop will exit prematurely.
You can avoid this by using the identical (===) or not identical (!==)
operator, since the 0 returned when a match was found will be an integer,
whereas a 0 or FALSE returned when there was no match will be con-
sidered a Boolean. For example, if you wish to echo the index of all
strings "match" in Sstr, you could write
<?PHP
II we assume that $str has a string
$i = 0; II $i will be used to store the index of
Ileach match
while (($i = strpos($str, "match", $i)) !== FALSE)
echo $i++." H;
II We increment $i so that next search starts after
II the last match to avoid an inflnite loop
?>
• strrpos($str, $tofind, $offset)-reverse find. Will find the last location of
$tofind in $str before the index $offset. $offset can be omitted, in which
case it will be considered equal to the length of the string minus one.
• substr($str, $start, $length)-returns the substring from $str starting at
$start with $length characters. For example, substr("Hello World", 2, 5);
would return the string "110 ~"
Formatting Strings
Here are a set of functions that can be used to print formatted strings:
PHP provides a very useful method to retrieve all the META information
as an array called get_meta_tags($url). The returned array is an associative
array holding the name of the META tag as a key and the content as the
element. If we were to call this function on a file containing the previous
example of META tags, our array would be as follows:
A common problem when mixing HTML and PHP is new lines. When
printing a new line (\n) in PHP, we are technically inserting a new line on the
resulting HTML code that will be printed by the browser, but as we know, a
\n is shown by browsers as a white space. Many times you will be trying to
either show information retrieved from a text file or even a database that was
not necessarily formatted in HTML, meaning that it contains many new-line
characters, but no <BR> tags that would allow the new line to appear on the
resulting Webpage. You can solve that by using nI2br($str), which will return
a new version of $str that will have <br /» inserted before all new lines (\n).
96 USING FILES, FOLDERS, AND STRINGS IN PHP
Another source of problems are URLs that contain special characters such
as white spaces. Many browsers will not accept a link containing white spaces,
and will understand those links only if the code of the special character is
written. For example, a white space is usually represented as %20 in a URL.
When URL contains those special characters represented as the percentage
sign followed by the code of the character, we say that the URL is encoded.
If you want to show the same URL with regular characters (e.g., replacing
%20 with a white space), you say that you are getting the decoded version of
the URL. You can switch easily between encoded and decoded URLs by
using rawurlencode($url) and rawurldecode($url), which will return either
the encoded or decoded version of the $url. As a basic rule, always encode
the URLs you are going to insert in an HTML link, and always decode the
link names you want to show on the actual page. So, for example, assuming
that $url is your URL, you could write the following code (code in boldface
is PHP code, the rest is regular HTML):
Last but not least, one of my favorite functions that will prove extremely
useful for our indexer is strip_tags($str). This function takes a string and
returns the same string with every single HTML tag removed from it. Here
is an example:
<?PHP
$str = "<B>I am</B> a <I>string</I><BR>with loads of
<A HREF=\ ''http://ww'w.w3c.org\''>HTML</A>;
$str2 = strip_tagrs ($str);
echo $str2;
?>
The variable $str2 would hold "I am a string with loads of HTML."
PHP has a set of methods used to retrieve information on its actual settings.
Here are some of the most important ones:
CLOSING REMARKS
With all the functions and techniques studied to this point you can write
almost any script you wish. The only important thing needed (coming in
Chapter 9) is how to send information between different scripts, or how to
send information from HTML to PHP using forms (also in Chapter 9). The
following chapter will be devoted to PHP5 techniques and object-oriented
programming. Now it is the time to test your skills, and the best way is to
practice, practice, and practice some more. PHP is a very easy language, but
writing scripts will end up taking more time than you expect, so have patience
and take your time to make sure that you write the best possible code. The
only limit right now is your imagination. To get you started, here is a first
PHP assignment.
Requirements
The following guidelines are recommended:
• To keep it simple, your script should have a variable called $path that
will hold the path to check.
98 USING FILES, FOLDERS, AND STRINGS IN PHP
• You should make sure that the variable $path represents a real directory
and that you print an error if this is not the case.
• The explorer should now check the contents of the folder
• You should then echo the contents of the folder by first writing all the
folders in alphabetical order, followed by all the remaining files also in
alphabetical order. For example, if your folder contains the files bla.htm,
foo.php, bar.mp3, and the folders Music and Work, you should display in
order "Music, Work, bar.mpS, bla.htm, foo.php."
• Try to show what is a folder by either underlining its name using the
HTML <U> ... <I"U> tag or simply by placing a small icon (using
<IMG ... > tag) in front of it.
Hints
The following tips are also recommended:
• Try not to parse the folder twice. You should be able to open the $path
after you know that it is a real directory and retrieve all the needed
information in one pass.
• The order in which files and folders are read will most likely be the order
of creation, so do not assume that folders will always be before files, and
do not assume that everything will be sorted alphabetically.
• When sorting data you might want to have two separate arrays holding
names (one for directories, one for files) and sort them individually.
Another option could be to have a two-dimensional array, where
$arr[$i][O] is the name and $arr[$i][l] is the type. In that case you
could use usort, using a method that would compare two entries by
checking their types first, and then their names if their types are the
same.
• Remember to do a ICHDIR before opening the folder!!
Overview
If there is a tool that has made the Internet as useful as it is, it would undoubt-
edly be searchers. Trying to imagine an Internet without Google, Yahoo,
AltaVista, and other searchers should bring shivers down your spine. Imaging
having to find the lyrics to a song you are looking for by yourself, or find an
CASE STUDY: AN INDEXER/SEARCHER-STEP 1 99
answer to an aching questions without a tool to do the dirty work for you.
Now, since we are learning about Web programming, it is our chance to get
behind the wheel and figure out how searchers work, by writing our own.
The Indexer-Step 1
The secret to a great search engine is having great indexing. The process of
indexing is the usually long and hard task of gathering as much information
on the pages we want to be able to search for and organize our findings. There
are tons of different types of indexers, from the basic "keywords" indexers
that simply store the information found under the META tag "keywords" to
complex full-text indexers with thesaurus that use n-dimensional space vectors
to store the information of the files (beyond the scope of this book). We are
going to settle for something in the middle: a basic full-text indexing with
META tag information gathering.
A full-text indexersimply goes through the content of the file being indexed,
counting how many times each word appears. This information is then stored
in a database, and when a user looks for a word like "Spain," you show all
the pages that contained that word, starting with the one that had the word
appearing more times. There are several important things to realize when
indexing, though.
First, there are useless words that do not need to be indexed. A "useless"
word is a word that no one with common sense would try to look for, usually
a word that gives no information on the topic of the page. For example, words
like "a," "the," "for," "yes," and "no" could be considered "useless." In order
to skip useless words, there are several techniques, such as having an array
with all the entries to ignore (the safest way). Another faster way is not to
index a word that has less than a predetermined amount of letters, with the
danger of excluding short but important words. For example, a page on data-
bases might contain the abbreviation DB (for database) appearing many
times, and should not be ignored. For our indexer, we will simply ignore words
of one letter, indexing only words of two or more letters.
Another typical problem when indexing is HTML tags. Obviously when
searching for files, you want to be able to know how many times a word
appeared, but you seldom care about how many times a specific HTML tag
was used. Our function strip_tags will be extremely useful! Always remove
the HTML tags before proceeding to indexing the words in the file.
Other important thing to keep in mind are letter casing and special char-
acters. Realize that as far as PHP goes, words like "Alicante" (my hometown)
and "alicante" are different, but as far as your indexer goes, they should be
the same. To solve this, the standard consensus is to lowercase the entire file
being indexed. As for special characters, you do not want to record in your
database how many times you had a new line, and exclamation point or a
double quote. So you need to find a way to get rid of special characters.
Regular expressions are usually the best way, but since we will not see them
100 USING FILES, FOLDERS, AND STRINGS IN PHP
until almost the end of this book, you may use strtok or str_replace. This way,
you can avoid problems like having "hello!" and "hello" appear as two sepa-
rate words because of the exclamation point. Getting rid of special characters
is one of the most important steps in an indexer.
Finally, as stated above, our indexer will also have to gather the META
tag information. This step has basically no interference with the full-text
indexing, since get_meta._tags accepts the URL of the file directly, whereas
the full-text indexing will require you to open the file and store its contents
in a string so that it can be modified.
In a nutshell, our basic indexer will need to
Hints:
Even though objects in PHP have existed since version 3, their use has been
improved with PHP5, thanks to the use of the script motor Zend 2. In case
you have never programmed in any object-oriented programming language
(e.g., C++ or Java), I will explain the raw basics so you can follow the explana-
tions. If you wish to look into C++, I recommend that you read The Design
and Evolution of c++ by Bjarne Stroustrup (see alphabetical list in Bibliog-
raphy at the end of this book).
A class is a complex data type that can hold both data and methods. Classes
are generally categories of objects; the data it contains are called data members
or attributes and allow definition of a particular instance of that class. The
methods inside a class are generally actions that an instance of a class can do,
or simply methods that allow access to or modification of data members. For
example, you could have a class called Car that would hold data members
such as manufacturer, model, and year, and methods like checkMileage() or
changeColor().
Web Application Design and Implementation: Apache 2, PHP5, MySQL, IavcScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
101
102 PHP5 AND OBJECT-OPIIENTED PROGRAMMING
CLASSES IN PHP
To create a class in PHP" you start by writing class followed by the name of
the class. Once you are in the class, you can create functions as you would
outside a class. The difference will be that definitions of functions defined
inside a class will be methods of the class. In order to call a method of a class
you have two choices: either creating an object of your class and invoking the
method (see below) or calling the method statically through the class name:
<?php
class SimpleClass
(
II member decl.aration
public $var = 'a default value';
II method decl.exec ion
public function clisplayVar() {
echo $this->var;
}
public static Eunctiion statMethod () {
echo "This is a static method";
}
}
$a = new SimpleClass(); Ilwe create an object of the
//class SimpleClass
$a->displayVar(); I/we invoke the method displayVar
I/through the object $a
SimpleClass::statMethod(); II We call the static method
//statMethod
?>
<?php
class BaseClass {
function __construct () {
print "In BaseClass constructor\n";
}
function inheritedFunction() {
echo "howdy! " ;
}
}
class SubClass extends BaseClass {
function __construct () {
parent: : __construct ();
print "In SubClass const.ructzorvn",
}
}
$obj = new BaseClass()i
$ obj2 = new SubClass () i
$obj2->inheritedFunction()i
?>
104 PHP5 AND OBJECT-ORIENTED PROGRAMMING
VISIBILITY
When you are defining a data member or data function, it is possible to set
up its visibility. The visibility can be public, private, or protected. Public vis-
ibility means that the data can be accessed anywhere, private means that the
data are accessible only within the class itself, and protected means that only
the class itself, its parents, and its descendants can access it. Data members
should always have their visibility written before the data themselves, but it
can be omitted in the case of methods that take public as default visibility.
<?php
1**
* Define MyClass
*1
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHe.Ilo ()
{
echo $this->pulJlic;
echo $this->protected;
echo $this->pr~[vate;
}
}
THE STATIC KEYWORD 105
The scope resolution operator is basically two colons (::). The scope operator
was named "Paamayim Nekudotayim" by the Zend team of developers while
they were writing Zend engine 0.5 (used in PHP3). It actually means "double
colon" in Hebrew. It is a token that allows access to the static, constant, and
overridden members and methods of a class, without the need to create an
object of that class.
<?php
class MyClass {
const CONST_VALUE = 'A constant value';
}
echo MyClass:: CONST_VALUE;
class OtherClass extends MyClass
(
public static $my_static = 'static var';
When you have a method that you would like to access without the need to
create an object, you must make the method static (and public). Doing so,
you will be allowed to access the method by simply writing the name of the
class followed by the scope operator and the method name. Note that since a
static method can be called without an instance of the class, you may not use
the $ this object reference inside a static method. A static data member is
basically a member that can be accessed without the need of an object. Fur-
thermore, you cannot access a static data member from an object, so it is
106 PHP5 AND OBJECT-OI':lIENTED PROGRAMMING
accessible only by writing the name of the class, followed by the scope opera-
tor and the variable name.
CLASS CONSTANTS
You may define constant values inside classes. Constants are similar to vari-
ables, but they cannot be modified. Constants do not use the dollar sign in
their names, and, like static members, they cannot be accessed from an
instance of the class. You may not store a variable, class member, result of a
calculation, or function call inside a constant. Constants are useful when there
is an important data item that you will use throughout your code and that
does not change. You might wonder, why use a constant instead of simply
writing its value? Imagine that you are programming a page that will handle
an array, making sure that you never get more than a specific number of ele-
ments, say, 100. You could write the number 100 each time you want to check
the maximum size of the array for comparison, but if in the future you wish
to upgrade your program to accept 1000 numbers, you will have to go through
your code and change every single "100" to "1000." A problem might arise if
you also use "100" for other functions, such as calculating a percentage. By
creating a constant instead of writing the actual data throughout the code,
you allow yourself the flexibility needed to upgrade your code by simply
changing one value: the one written in the constant declaration.
CLASS ABSTRACTION
OBJECT INTERFACES
Object interfaces allow you to create code that specifies which methods a class
must implement, without having to define how these methods are handled.
The difference between an abstract class and an interface is that abstract
classes are used for inheritance and can contain both data and methods.
Interfaces can only have methods, which must be implemented by a class.
Interfaces are defined using the interface keyword, in the same way as a stan-
dard class, but without any of the methods having their contents defined. All
methods declared in an interface must be public.
COPYING AND CLONING OBJECTS 107
<?php
II Declare the interface 'i'Iemplate'
interface iTemplate
(
public function setVariable($name, $var);
public function getHtml($template);
j
II Implement the interface
II This will work
class Template implements iTemplate
(
private $vars = array();
public function setVariable($name, $var)
(
$this->vars[$name] = $var;
j
public function getHtml($template)
(
foreach($this->vars as $name => $value) (
$template = str_replace('{' . $name. 'j', $value, $template);
}
return $template;
}
}
There is a very important thing to realize about objects, and that is that an
object variable is technically a reference to the actual object. Therefore,
copying an object by doing object] = object2; simply causes both variables to
refer to the same object. In many cases we will not want just a copy of the
reference to the object but a copy of the entire contents of the object. To do
so, we can use the clone operator, for example, object] = clone (object2);
The clone operator will create a new object and copy all the attributes from
object2 to objectl. This may sound like using the equal sign (=), but the main
difference is that using clone will call any existing __ clone() method of the
class (see below).
108 PHP5 AND OBJECT-ORIENTED PROGRAMMING
COMPARING OBJECTS
There are two ways to compare two objects to determine whether they are
the same. You may use the double or triple equal sign. The double equal (==)
EXCEPTIONS 109
will check whether all attributes are the same, and whether the two objects
are instances of the same class. For example, an object and its clone would
be equal, if compared with ==.
The triple equal (===) will check whether the object variables are identi-
cal, meaning that they will refer to the same instance of the same class.
TYPE HINTING
EXCEPTIONS
<?PHP
function divide ($a, $b)
{
try {
i f ($b == 0)
throw new Exception(''Attempted to divide by zero!");
return $a / s»,
110 PHP5 AND OBJECT-ORIENTED PROGRAMMING
<?php
class Exception
{
protected $message 'Unknown exception';
II exception
Ilmessage
protected $code = 0; II user defined exception code
protected $file; II source filename of exception
protected $line; II source line of exception
function __construct ($message = null, $code = 0);
FINAL WORDS
OVERVIEW
By now you know all the nuts and bolts of the core set of tools that PHP pro-
vides with one major exception: interactivity between pages. The goal of this
chapter is to overcome this need and show you the many ways of transmitting
information between PHP scripts.
FORMS
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
111
112 CREATING SOME INTERACTIVITY
the script that will run when the form is submitted, and method specifies how
the information will be sent to the script. The two possible methods are GET
and POST. For now, simply write POST, and later on I will explain why that
option is better. You may also add a target the same way we did with regular
links if you want to send the form information to a different window or
frame.
Once you have created the working area for your form, it is time to create
input areas. Input areas are created with the <INPUT /» tag, which can be
set up with the following attributes:
Here are the different types of input that exist, and what they are used
for:
with the same name, followed by brackets. For example, if your group of
checkboxes needs to be called "Checks," you should write "Checks[]"
for each checkbox under their name property. Grouping checkboxes
together allows you to gather all the information of the checkboxes as a
single array, rather than having one variable per checkbox.
• Radio-used to create radio buttons. A radio button is a circle on a
screen that can be checked or unchecked. The difference between radio
buttons and checkboxes is that radio buttons should always be grouped,
as only one option can be selected at any time. You may not click on a
selected radio button to unselect it. Instead, you need to click on a dif-
ferent radio button of the same group. This makes the need of grouping
radio buttons crucial. If you leave all the radio buttons independent, you
will be able to select them all, but unselect none. To group radio buttons,
simply give them the same name. In the case of radio buttons there is no
need to put the angular brackets that we used with checkboxes, because
checkboxes are processed as an array (hence the brackets). You may have
several options selected, but since radio buttons can have only one option
selected within the same group, there is no need for arrays.
• Hidden-probably one of the most useful underused input types. They
are useful when transfering information from forms to forms without
showing that information to the user. It simply saves the data stored in
the "value" attribute and sends it through the form without asking for
any input to the user. Note that since this is HTML, the "hidden" field
can still be seen and read through the page's code, so avoid entering
decrypted passwords in "hidden" inputs.
• Reset-this will create a button that will reset the form to its initial state,
erasing any data that might have been written thus far and replacing them
with the default values.
• Submit-probably the most important button (at least until we study
forms manipulation with JavaScript). This will create a button that will
send all the input values to the script specified on the "action" field of
your FORM tag.
• Button-a simple button like reset and submit but that has no action. It
is useful in JavaScript.
There are actually two more types of input, but they do not use the INPUT
tag. These are text areas that are multiline textboxes, and select areas that
are menus.
To use a text area, use the <TEXTAREA> ... </TEXTAREA> with the
attributes name (same meaning as the name of an INPUT tag), rows (number
of rows the text area will show on screen), and cols (number of columns of
character the text area will show on screen). Note that any character between
the end of the opening tag and the beginning of the closing tag will be
considered the default value, so if you want a totally empty text area of
114 CREATING SOME INTERACTIVITY
<?PHP
i f (!isset($_POS~r["text"]))
echo "You stup.id cheater!! You didn't use my form!!!";
else
{
echo strip_tags ($_POST["text"]). "<BR>";
$arr = $_POST["check"];
foreach ($arr as $elem)
echo $elem." ";
echo "<BR>";
echo strip_tags ($_POST["textarea"]) ."<BR>";
/ I you can access the variables by knowing their name
foreach ($_POS'T as $k=>$e)
echo "Input .$k received with value $e<BR>";
/ I or simply uee foreach
} ?>
The most basic way to transfer data between PHP scripts is by using the GET
method. Because of the way GET data are retrieved in PHP, you do not actu-
ally need to receive these data from a form. Simply use the syntax presented
before to write variables after the URL of the script to which you wish to
send data. So, for example, if I had $varl and $var2 that I wanted to transmit
to a new PHP script, I could have a link created by PHP as follows:
Instead of having a link, we can use the header function, which, as we will
see at the end of this chapter, can automatically redirect the user to the des-
tination page if the proper conditions are met.
Cookies
A better way to share information among different scripts is the use of
cookies. But you may ask "What are cookies?" Well, let me quote the Cam-
bridge Advanced Learner's Dictionary to answer you:
The function timer) returns the current UNIX timestamp, which is the
number of seconds passed since the Unix Epoch (January 1, 1970 00:00:00
GMT). You may also retrieve the number of milliseconds elapsed since
that date with microtime();. Since we want our cookie to exist for one minute,
we simply need to set the expiration date to the creation time plus 60
seconds.
TRANSFERRING DATA BETWEEN PHP SCRIPTS 119
If later on you wish to access that same cookie, you would read the contents
using $_COOKIE["myCookie"], which would hold the string that the cookie
contained.
As cookies hold only text data, you might think that they are quite limited,
but with our imagination, we can overcome this limitation. Simply use implode
to create a string with multiple variables concatenated one after the other
before writing in the cookie, and use explode when reading that same info to
split it back the way it was. Here is an example:
You probably noticed the line that uses ${"cookie_$k"} as a variable name.
This is a technique that allows you to create several variables with automati-
cally generated names. As you know, the dollar sign $ means that you are
writing a variable and the curly braces { }tell PHP that you wish to generate
the name of the variable through a combination of strings and other variables.
For example, in our code we have $k holding the key of elements in an array,
getting the values 0, 1, 2, and 3. This will result in variables called $cookie_O,
$cookie_l, $cookie_2, and $cookie_3.
120 CREATING SOME INTERACTIVITY
Sessions
One of the most efficient and easy ways of transferring information between
pages without the user's knowledge is to use sessions. Sessions can be imag-
ined as a "magic cloud" that contains all the variables that we need it to hold.
The session can be accessed from any PHP script, which can either add
more data or read data from the session. The session information is saved in
the server computer either on text files (that's the standard behavior) or on
the Web server's process memory. This makes session much more flexible
than cookies to store data, as the only limit is the size of the server's hard
drive.
When a user accesses a page that uses sessions, a unique session identifier
is randomly generated and encrypted. This session id is usually stored in the
client's computer as a cookie, although you do not need to manually create
the cookie, as the session initialization will do this for you. If the browser
that the client is using does not accept cookies from your domain, you can
still transmit the session identifier between pages with the GET or POST
method.
The default session configuration should be good enough for the scope of
this book, but here are some settings you can change in your php.ini file (each
element will be written as a setting=default_value, followed by an explanation
of what it does):
To use session in PHI), you first need to start the session with session_
start(). If no session was yet created for the user, a session will be created. If
a session already existed for this user, starting the session will allow you to
access the existing session. Remember that you must use session_start() if
you are planning on using sessions, or the session data will not be accessible.
If you want to destroy a session, meaning that you don't want the user to be
able to access the session data any longer, use session_destroy(). This func-
tion is usually one of the last steps of a logout procedure. When a session is
started, you may check the name and id of the session with the functions
session_name() and session_id(), respectively.
TRANSFERRING DATA BETWEEN PHP SCRIPTS 121
In order to use the session, use the array $_SESSION. For example, if you
want to create a session variable "username" with the value "Bewchy," you
simply need to write
$_SESSION["username"] = "Bewchy";
The $_SESSION array works pretty much the same way as$_GET,
$_POST, $_SERVER or $_COOKIE. Therefore it is possible to check
whether a sessionvariable existsbysimplyusing isset ($_ SE SSION[rvamame "J).
You may also delete a session variable using unset. Also, since it is an array,
you can use foreach to retrieve all the data in a session.
The following example is a series of three files. The first one will create a
session and store data in it; the second file will check whether the session
exists and show any data stored in it; the third file will be a logout procedure
that will destroy the session. To navigate between the pages, we will add some
basic HTML links:
<HTML><HEAD><TITLE>File 2</TITLE></HEAD>
<BODY>
Checking the session. . . <BR>
<?PHP
session_start () i
echo session_name ()." ".session_id (). "<BR>"i
i f t! isset ($_SESSION["username"]))
{
echo "You cheater!!! You tried to sneak in with no
session!<BR>"i
?>
<A HREF="sessions.php">Go create your session!</A>
<?PHP
}
122 CREATING SOME IN1ERACTIVITY
else
{
echo "Session data is:<BR>";
foreach ($_SESSION as $k=>$e)
echo $k." ".$~e."<BR>";
?>
<A HREF="sessions3.php">Next pagel<IA>
<?PHPII the pxevi.oue HTML line is inside the { } of the
I leIse, so will
I I only run i f the session existed
}
?>
<IBODY>
</HTML>
Sometimes you will process information in pages that are not really displaying
any data, but that are just PHP scripts that, for example, make sure that the
login information is corr1ect before setting up the page for the logged-in user.
In those cases we want to be able to redirect the user from the current script
ASSIGNMENTS 123
to a different one. This can be done with JavaScript, as we will see in Chapter
14, or you can simply use the PHP header function.
The function header allows you to send a raw HTTP header. For this
reason you may use this function only if the headers haven't been sent yet,
which means that if a single character has been printed, you will not be able
to user header, and will get a message saying "headers already sent." I will
not get into the details of raw HTTP headers; the only thing you need to know
for our situation here is how to utilize this function for redirections. Simply
write headert'tlocation: http://blablabla.com'');replacing "blablabla.com"
with whatever URL you wish to go to. You can, of course, take advantage of
this to send GET information by writing, for example, headeri'Tocation:
myscript.php?varl=1&var2=2&var3=3");.
Usually when I write a login procedure I start on a standard form. When
the user enters the user and password information and clicks on the submit
button, I receive all the information in a PHP script that starts by checking
the database. If the user and password do not match any record, I use header
to redirect the user to the login page; if the login information is correct, I set
up my session with all the info I might need from the database (email address,
name, surname, preferences, etc.) and use header to move to the "logged-in"
main page.
A header can also be used as a basic security tool. If there is a page that
should be accessed only if the user is logged in and you are using sessions,
you can check one of the session variables right at the beginning of your page
and header the user back to the login page if that user is not properly logged
in. You can also add information on the redirection with the GET method.
This is what the top of your "secure" pages could look like this:
<?PHP
i f (Jisset($_SESSION["user"}))
header("location: http://mydomain/index.php?reason=nologin'');
?>
<HTML>
<HEAD>
[ .·. }
ASSIGNMENTS
File Explorer-Step 2
Now that we know how to transmit information between PHP scripts, take
the file explorer from Chapter 7 and make it more useful by rendering the
folders clickable. The idea is to turn each folder into a link. When you click
on a folder name, you should call the same explorer script sending the new
124 CREATING SOME INTERACTIVITY
path to parse through the GET method. Note that there are always two
"directories" that appear in every path: "." and" ... " The folder ":" repre-
sents the current working directory, and is not of much use to us, so there is
no need to print it. The ".." folder represents the parent directory. Now if you
click on "..", you can process the folder the lazy way, meaning that the path
will appear with a "1..1" at the end. The problem with this technique is that
after several clicks your path might look something like "/usr/home/sgabarrol
folder/..I../sgabarro/folder/," which shows poor design as it actually refers to
the folder "/usr/home/sgabarro/folder/." Instead, when you encounter a"..,"
you should figure out the path of the parent directory by using functions like
strrpos and substr.
In this new step of our indexer, we are going to make our indexer more user-
friendly. The last thing a user who wants to index files should need to do is have
to open the script source file and modify a Spath variable. Instead, use a form.
The other improvement is to make our indexer more flexible, to expedite
the indexing of local files. Our indexer will have to accept either regular .htm
or .html files (in which case the indexer will do the same as in step 1) or actual
folder names. First, if you wish to make your indexer work perfectly well,
make sure that you can handle paths written with forward slashes (I), back-
slashes (\), and in case of folders, paths that either do or do. not contain a
"closing" slash at the end.
If the input received is a folder, find all the .htm and .html inside that folder
and use your indexer on those files. However, if the provided path is a folder,
and that folder contains other directories, you should enter those new direc-
tories and do the same work. Basically you need to traverse the entire direc-
tory structure rooted at the path provided as a parameter, and index every
single .htm and .html file. Don't forget to ignore nonhtml files like .php, .mp3,
and .zip, as they would probably crash your indexer. To make mattersclearer,
here is an example of directory structure:
FolderPassedThroughForm
file.htm
aFolder
oreFolders
more:file.html
script.php
work.pdf
otherfile.html
music.mp3
anotherFolder
more.htm
CASE STUDY: INDEXER/SEARCHER-STEP 2 125
One of the drawbacks of embedding HTML and PHP is that it makes code
look quite messy. It is also pretty easy to get confused on where HTML ends
and PHP starts. If we manage to avoid writing HTML inside PHP code, and
if we avoid writing PHP code around regular HTML tags, we can have code
that is much easier to read. The problem that this will cause is that it will be
more complicated to implement the scripts.
To face this challenge, we will use something called templates, and more
particularly, a class called FastTemplate. There are many different template
options, but I have been using FastTemplate for many years and it is fast and
efficient to use. The idea behind templates will be to have pieces of HTML
in a small file that will be used as puzzle pieces to finish our Webpages. Each
little HTML piece will be called a template file, and might contain areas that
we will manage to change from our PHP code. Just imagine those dynamic
sections as if they were "template variables."
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavcScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
127
128 MAKING CLEANER CODE AND OUTPUT
Note that this version is a debugged version of the standard one you can
find online. When I tested the class with the newer versions of PHP, I realized
that there were many notices due to outdated writing. I corrected those errors,
and the class now works flawlessly with PHP 5.1.2. Extract the zip file in your
desired folder (e.g., a folder ./include/ inside your document root), open up
the file, and find the variable $WIN32 (it should be around the first few lines
of code). If you are running your server on a Windows system, make sure that
the variable is set to TRIUE. If you are running a UNIX/Linux server, make
sure that it's equal to FP~LSE.
The most important thing to remember is to place all template files in the
same folder. Try to think in terms of reusability and do not be afraid to break
your standard page into many different template files. Think that the more
template files with "template variables," the more flexibility you will have
when building your final output.
Then you will need to create an object of the class FastTemplate and use some
of its methods to set up your final page.
To create a FastTemplate object, decide on its name (e.g., $tpl) and use the
FastTemplate constructor, by providing the path to the template files. For
example, if your template files are in .Itemplates!, you would write
The basic methods needed to use templates are define, assign, parse, and
FastPrint. Define and FastPrint will be used only once per page, whereas
assign and parse might occur a variable amount of times, depending on the
number of "template variables" used.
The define method takes an associative array in which the elements are
the name of the template files to use and their keys are abbreviations of those
pages. Choose easy-to-remember names for the keys, as you will refer to the
templates through those abbreviations. For example, if we needed to use the
files mainpage.html and tablerow3.html, you would write
$ tpl->define (array("main"=>"mainpage.html",
"row"=>"tablerow3.html"));
The next step is to use assign to set up all the template variables of the
template file that we wish to parse. Simply call the assign method with the
name of the variable you want to set up and the value you want to assign to
it. This information will be saved inside the template object and used when
you parse a file (see next paragraph). For example, to set up my template
variable {CELL_l}, I would write
$tpl->assign("CELL_l", $value);
Note that using assign on a template variable that was already assigned will
overwrite the previous value of that template variable.
Once all the variables of a template file have been set, you may parse
the file. Parsing the file means going through the template file, replacing
all template variables found with their appropriate values, and storing the
final parsed string (file with proper values) in a new template variable to be
used later. There are two ways of doing this. The first, and usual way, is to
call the parse method with the name of a variable that will hold the result
of the parsing, and the abbreviation of the file to parse. For example, if
we wanted to parse tablerow3.html after we assigned all three cells, you
would do
$tpl->parse("ROWS", "row");
130 MAKING CLEANER CODE AND OUTPUT
If it is the first time you call this parse, a new template variable ROWS would
be set up containing the parsing of row. Each additional call of the same line
will add the result of a new parsing right after the previous content of ROWS.
Between each call of parse, be sure to reassign the template variables of the
parsed file so that each row has the appropriate information, rather than all
rows holding the same information. Again, remember that parsing will techni-
cally do an assign of a te:mplate variable.
Once you have parsed, from the inside out, all the template files needed
to create your final output (including the main page), use the method Fast-
Print by doing
$ tpl->FastPrint ();
This method will find the result of the last parsing done and will output the
entire string contained ill that variable.
Here is an example that would create our dropdown menu with the list of
states assuming that we have the variable $states containing the associative
array explained in Chapter 6. To keep it simple, we will assume that the
variable is in an include :file states.php. I will provide, in order, the code for
mainbody.html (main pa.ge), option.html (containing a single option line),
and templates.php that will do all the work:
<HTML>
<HEAD><TITLE>Templa~te example</TITLE>
</HEAD>
<BODY>
<FORM action=nopelge.php method=post>
<SELECT nemee eel.ect:»
{OPTIONS}
</SELECT>
CLEANING UP YOUR OUTPUT 131
<option value="{VALUE}">{NAME}
<?PHP
include (". /include/states.php") i
include I.". /include/class . FastTemplate.php" ) i
$ tpl = new Fas tTempla te ( ". /TEMPLATES" ) i
$ tpl-> define (array("page" => "mainbody.html",
"option" => "optz iott.htzmlrl l :
foreach ($states as $k=>$e)
{
$ tpl->assign ("VALUE", $k) i
$tpl->assign ("NAME", $e) i
$tpl->parse("OPTIONS",".option")i //We use append
}
$tpl->parse ("OPTIONS", "page") i
/* This parse parses the nnal page once all options
have been set up. Since the result of this parse will
be printed out and not really used inside any nle, and
since the OPTIONS variable will not be needed any
further after the parsing of mainbody.html, I store the
result in the last variable I used (in this case
OPTIONS). I do this to avoid creating an extra entry,
and waste memory space. Technically on the last parsing
the name provided on iiret: parameter is not important.
Realize that we do not need to append either, as we
need only one main body. */
$tpl->FastPrint () i
?>
To this point, we have been using boring black and white pages, with all set-
tings to default. It is time to bring up some life in our pages, by making a
cleaner output.
The first method, which is considered deprecated and poor programming
practice, is to use the HTML <FONT> ... </FONT> tag. This tag allows you to
specify the font, size, color, and many other cosmetic settings for a block of text.
Since this tag should not be used, I will not waste time discussing it further.
The way you should set up the aspect of your pages should always
be through Style Sheets. These style sheets can be defined inside the header
132 MAKING CLEANER CODE AND OUTPUT
of your HTML files, or even better, saved inside style sheet files called
Cascading Style Sheets (or .css files). We will, of course, concentrate on the
latter.
<'--
A:link
{font-size: 12pt;
font-weight: bold;
text-decora tion ;' none i
color: 000000; }
A:visited
{font-size: 12pt;
font-weight: bol.d:
text-decora tion : none; color: 000000; }
CLEANING UP YOUR OUTPUT 133
A:hover
{font-size: 12pt;
font-weight: bold;
text-decoration: none; color: red;}
A:active
{font-size: 12pt;
font-weight: bold;
text-decoration: underline; color: OOOOOO;}
BODY
{font-size: 12pt;
font-family: Verdana, Arial, Helvetica, sans-serif }
table
{font-size: 12pt;
font-family: Verdana, Arial, Helvetica, sans-serif }
Hl
{color: darkblue;
font-size: 18pt;
margin-top: lpt;
margin-bottom: 2pt;
margin-left: lpt;
margin-right: 1pt;
font-family: Verdana, Arial, Helvetica, sans-serif;
}
H2
{color: black;
font-size: 16pt;
font-family: Arial Narrow, Arial, Helvetica, sans-
serif }
H3, H4
{font-size: 14pt;
font-weight: bold;
font-family: Verdana, Arial, Helvetica, sans-serif }
H5
{font-size: 12pt;
font-weight: bold;
font-family: Verdana, Arial, Helvetica, sans-serif }
.myclass {
font-size: 30pt;
letter-spacing: 10;
font-weight: bold;
font-variant: small-caps;
color: Yellow;
background-color: Red;
}
-->
134 MAKING CLEANER CC)DE AND OUTPUT
Some of the main features of my style sheet, and something that I usually
have in all my pages, is nonunderlined links. I personally dislike seeing a link
as a typical blue underlined text. Instead, my links simply have the same look
as regular text with the only difference that they are in boldface. To let the
user know that they are links, I use the hover state of the link and use flashy
colors like red; that way, when the user passes the mouse over the link, its
appearance will change, capturing the attention of the user. I do have under-
lined links, but only when the page referred to by the link is active. Note
that colors can be written in hexadecimal, providing a RGB color (red-
green-blue), or by simply writing the name of the color.
I also included a .myclass style to show how to create your own class. This
class in particular is a silly one that will show up text with the colors of the
Spanish flag (red and yellow). I also added humorous attributes such as font_
variant, letter_spacing, and background_color.
How to use the style sheet? The first thing to do is to link to the style sheet
in your HTML file. Simply insert the following line of HTML inside the
<HEAD> ... <IHEAD> section:
Of course, don't forget to change the href parameter to hold the path to your
style sheet file.
The next step is to use the actual styles that are in the CSS file. If you defined
a style for a standard tag, simply use the tag, and the style will be applied auto-
matically (as long as you are already linked to the style sheet). If you created
your own class and you wish to apply it to any tag, simply add the attribute class
to the tag you wish to change, followed by the name of the class (without the
period sign). So, for example, if I want a link to use myclass, I would use
If you want to apply your class to a section of your HTML without separating
that portion as a link, paragraph, or other "visible" container, you can use the
<DIV>...</DIV> tag, which will cause your portion of HTML code to be
"divided" from the rest of the HTML. This will be very useful when we do some
DHTML, as it will allow us to move entire sections around our pages. Of
course, you still need to use the class attribute, as in this example:
Useful Tools
If you are a lucky user of Macromedia's HomeSite software, you have the
opportunity to use a program called TopStyle, which ships with HomeSite.
ASSIGNMENT 135
TopStyle is an excellent tool for creating style sheets; it shows all possible
attributes on a menu at the right side of the program. It also provides a
preview window where you can see what your styles look like while you write
them. Please note that I sincerely like the product in question and am not
trying to advertise anything.
ASSIGNMENT
Now that you know how to use templates and styles, try applying all that you
have learned in this chapter on the file browser that you have been working
on in the previous chapters. This means no <FONT> tags, no background
properties in the <BODY> tag, and, of course, not a single HTML tag in your
PHP and no PHP inside files containing HTML.
11
Using Databases
OVERVIEW
DATABASE BASICS
As the word indicates, a database is basically a base of data, or, if you prefer,
a set of data with a structure that is similar to real-life situations. It allows
you to store any type of information you need, and it can be accessed by any
user with the proper rights.
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
137
138 USING DATABASES
Entity 1 Entity2
Id entity1 Id entity2
-1 N
Attribute 1 AttributeA
Attribute2 AttributeS
through relationships usually named as actions. Each entity type has a set of
attributes that help define different entities at the same time. For example,
name and age would be attributes of the entity type "workers."
When an entity can be identified individually with a single attribute or a
small set of attributes, these are considered index keys. If there is more than
one index key, one of them has to be set as a primary index key. If an entity
cannot be identified through its own attributes, and if it needs a relation with
another entity, it is called a weak entity. Any relationship to a weak entity is
called a weak relationship.
Relationships between entities have a complexity of either 1:1, l:n
(or n:1), or n:m. If you have a 1:1 relationship between an Entity] and
Entity2, this means that for each entity of the type Entity] there will be a
single entity of type Entity2 related to it and vice versa. A relationship of
l:n would mean that an entity of type Entity] can have n associated
entities of type Entity2, but a single element of Entity2 can be associated
with only a single item of Entityl. The relationship n:l is the reverse of l:n.
Finally, a relationship n:m means that an item of Entity] can be related to
many items of Entity2, and an item of Entity2 can be related to many items
of Entity].
An example of an entity relationship model is shown in Figure 11.1.
of the questions will be used in the table question_in_test along with an id_
test referring to the test it was asked in; number, to know in which order it
was asked for the test; value, indicating the number of points it is worth for
that test; and id_qt, which will be a primary automatically incremented dull
key used to refer to a specific question of a specific test. Finally, we need to
hold the grades of each student, which might as well be a grade per question.
We will have a table grade_per_question with id_gq (dull key), id_student
(the student that took the test), id_qt (reference to a question of a test from
the question_in_test table), and grade. Technically we could create an addi-
tional table with the grades for a full test per student, but since it is possible
to calculate it from data held in other tables, it is not necessary. The final list
of tables (and attributes) we have is as follows:
previous database and you insert an entry in the table question_in_test, you
should make sure that it refers to the right test with a proper id_test and to
the right question, with the proper id_question. You should systematically
check all data inserting when the entity you insert depends on data already
in the database.
To avoid problems, and to enhance security, I personally always use a dull
key called id_ followed by the name of the table. I always make that key
primary, and autoincremented (automatically incremented), so I do not need
to worry about specifying its value when inserting elements. Fields like email
should always be set as UNIQUE to avoid problems. The reason why
dull keys help protect your database is that all the information you need
to search for a specific entry in any table is simply a number, so if you send
that information through pages, anyone trying to hack on your site will see
only a number, without knowing what it means. For example, if you are
sending a reference to a student through the GET method in PHP, it is
much safer to see something like script.php?id=4 instead of script.
php?student=sgabarro.
USING MySQL
t name I title
i surname ! date
LL~<~.~~.w~~~~
tI
id_test
number
I
~
value I
FK2 ¥eSlion I
I
PK ~
Well, no need to know since we do not plan to go that far into MySQL for
you to need those features.
MySQL also includes extra features that were not in the standard SQL,
such as proper string comparisons, regular expressions, arithmetic on dates,
and many other things that again we will not see as we can do all of it with
PHP and JavaScript.
MySQL Syntax
Before we go into MySQL syntax, I would like to explain some standard
notations that I will use to explain the different commands. Whenever you
see a group of text between square brackets in a syntax line (e.g.,
[UNSIGNED]), this means that the element between brackets is optional and
you may use it or not use it depending on what you are trying to achieve.
A group of elements separated by the pipe sign "I" and surrounded by curly
braces ( ) implies a choice. Simply read the pipe as "or"; for example, if you
see "{integer I real I string}," this means that the whole block between the
opening and closing brace must be replaced by either the word integer, real,
or string, and that exactly one of those blocks must be used, no more, no less.
You may also see the pipe sign separating options inside a set of square brack-
ets, meaning a choice between the different options, so that only one option
maximum can be used. For example, if you see "[FIRST I AFTER position],"
this means that you can write FIRST, AFTER position or simply nothing at
all.
142 USING DATABASES
Data Types
When using MySQL you can use a string by simply surrounding a piece of
text with either double or single quotes. Inside a string you may use any of
the following special characters: \0 for an ASCII 0 (NULL) character, \' for
a single-quote character, \" for a double-quote character, \b for a backspace
character, \n for a new-line character, \r for a carriage return character, \t for
a tab(ulation) character, \Ok for the percentage character, and \_ for the under-
score character. You may also use floating-point numbers (e.g., -12.345),
integers (e.g., 678), as well as hexadecimal numbers (e.g., 3FB7A). Finally you
may use the NULL value to represent the lack of data.
Any name you use to define the structure of your database has a maximum
size. For instance, database names, table names, and column (or attribute)
names cannot exceed 64 characters. If you wish to use a longer name, you
may use aliases, which allow a maximum of 255 characters.
Assuming that you have a database called classgrades with the previous
example of database structure (see Figure 11.2), you could access a student
name by doing name if you are inside the table student, student. name if you
are in the classgrades database, but not accessing the table student, or simply
classgrades.student.name if you want to access that field from a different
database on the same server. For Web projects you will most likely have only
one database with many tables, which will simplify your work.
You may create variables in MySQL using the SET instruction to declare
the variable, and := to assign an expression to it. You may declare a variable
as integer, real, or string, and might declare many variables with a single SET
instruction. All MySQL variables start with the character @. Here is an
example:
I have never used MySQL variables, as I can accomplish the same func-
tionality with PHP in a" much faster and easier way.
explanation of what they mean. You might also see lUi, meaning that the
type can be set as UNSIGNED or [Z], meaning that the type can be set as
ZEROFILL (indicating that the number will be filled with zeros to the left
of the number until all the allowed digits are used). If you see [(M)] or
[(M,D)], this means that you may specify the maximum number of digits
[e.g., (5)] or the number of digits for the integer and fractional part of a
number in the case of nonintegers [e.g., (5,2) would allow five digits before
the decimal point and two after]:
MySQL Operators
In MySQL you will find the traditional arithmetic operators such as +, -, *,
and I. You can also use the pipe sign I for a binary OR operation, the ampersand
USING MySQL 145
& for binary AND operations, a double "less than" sign « to do a logical shift
to the left, and a double "greater than" sign » to do a logical shift to the
right. If you wish to know how many bits there are in a number n, simply use
BIT_COUNT(n).
Logical operators can be NOT, or simply an exclamation point !, for the
logical NOT (!TRUE == FALSE). You can use OR, or the double pipe II; AND
or the double ampersand &&.
MySQL Instructions
The following chapters explain the basics of the most important functions as
far as Web programming goes. The explanations of some functions will be
brief, as their actions will usually be done through PhpMyAdmin, rather than
typing the actual SQL query. For the same reasons, I will not go in full depth
of all the abilities of each one of the instructions; instead, I will limit discus-
sion of each instruction to its most common use(s).
To create a database, use CREATE DATABASE name. To delete the data-
base (along with all its contents), use DROP DATABASE [IF EXISTS} name.
The option IF EXISTS is just an extra flag that you can put to avoid errors in
case the name provided does not correspond to an actual database on the
server. To force the use of a database, write USE DATABASE name.
The code used to create a table in a database is CREATE [TEMPO-
RARY} TABLE [IF NOT EXISTS} table_name [(create_definitionl, create_
definition2, ... J). When creating a table it is possible to set up its contents
through the create definitions. Each one of them can be either one of
these:
• attribute_name type [NOT NULL I NULL][DEFAULT default_value]
fAUTO_INCREMENT]fPRIMARY KEY]freference_definition]-
used to define a new field in the table
• PRIMARY KEY (key_column_name, ... )-used to specify the fields
that will act as primary key
• UNIQUE (column_name, ... )-used to specify which fields are unique
For example, to create the student table of the earlier example, assuming that
the email address has to be unique, you would write
CREATE TABLE 'student' (
tid_student' SMALLINT UNSIGNED NOT NULL
AUTO_INCREMENT,
'name' VARCHAR(lO) NOT NULL,
'surname' VARCHAR(20) NOT NULL,
'email' VARCHAR(30) NOT NULL,
PRIMARY KEY ('id_student'),
UNIQUE ('email')
TYPE = MYISAM COMMENT = 'Super table';
146 USING DATABASES
The TYPE field at the end is not really necessary, but you should include it
to force the type of table you are creating. The COMMENT field is just an
example of how you would insert a comment for a created table.
If you need to alter an already existing table, you may do it by writing
ALTER [IGNOREJ TABLE table_name alter_specs [, alter_specs2, ...J.
The alter_specs can be any of the following:
All these instructions allow you to prepare the database for its use, and even
though you will most likely do the same job through PhpMyAdmin without
needing to understand the syntax, it is very useful to understand the queries
so that you may create a.n installation script that would set up the database
with the proper structure needed for your scripts to work.
The two operations we will do most often through PHP scripts are inser-
tions and searches in the database. In order to insert an element in a table,
there are three possible syntaxes:
For example, to insert a new user in our previous example, we could write
Another final way to update a series of entries is to use UPDATE with the
following syntax:
The way UPDATE works is simple; you provide a condition as part of the
wherejcondition that will match all the elements you want to update, and it
will change the specified columns for all the matches found. If you provide
an ORDER BY statement, the updates will be done in the order of the sorted
elements. Finally, the row_count is used as a limit and represents the maximum
number of rows to update. If you do not provide a limit, all matches will be
updated. Also, if you do not provide a WHERE statement, all entries in
the table will be matched and updated (based on the limit). For example,
148 USING DATABASES
assuming that we had an extra field age in my table students, we could decide
to look at every student alphabetically ordered by their last names (surnames),
and make the 10 first 20-year-old students in the list one year older by writing
Assuming that you already inserted data in your database, the operation
you will use more often is called SELECT. A SELECT is used to look for
information in one or more tables that matches specific criteria. The following
displayed routine in bold, is the full syntax accepted for a SELECT; it may
seem overwhelming, but as you will see in a later example, it is quite simple
once you skip some of the optional sections. I will explain the important
options that you might need and skip the rest, which is usually needed only
in advanced database ma.nipulation.
SELECT
[ALL I DISTINCT I DISTINCTROW]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESlJLT] [SQL_BIG_RESULT]
[SQL_BUFFER_RESU.LT]
[SQL_CACHE I SQL NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expression, ...
[FROM table_references
[WHERE condition]
[GROUP BY {col jname I expression I position}
[ASC I DESC], ... [WITH ROLLUP]J
[HAVING wherecondition]
[ORDER BY {col jname I expr I position}
[ASC I DESC], . · .]
[LIMIT [[offset,] row__count I row_count OFFSET offset}]
[PROCEDURE procedure name (argument list)]
[INTO OUFILE 'file name' export_options I INTO DUMPFILE 'file
name']
[FOR UPDATE I LO(~K IN SHARE MODE]]
USING MySQL 149
OVERVIEW
CREATING A DATABASE
The first thing you need to do when creating a database is to have its layout
prepared. It is important to know exactly what the database will hold, what
tables it will include, and what fields will define the tables. The next step is
to create the actual database.
In PhpMyAdmin main page, you will see a text area such as that shown in
Figure 12.1
In that field you should enter the name of the database you wish to create
and then click on "create." If the database already exists, select it from the
dropdown menu on the left frame. Once you have selected the database you
wish to access (or created a new one), you will see its name appear on the
left frame, along with the name of every table it contains.
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
151
152 USING PhpMyAdmin
CREATING TABLES
Once you select a database and you see the list of tables on the left, you may
click on a table name on the left menu to check the structure of that table.
Clicking the icon to the left of the table name will show its contents. If there
are no tables, you will see a screen like that shown in Figure 12.2.
The top menu gives access to Structure (to,view the structure of the data-
base), SQL (where you can type in your own SQL queries, or import a SQL
file), Export (which allows you to export the structure and data of the data-
base), Query (used to create queries through dropdown menus, when you are
uncertain of SQL syntax), Operations (to copy the database, rename it,
change its character set, etc.), and Drop, which deletes the database along
with all the data it contains.
To create a new table, enter its name in the Name field, and the amount of
attributes it will contain in the Fields attribute. You can always modify this
later, but it is preferable to know the details beforehand. Each time you
are in the database structure page, you have the possibility of creating a
new table.
Once you select the number of fields for the new table, you will see a screen
similar to the screenshot in Figure 12.3, with as many lines as number you
provided for the Fields value. For each line you must insert (in this order) the
name of the field (how you will refer to it in your scripts), its type (through
the dropdown menu), its length (see chapter 11), its collation (just leave as
default), any attributes (like UNSIGNED or UNSIGNED_ZEROFILL),
CREATING TABLES 153
whether you wish to allow the field to accept being null or not, a default value
(if any), whether it is an AUTO_INCREMENT field (ideal for ids) and,
through the radio buttons, whether the field is a primary key, index key, or a
unique or regular field. The last checkbox allows creation of a full-text, which
is a way to group several fields together as one massive text field.
After you fill in all the details of your new table, you can insert some com-
ments, and then submit it so that the table is created. You should see its name
on the left frame menu, as in Figure 12.4.
Click on the name of the table you wish to view in the left menu. This will
take you to the table menu (see Figure 12.5), where you can view the table
structure, Browse the data in the table, send a SQL query, Insert new entries,
Export the table and its contents, do several Operations on the table, Empty
its contents, or Drop the entire table along with its data.
and table structure in the database server. To do so, follow the directions in
the next chapter to write a PHP script that will run all the needed SQL
queries, such as "CREATE DB" or "CREATE TABLE."
Another way of setting up your database on another computer is to use the
export/import feature. Select the database you wish to export from the drop-
down menu on the left and select the Export tab (see Figure 12.6).
Once you are there, select the format to export to (SQL is usually the best
choice, as it will create a simple text file with all the SQL queries that will
create and populate your database). You may choose whether you wish to
export the database structure, the data, or both, as well as setting up other
options on the way the import will work. Finally, select the "Save as file"
option so that you can save the export. If you don't select "Save as file," the
actual export file will simply show up in your browser, rather than allowing
you to download it. You may also choose to compress the file as a zip or gzip
(I personally use gzip when exporting), to make the export file smaller. Note
that exporting a database exports its contents, but not the database name, so
you will need to create the database before you can import the structure.
Once the file is created and saved in your computer, transfer it to the server
in which you wish to install your database. We will assume that you have
installed phpMyAdmin in the destination computer. Create a database with
the same name as your source database, and select the SQL option (third icon
from left in the toolbar shown in Figure 12.7).
From there, click on the Browse button, select the export file you saved,
and click on the lower Go button. The other Go button is used when you
156 USING PhpMyAdmin
manually write your SQL queries. Make sure that the file is smaller than the
size specified (2048 KB in my screenshot), or the operation might time out.
If your file is larger, you can break it down into several small files and import
them one by one.
ASSIGNMENT-FINAL PROJECT
When I teach this course, this is the point where I ask students to specify their
idea for a final project. The reason I wait until I finish the basics of databases
is because all database-driven Websites should be designed around the data-
base, so it is important to have enough knowledge of database structures to
come up with a proper database layout for the project. The main rules I
enforce are:
1. First they need to come up with the database layout, which needs to be
reviewed by the professor and approved.
2. About a week or two before the final presentation day, the students should
go through what I call a "CEO" (chief executive officer) presentation.
158 USING PhpMyAdmin
In the last chapter of the book you will find a long step-by-step develop-
ment cycle that I use on my Websites and that I recommend. It also includes
some examples of security breaches that can happen in a PHP project.
13
Creating Database-
Driven Websites
with PHPIMySQL
OVERVIEW
Once you have designed and created the database you want to use, it is pos-
sible to access its contents with PHP. The easiest way to proceed is to create
the database and its tables with a tool like phpMyAdmin, and then use PHP
scripts to manipulate the data in the database.
When you wish to check the contents of your database with PHP, the first
thing to do is to connect to it, using the method mysql_connect. This function
requires three extremely important parameters: the host (or server where the
DB is installed and running), the user (should be the same one you set up for
phpMyAdmin), and the password for that user. Generally the host will always
be Iocalhost unless your Web server and database server are installed in two
separate machines.
Instead of directly using the mysqI_connect, I would recommend creating
an include file in which you will write wrapper functions for all the standard
methods. A wrapper function will run the standard one, making sure every-
thing works fine, or quit the script if there is a problem. The include file should
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
159
160 CREATING DATABASE-DRIVEN WEBSITES WITH PHPIMySQL
also include the user, password, and server information so that the informa-
tion is centralized in a single file. The file should be kept in a safe folder!!!
Here is what the beginning of the include file should look like:
<?PHP
$MySQL_Hos t= IIloca.lhos t";
$MySQL_User="user H;
$MySQL_Pass = Hpass ";
function connect ()
{
global $MySQL_Host, $MySQL_User, $MySQL_Pass;
i f (1 $linkid=mysql_connect("$MySQL_Host l l, "$MYSQL_
User", "$MySQL_Pass"))
{
echo "Impossil)le to connect to ", $MySQL_Host,
"<BR>";
exit;
}
return $linkid;
}
?>
Note that our new function connect will return the same value that mysql_
connect returns. This $linkid will be the resource needed for us to send any
query to our database server. To actually connect using our function, we need
to first include our include file and then simply call our function connect, like
this:
<?PHP
include ("/usr/home/sgabarro/includes/myinclude. inc .php II) ;
$lkid = connect () /
?>
So far our code simply connects to the database and does nothing else. To
add extra functionality, there are many methods, as we shall see; but once
you know MySOL syntax, you only need the method to send a query and the
methods to read the results from those queries. Whenever you wish to access
a database, create a string holding a SQL query, and use either mysql_db_
query or mysql_query. The first one takes a database name and the query;
the second takes the SOL, query and the link id provided by connect. If you
use the second method, you must first select the database to use on your
MySQL server using mysql_select_db. I personally prefer the second option,
but I also have a wrapper method for this task:
PROCESSING THE RESULTS OF A QUERY 161
Note the use of mysql_error(), which prints the last error returned by the
MySQL server. Usually my scripts will use only a single database, so I write
send_sql with just two parameters, and I hard-code the database to access on
the my_select_db line. This function should be in the same file as connect.
Here is an example of how you would retrieve all the info for a user "Bewchy"
assuming that our DB name is "Examples" and our table name is "Users":
<?PHP
include ("include.inc.php");
$link = connect () ;
$db = "Examples";
$sql = "SELECT * FROM Users WHERE username='Bewchy''';
i f ($res = send_sql ($sql, $link, $db))
echo "The query worked, now let us learn how to
use the returned var";
?>
As you probably noticed, when sending a SQL query, the send_sql function
returns a variable that we called $res. This variable is a resource handler, and
contains all the information related to the query sent. For example, if you
tried to find a series of users, $res would hold the details of all the matches
found. These data can be read with several methods; my favorite is the func-
tion mysqIJetch_row. This function receives a resource handler as an input
and returns the next row. Each row is an entity that was returned after the
query. What is nice about this method is that it will return an array with all
the details in the order they were requested. Also, this function returns
FALSE if there are no more rows, so you can easily use it in a loop to process
all the results. You can also use the function mysql_num_Tows($res), which
will return the number of rows the resource handler contained. If, for example,
your query was "SELECT user, password FROM Users WHERE age=26,"
162 CREATING DATABASE-DRIVEN WEBSITES WITH PHPIMySQL
doing sendjsql should return a resource handler with all the usernames and
passwords of all the 26-year-old users. Assuming that we called $res =send_
sql($sql, $ link, $db), here is some code you could use to check all the
entries:
<?PHP
// we assume that the query was already done
if (mysql_num_rows($res) == 0)
echo "No match found!";
else
while ($row = Inysql_fetch_row($res))
echo "User: "'.$row[O]."<BR>Password: ".$row[l]."<BR>";
?>
When you have a page that requires users to log in using a username and
password, I usually have a login.php script that checks user validity. If it is, I
gather all the needed info for that user and store it in a session, right before
I redirect the page to the~ "logged-in" area, which, of course, will ensure that
the session is properly set up. Something I like to do is store all passwords
with MD5 encryption, to increase security. This means that to verify user-
name/password information, I need to encrypt the password received through
the login page also with MD5, and see if it matches the one stored in the
database. A basic way to check for proper username/password is to attempt
to find all users with same username and encrypted password. If you set up
your database properly, :fields like "username" will be unique, so you know
that you can receive only a single match or none at all. Here is a basic login.
php procedure, assuming that our "users" database contains (in order) the
fields id_user, username, pass, name, surname, and email:
<?PHP
include (r include.Lnc.pbp"),
session_start ();
$link = connect ();
$sql = "SELECT * FROM users WHERE user='''.$_
SESSION["user"].'" liND pass=MD5 ('''. $_SESSION["pass"]."')";
i f (! $res = send_sql ($sql, $link, "examples"))
{
echo "Database problem!!!
exit;
}
i f (mysql_num_rows ($res) == 0)
header( "Location: index.php");
OTHER USEFUL FUNCTIONS 163
<?PHP
/***********************************************************
** **
** Class database written by Steven A. Gabarro **
** **
*******************:~***************************************/
class database
GROUPING OUR METHODS IN A CLASS 165
{
private Slink;
private $res;
private $host "localhost"; II change to your own
Iidefault value
private $user "root"; II change to your own
Iidefault value
private $pass ''''; II change to your own default
Ilvalue
private $db;
II sets user, pass and host and connects
public function setup ($u, $p, $h, $db)
{
$this->user = $u;
$this->pass $p;
$this->host = $h;
$this->db = $db;
if (isset ($this->link))
$this->disconnect ();
$this->connect o.
}
II Changes the database in which all queries will
Ilbe performed
public function pick_db ($db)
{
$this->db = $db;
}
II destructor disconnects
public function __ destruct ()
{
$this->disconnect ();
}
{
if t l isset ($this->link))
{
try {
i f (! $this-->link=mysql_connect ($this->host,
$this->user, $this->pass))
throw new Exception ("Cannot Connect to
". $this->host);
} catch (Exception $e)
{
echo $e->g'etMessage ();
exit;
}
}
else
(
$ this->disco.nnect () ;
$this->connect ();
}
}
$num=mysql_num_nelds ($this->res);
echo "<table border=l>";
echo "<tr>";
for ($i=O;$i<$num;$i++) {
echo "<th>";
echo mysql_tield_name ($this->res, $i);
echo "<Ith>";
}
echo "<Itr>";
while ($row = mysql_fetch_row($this->res)) {
echo "<tr>";
foreach ($row as $elem) {
echo "<td>$elem<ltd>";
}
echo "<Itr>";
}
echo "<Itable>";
}
else
echo "There is nothing to print!<BR>";
}
II returns an array with the next row
public function next_row()
{
i f (isset ($this->res))
return mysql_fetch_row($this->res);
echo "You need to make a query first!!!";
return false;
}
II returns the last AUTO_INCREMENT data created
public function insert_id ()
{
if (isset ($this->link))
{
$id = mysql_insert_id ($this->link);
i f ($id 0) ==
echo "You did not insert an element that cause
an auto-increment ID to be created! <BR>";
return $id;
}
echo "You are not connected to the database!";
return false;
}
II Creates a new DB and selects i t
public function new_db ($name)
168 CREATING DATABASE-DRIVEN WEBSITES WITH PHPIMySQL
{
i t (lisset($this->link))
$this->conntect ();
$query = "CREATE DATABASE IF NOT EXISTS". $name;
try {
i f (mysql_query($query, $this->link))
throw new Exception ("Cannot create database
". $name);
$this->db = $name;
} catch (Bxceptz ioti $e)
(
echo $e->g€,tMessage (). "<BR>";
echo mysql_error();
exit;
}
}
}
?>
Here is a small function that illustrates how the previous class would be used:
<?PHP
include ( ", /datal:.>aseClass .php");
INDEXERISEARCHER--STEPS 3 AND 4
The next phase for our indexer/searcher is to start using our database to hold
the results from our indexing as well as reading the information in the data-
base to perform a search.
INDEXER/SEARCHER-STEPS 3 AND 4 169
Step 3 will consist in taking our previous version (step 2) and modifying
the code so that instead of outputting the results on a page, everything will
be stored in a database. It is entirely up to you to decide on your database
structure, but remember that you want to be able to search all that informa-
tion effectively. The important data we will need to hold are
• Filename
• File URL
• Metatags for each file
• Full-text count of the words of each file
extra features such as wildcard searching. For example, you could allow a user
who is looking for any words containing the string "abc" to write things like
*abc*. This is easily done by replacing the asterisks by a percentage sign, as
the % is the "wildcard" character in MySQL. To look for a nonfull match, do
not use attribute = value; instead use the LIKE operator. For example, if you
wanted to search for any user whose name includes the letter "z," your SQL
query would be
Another fun feature is to add a "highlight" link that would load a prepro-
cessed version of the page. The preprocessing would basically be a PHP script
that would open the page, replace the word you were looking for by the same
word with a "highlight style" (such as all-capital letters, yellow background
with red lettering) throughout the original text and then display the updated
version of the page.
14
JavaScript-A Client-Side
Scripting Language
INTRODUCTION
Web Application Design and Implementation: Apache 2, PHP5, MySQL, Javo Script, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
171
172 JavaScript-A CLIENT-SIDE SCRIPTING LANGUAGE
the <?PHP and ?> for PHP. Once you are in between opening and closing
SCRIPT tags, make sure you respect all JavaScript syntax rules!
As we saw on Chapter 2, JavaScript is an object-based language, so most
of our time will be spent using preexisting objects to do our job. One thing
to remember is that the language is case-sensitive, so make sure to use the
proper mix of upper- and lowercasing when calling an object's method or
attribute!
When we studied PHI·, we saw that it works by executing the code on the
server, and sending the final result of the script directly to the client's browser.
JavaScript runs client-side, having all its code downloaded along with the
HTML. For this reason, all the JavaScript is run line by line as the page is
being read and displayed.. For example, if you have some JavaScript between
two HTML paragraphs, the first paragraph will be displayed, then the
JavaScript will run, and the second paragraph will appear on the page only
after the entire script is finished running. Here is an example of a page con-
taining a script that will change the background color of the page. You do not
need to understand how it works; we are just trying to see the basic structure
of a page containing Jave'Script and how the script is executed step by step:
<HTML>
<HEAD><TITLE>JavaIScript example 1 </TITLE></HEAD>
<BODY>
First block!<BR>
<SCRIPT LANGUAGE="JavaScript">
alert ("First block");
</SCRIPT>
Second block!<BR>
<SCRIPT LANGUAG.E="JavaScript">
alert ("Second block");
</SCRIPT>
And now we cbenqe the background color to flashy
yellow<BR>
<SCRIPT LANGUAG.g="JavaScript">
alert ("Change Background!");
dooumetit..bqcolor = "Yellow";
</SCRIPT>
</BODY>
</HTML>
The function alert used creates an alert window, which blocks the script
until the user clicks on "()K." As you can see, when an alert is waiting to be
clicked on, it blocks the interpretation of the HTML file and nothing else is
displayed until we unblock the script.
Comments work in JavaScript the same way as they did in PHP, meaning
that you can use either the double slashes or the /* ... */.
JavaScript SYNTAX 173
JavaScript SYNTAX
Remember to put a semicolon at the end of each line of code. As you can
see, alert is very flexible, and can show any data of primitive types.
Two very useful methods will allow you to find a number inside of a string.
You can use parselnt(string) , which returns the first integer found in the string
or NaN if no string was found; or parseFloat(string), which returns the first
floating-point number found in the string or NaN if there were no numbers.
NaN stands for "not a number" and means that a string contains no numerical
data. These two functions work only if the number you are looking for is right
at the beginning of the string (white spaces may precede the number). If you
try to parse a string of the type "string 123," these methods will return NaN.
You can actually test a string to see if it is a number using isNaN (). Realize
that this method tells you if the parameter provided is not a number, so it will
return false if the parameter was a number: it would mean that it is not NaN;
therefore it is a number (you must love double negations ©). For example,
isNaN(234) will return false and isNaN("Hello") would return true.
Here is an example: of a miles-to-kilometers converter script. Since
JavaScript is client-side, we can directly ask the user for input data without
the need of forms. To do so we will use the prompt method, which takes two
parameters: the string to display (what you want the user to input), and the
default value. The function prompt will pop up an entry box for the user to
enter some information, and will return whatever the user wrote. Also, instead
of doing an alert as in the previous examples, we will use document.writet),
which is basically the JavaScript equivalent of PHP's echo. This way we will
show the results on the Webpage rather than on an alert window.
<HTML>
<HEAD> <TITLE> Corivexs ione ! <ITITLE> <IHEAD>
<BODY>
I don't understand miles, so give me kilometers
please!<BR>
<SCRIPT LANGUA(';E="JavaScript">
var inputVar = prompt("Enter the number of miles
to convert", 60);
i f (isNaN(paz'seFloat (inputVar)))
alert ("You di.dnr : enter a number!! This is
unacceptable! ") ;
else
(
var result =
parseFloat (inputVar) * 1.609344,-
II conversion data provided by Google
document.write (parseFloat (inputVar) + " miles is
the same as " + re su It: + " km");
}
<ISCRIPT>
<BR>Thanks for using the converter!
<IBODY>
<IHTML>
JavaScript SYNTAX 175
Arrays
If you wish to use arrays, you need to specify that the variable you will use
is an array. This is done by creating an object of the class Array by writing
The Array constructor can actually accept the series of elements to insert in
the array. Since JavaScript's variables can be of any type, you can hold a mix
of different data types in the same array. To access or modify data in an array,
you can use the angle brackets with the index of the element to modify. Note
that as in PHP, the elements inserted in an array do not need to have succes-
sive indices, and it is possible to have an array with only three elements
located at indices 2, 23, and 325, for example. Here is a basic array manipula-
tion example:
var myArray;
myArray = new Array("Uno", 2, "3.0");
myArray[3] = "Four",·
As with PHP, array indices start at 0 by default. You can create multidi-
mensional arrays by simply making an array element become a new Array();
thus each new level of arrays would use a new set of angled brackets with an
index. Here is how you would create the same "friends" array that we saw in
the PHP version of multidimensional arrays. Remember, our goal was to have
a set of names and list of relatives for each entry in our friends array. So
technically we need a three-dimensional array. The first dimension tells us
which friend we are dealing with, the second dimension allows us to read
either the friend's name or the array of relatives, and the third dimension
holds the names of the relatives:
Decisions
As in PHP, JavaScript can check different conditions and branch to different
sections of the code depending on the value found. To do so we can use the
common comparison operators "==" for equals, "<" for less than, ">" for
greater than, "<=" for less than or equal to, ">=" for greater than or equal
to, and "!=" for different. You can combine different boolean expressions
with "&&" for AND, "II" for OR, and "!" for NOT.
When using the if statement in JavaScript, there is one basic difference,
residing in the elseif. In PHP elseif has to be written as a single word, but in
JavaScript it is two separate words. The general syntax would therefore be:
if (condition)
{}
else if (anotherCondition)
{ }
else
{ }
You may also use the switch . . . case the exact same way as in PHP (don't
forget to use break). Here is an example of using both switch and if state-
ments. We will prompt the user for a number; if the user inputs something
that is NaN, we will say there's a problem; if it is a number, we will say "hello"
if it is 0 or 1, "goodbye" if it is 2, and "hooah!" otherwise:
var input = prompt ("Enter a number", 0) ;
if (isNaN(input))
document.write("1:ITot a number!");
else
{
switch (input)
{
case 0:
case 1:
document. write ("Hello");
break;
case 2:
document. write ("Goodbye");
break;
default:
document. write ("Hooah!");
}
}
Loops
In JavaScript, you may use the exact same basic loops used in PHP (except
for the foreach loop). Just as a reminder, here are three quick loop examples.
JavaScript SYNTAX 177
Remember that if you are creating a new variable in the first section of a for
loop, you will still need to write the keyword var:
In case you feel deprived for not having the great foreach to process all the
elements in an array, feel that way no more, since JavaScript has the equiva-
lent for . . . in. The basic syntax is for (index in array) and allows you to get
all the valid indices in an array, skipping the indices of empty cells. For
example, you could print all the contents of an array doing
var index;
for (index in myArray)
{
document. write (myArray[index]);
}
Finally, you can use break and continue as we did in PHP. The first will
quit a loop, and the latter will force the next iteration of a loop.
Using Functions
To create a function, simply write function functionName(parameterl,
parameter2, ...). As in PHP, the type of parameters or return value can be
anything, so it does not need to be defined. For example, if we wanted to
create a function to convert miles into kilometers, we would write the follow-
ing code:
function milesToKm(miles)
{
i f (isNaN(miles))
alert ("Error in function milesToKm: Parameter
provided is NaN!!");
else
return (miles * 1.609344);
}
To use the function later on, you would simply write, for example, var
myKm =milesToKm(60);.
178 JavaScript-A CLIENT-SIDE SCRIPTING LANGUAGE
USING OBJECTS
starting at the index provided (0). The second parameter is optional, but
very useful if trying to find a series of matches.
• lastIndexOf(string, position)-same as indexOf but searches back-
ward. If the position is omitted, the search is done from the very end of
the string.
• substring(beginning, end)-returns the substring from the calling string
starting at position beginning and finishing before index end. It is very
important to realize that the last character returned will always be at
index end-l. For example, if myString holds "Hello," doing myString.
substring(l, 3) would return the string "el."
• substr(beginning, length)-similar to substring. Returns the substring
starting at beginning and having length characters. For example, "Hello".
substr(3, 2) would return "10."
• toLowerCase()-for example, myString.toLowerCase(). Turns myString
to all lowercase.
• toUpperCase()-for example, myString.toUpperCase(). Turns myString
to all uppercase.
One last and fun function of the Math class is random(). Unlike PHP,
random will always return a number between 0 included and 1 excluded. From
there it is up to you to figure out how to achieve the range of numbers you
want to have. Here is an interesting application. Imagine that you are writing
a script for role players, and you are trying to get a dice-rolling script that will
calculate a series of dice rolls. A very popular role playing rule set called the
"d20 system," used in games such as "Star Wars RPG" or "Dungeon &
Dragons," is based on rolling a die with 20 sides, numbered 1 to 20. Now, we
know that our random-number generator will return a value (let us call it x)
between 0 and 1. We have
o <=X < 1
180 JavaScript-A CLIENT-SIDE SCRIPTING LANGUAGE
o ~ 20x < 20
One problem is that, we may get 0 and yet we will never reach 20. Since our
smaller number will always need to be 1, we can add one:
1 ~ 20 x + 1 < 21
Now we have to realize that the number we will get will be a floating-point
number. In order to turn it into an integer, we will need to round it. If we
round up, our range will be 1-21, which is not good. If we use the regular
round, we might still get number 21 which is out of bounds. Instead, we can
use floor since the largest number we will get is 20.9999999999[...], which,
rounded down, is still 20. Our final formula gives us
1 ~ floor(20 x + 1) ~ 20
<HTML>
<HEAD><Title>d20 System dice roller v1<ITitle>
<IHEAD>
<BODY>
<SCRIPT LANGUAGE= "JavaScript">
var numberOfThrows,-
var diceRoll,-
do
(
numberOfThrows = parseInt(prompt("How many times
should I roll the dice? Enter a number please.", 1)),-
} while (isNaN(numberOfThrows)),-
II we bug the user until he enters an actual
lin umber.
document. write ("Let's roll!! <BR>"),-
for (var i = 0,· i < numberOfThrows; i++)
(
diceRoll = Math.floor(Math.random() * 20 + 1),-
document.write(diceRoll + "<BR>"),-
}
</SCRIPT>
I f you want to reroll, press F5 or click on the
browser's refresh button.
<IBODY>
<IHTML>
THE DATE OBJECTS 181
A quite useful class in JavaScript is the Date class, which allows you to store
any date. To create an object with the current date and time, simply write var
date = new Date();. You may also use three other constructors if you are
trying to create a date object for a date different from the current one.
The first alternative is to provide a number, particularly the number of
milliseconds elapsed since January 1, 1970 at 00:00:00 GMT. For example, if
you do var date = new Date (303178567890); you are creating a Date object
based on August 10, 1979 around (20:15 hours) (8:15 p.m.).
Obviously, creating a date like this is useful only if you want to create an
object using a saved UNIX timestamp that you might have received through
a PHP script. To create a Date object for an older date, write the date as a
string with Day Month Year, for example, var date = new Datet'Tt) August
1979");.
The final alternative if you want a specific time but do not know the number
of milliseconds elapsed is to use a Date constructor that accepts seven param-
eters in the following order: year, month, day, hour, minute, second, and mil-
lisecond. Note that in JavaScript, the list of months actually starts at index O.
This means that January is 0 and December is 11. Therefore, to create a date
based on August 10, 1979 at 5:30 hours (5:30 a.m.), 20 seconds and 14 milli-
seconds, you would write
182 JavaScript-A CLIENT-SIDE SCRIPTING LANGUAGE
One last thing to remember when writing times with this format is that all
times use the military 24-hour system, so if you wish to say that it is 3:00
p.m., you must write 15:00 hours. Basically, just add 12 to p.m. times to get
the military time.
Once a Date object has been created, it is possible to extract individual
items from it, or modify settings individually. Here are the available methods,
assuming that our object is called myDate:
that, but let me tell you a little (true) story. As the Spaniard I am, I love soccer,
and my favorite team happens to be a team from a major city in Spain that is
not the capital. I will not say the actual name of the team because I do not
wish to get into trouble with them. Any soccer fans probably guessed the team
I root for. Anyway, in order to please their fans, they had a page with live text
description of their games. To build up anticipation waiting for the next game,
they had a counter saying how long you had to wait for it. The script worked
by checking the current time and comparing it to the game time-except that
they programmed it in a client-side programming language, and did not
account for the time difference. So, there was I in the United States wanting
to know how my team was doing at the exact time the game was being played,
but the page said I had to wait 6 hours for the game to start, simply because
there is a 6-hour difference between that major coastal Spanish city and U.S.
west coast. The moral of this story is "Remember which side you are gathering
the time from!" The client side will give you the user's time; the server side
will give you the server's time, which won't be affected by the time zone of
visitors.
Luckily, JavaScript has a way to solve this issue: using UTC times. UTC is
the Coordinated Universal Time (UTC sounded better than CUT) imple-
mented in 1964, and more commonly known as GMT (Greenwich Mean
Time). Basically it sets the center of all time zones in Greenwich (southeast
of London, U.K.). Eastern Standard Time (EST) is GMT - 5, Central Euro-
pean Time (CET) is GMT + 1, and so on. Once you have a Date object, you
can create a nice formatted string of the full date using the methods myDate.
toLocaleString() if you want to get the local time, or myDate.toUTCString(),
which will represent the same date as UTC. For example if the current time
is 13:15 (1:15 p.m.) in local time and I am in the U.S. east coast, the time
shown by toUTCString() will be 18:15 (6:15 p.m.), You may also retrieve the
time zone offset (number of minutes offset between UTC and local time)
using myDate.getTimezoneOffset().
You may also set or get individual sections of the date directly in UTC
format, by directly using any of the previous methods adding the word UTe
next to get or set. For example, myDate.getUTCDate() will get the UTC date,
and myDate.setUTCHours(n) will set the hours of the UTC time (which
obviously changes the local time accordingly).
15
Programming
the Browser
OVERVIEW
In this chapter, we will see how you can use JavaScript to access any section
of HTML files, as well as the actual browser window. To access all these fea-
tures, we need to use the Window object and its components.
The window object holds data members and methods that will allow you to
interact with the actual browser window. It is a global object, which means
that you do not need to actually write its name when calling its methods. We
already saw a method from the window object: the function alert. Technically
you should type window.alert{"Hello"} to use this method, but we can omit
the window. section. The window object also allows you to change things like
the message appearing on the status bar of your browser (the area that shows
the progress when downloading a page, and displays "Done" when the page
is loaded). You may do this by modifying the data member defaultStatus. For
example, writing window.defaulrStatus = "Hello and Welcome!"; will write
the welcome message in the status bar. Later on, when we start using timers,
we will see how to create scrolling text on the status bar. As with alert, you
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
185
186 PROGRAMMING THE BROWSER
do not need to write window. and may simply use defaultStatus = "This is
cool!".
The most interesting thing about the window object is the objects it con-
tains. These are the location, history, navigator, screen, and document objects.
Since all these objects are part of window, you may write, for example, either
window. document, or simply document.
<HTML>
<HEAD>
<TITLE>Navigator Example</TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE= "JavaScript">
var navData = navigator.appCodeName + "<BR>"i
navData += navigator.appName + "<BR>",·
navData += navigator.appVersion + "<BR>"i
navData += navigator.cookieEnabled + "<BR>"i
navData += navigator.mimeTypes + "<BR>"i
navData += navigator.platform + "<BR>"i
navData += navigator.plugins + "<BR>"i
navData += navigator.userAgent + "<BR>"i
document.write(navData)i
</SCRIPT>
</BODY>
</HTML>
this object: write, which adds text to a page. The document object also includes
arrays such as forms, images, and links, which allow you to access and set up
all the data inside forms, images, and links in the page.
The main problem of the document object is that browsers might have
different properties inside it, making it harder for the developer to write
multibrowser code. For example, Netscape Navigator contains an array tags
in the document object that Microsoft Internet Explorer does not support.
Let us concentrate on the basic arrays inside the document object.
First, we have the images array. Each time you use an image with the
<IMG> tag, there is a reference to that image that is added to the images
array. The very first image will be at document.images[O}, the second image
in document.images[l}, and so on. You may also add a name attribute to the
IMG tag, allowing you to refer to the image through the link's name. For
example an image defined as <1MG SRC = " bewchy.gif" NAME = "my Image">
can be accessed by doing document.images["mylmage"}. When you have a
reference to an image, you may change any attribute inside the tag by simply
writing a period (.) followed by the name of the attribute to change. The fol-
lowing example prompts the user for an image URL and replaces the image
on the page with the one provided in the prompt:
<HTML>
<HEAD>
<TITLE>Image Loader</TITLE>
</HEAD>
<BODY>
<IMG SRC="" NAME="imagel">
<SCRIPT LANGUAGE= "JavaScript">
varurl = prompt ("Enter an image URL",
..http://wroshyr.free.fr/images /bewchy. gif") ;
document.images ["imagel"}.src = ur1;
</SCRIPT>
</BODY>
</HTML>
The next array is the links array. It does the same as the image array, but
instead of storing all links created with the <IMG> tag, it stores references
to all links created with the <A> tag. As with the images, you may also
provide a name to the links so that they are easier to refer to. Since it is also
possible to change any of the links' tag attributes, you can drive a user crazy
by switching the destinations of your links by doing, for example, document.
links[O}.href = "differentpage.html".
Last but not least, we have the forms array, which holds references to all
the forms in the page. You might think that its usefulness is limited since
pages usually contain at most a single form, and you probably wouldn't want
to change its properties such as action or method, or your receiving script
THE WINDOW OBJECT 189
wouldn't work properly. Well, when you have access to a form element, you
can actually have access to every tag inside that form, which means that you
can edit the properties of every single input, and even add and remove options
in a select input!
Since there is usually only one form, the simplest thing to do is to give a
name to the form inside the FORM tag, allowing you to refer to it through
its name. For example, if you define a
<HTML>
<HEAD>
<TITLE>Changing Button</TITLE>
</HEAD>
<BODY>
<FORM NAME="myForm">
<INPUT TYPE="Button" VALUE="Name that WILL change"
NAME="myButton">
</FORM>
<SCRIPT LANGUAGE="JavaScript">
alert ("Let us change the button name!!!");
documen t . myForm. myBu t ton. val ue "I changed!!
Woohoo! ";
</SCRIPT>
</BODY>
</HTML>
If you do not know the names of the inputs (or are too lazy too scroll upl
down your code to read it), or if you wish to make a set of operations with
every single one of them, you can use a single form reference as an array. You
can therefore check the number of inputs in the form (including selects, and
textareas) by doing document.yourFormName.length. If you wish to access
the third input in the form, you can do document.yourFormName[2} (remem-
ber that arrays start their indices at 0).
Some form inputs have special behaviors, such as checkboxes and radio
buttons. Recall that you can group a set of checkboxes or a set of radio buttons
by giving the same name to each different option. Thus, the objects referring
to each one of those blocks can be used in JavaScript as an array, in which
190 PROGRAMMING THE BROWSER
the index identifies which option you are accessing. You can also determine
whether an option is checked by comparing the checked attribute to true. For
example, if you want to determine whether the third radio button on a series
of radio buttons called myRadio is checked, you can do
if(document.myForm.myRadio{2].checked == true)
doSomething();
You can also select and deselect options by accessing the one you wish to
modify and updating the value of the attribute checked to FALSE if you are
deselecting or TRUE if you are selecting it.
In the case of a SELECT input, you can access each option individually,
and even add or remove options. To access a specific option we use the options
array, which is automatically made part of each select object. The value of
each option can be value modified (with .value) or even the text next to the
option (with .text). To remove an option from a select menu, simply set the
option to be equal to null. To add a new option, we create an object of
the type Option, providing its constructor with the text to appear next to it,
and the value associated with that option. Note that all created options are
placed at the end of the menu, but since all options are in an options array,
you can use array operations to switch the elements around. You can also
check which option is selected by accessing the data member selectedlndex
of a select area anytime. For example, to change the text in a menu option
when you select it, you could do
One last useful thing that you can do in JavaScript is force the submission
of a form (even if there is no "submit" button!). Simply use the method
submit() from a form object. For example
Here is an example that allows you to add and remove options in a drop-
down menu:
<HTML>
<HEAD>
<SCRIPT LANGUAGE=JavaScript>
function butRemove_onclick()
{
var sel = document.forml.selectArea;
sel. options [sel. selectedIndex] = null;
}
USING EVENTS 191
function butAdd_onclick()
{
var sel = document.forml.selectArea;
var newoption = new Option ();
var pos = sel. options . length;
sel. options [pos] = newoption;
sel. options [pos] . text = document. forml. option. value;
sel. options [pos] .value = document. forml. optionValue.
value;
}
</SCRIPT>
</HEAD>
<BODY>
<FORM NAME=forml>
<SELECT NAME=selectArea SIZE=l>
<OPTION VALUE=O SELECTED>Example Option
</SELECT>
<BR>
Option:<INPUT TYPE="text" NAME="option"> .. .VALUE: <INPUT
TYPE="text" NAME="optionValue"><BR>
<INPUT TYPE="button" VALUE="Remove Selected Option"
NAME=butRemove onclick="butRemove_onclick()H>
<INPUT TYPE="button" VALUE="Add Option" NAME=butAdd
onclick=HbutAdd_onclick() ">
<BR>
</FORM>
</BODY>
</HTML>
USING EVENTS
Probably one of the most interesting things about JavaScript is the opportu-
nity to use events. An event is an action that is triggered by an action by the
client. For example, you can have an event happening when a page finishes
loading, when the client clicks on a button or link, or when the mouse cursor
is placed over certain areas. Events are assigned directly as a parameter of
the tag that will handle the event. For example, if you want to start an action
when the page finishes loading, the event is set in the BODY tag; if you want
a link to behave in a specific way,you would put the handler in the A tag; and
so on. Events start with on followed by the actual event to handle, these are
the main events:
Once you know which event you want to use, you must decide what action
to take. The general procedure is to create a function in JavaScript that will
be called by your event handler. Then simply write the name of the method
between double quotes next to the event, inside the tag that will handle the
event. For example, <BODY onload = "loadfunctiont)"» would call the
JavaScript function loadfunction() whenever the body of the page finishes
loading. Note that you may also call the methods with any parameter you wish
to use, so you can use the same function for different elements. I personally
like putting all my event functions inside the HEAD tags, which helps keep
the body as clean as possible, concentrating all functions outside it. This also
allows the functions to load before the body does, so that as soon as you need
to use them, the browser already knows about them.
Here is a fun little example. We will have a link with an onClick attribute
that will popup an alert message, a button input with an onMouseOver
USING EVENTS 193
that will change its face value, and an onClick that will change the page to
www.~oogle.com. Note that the event names are not case-sensitive, so you
may write onClick or onclick:
<HTML>
<HEAD>
<TITLE>Link that goes nowhere and onLoad</TITLE>
<SCRIPT LANGUAGE= "JavaScript">
function link_onclick()
{
alert ("You clicked on the link! Bu t I refuse to go
anywhere! ! " ) ;
return false;
}
function button_onmouseover()
{
document.forml.mybutton.value = "You placed the
cursor on me!!! I will take you to Google.";
}
function button_onclick()
{
location.href = ..http://www.google ..com ..;
}
</SCRIPT>
</HEAD>
<BODY>
Take me to <A HREF= ..http://www.google.com/ ..
onclick="return link_onclick()">Google</A>f
<FORM name="forml">
<input type="button" name="mybutton"
onmouseover="button_onmouseover()"
onclick="button_onclick() "
value= "Place the mouse over me!">
</form>
</BODY>
</HTML>
As you probably noticed, when using the event onClick I actually wrote
return in front of the function name, and my function returns a value. This is
a very useful feature that is used mostly on links and forms (through the
"submit" button, actually). Writing return basically means that your function
will return a value that should not be ignored, and that should be true or false.
Now, here comes the fun part! If the value is true, the element works normally,
as if the return were not there, but if your return value is false, the element
will not perform its standard task, leaving the user in the page. This is
194 PROGRAMMING THE BROWSER
extremely useful on forms as you can verify the contents of the form before
submitting it and let the users know about any errors so that they can correct
them before sending the data through the form. To do this, you would simply
have an onClick property on your "submit" button that would call the method
that will verify all data, returning false if a problem was encountered.
Two methods are very useful on forms containing text areas. Ideally, when
you are writing a form, you should always include some JavaScript to test the
form before sending any data to your PHP scripts. This allows a first layer of
data verification done on the client, which is much faster than transmitting
the data to a PHP script; have the PHP script verify the data; and redirect
the client to the first page if an error is found. Verifications done in JavaScript
allow you to avoid the burden of constant back and forth with the server. A
typical problem that can be found in forms· is bad type of data input in a
textbox; for example, you may be expecting an email address and the user
leaves the field empty, or inputs a text that is not an email address. In those
cases you want to inform the user of the error and to change the data. In those
cases you can call the methods focus() and select(), to place the user in the
field that needs changing. These methods should be called from a form
element object; an example would be document.myForm.mylnput.focus().
The method focus() will give the focus to the entry, and the method select()
allows you to select the entire text that was entered. When a field needs to be
changed, there is nothing better than to do a focus () of the problematic field,
followed by select(). This way the user simply needs to enter the new data,
automatically overwriting the previous text.
One last useful point is to realize that any of the objects accessed through
the document object can be stored in variables to ease up the typing. For
example, you could do
var myButton = document.myForml.button;
From then on, you would be able to access your button simply typing
myButton.
TIMERS
JavaScript has the ability to create two main types of timers: one-shot timers
and regular timers, called "intervals." One-shot timers allow you to decide
on a specific amount of milliseconds to wait before a function is called. Using
the function setTimeout, for example, you could do
var timerID = set'Iimeouttrmyliunctiont)", 5000);
This would create a timer that would wait 5 seconds before calling myFunc-
tion(). The returned ID is very important as it will be needed if you want to
stop the timer. Simply use clearTimeout(timerID) to stop the timeout.
TIME TO PRACTICEl 195
Regular timers are like timeouts, except that they restart the timer after each
timeout. The function used in that case is setlnterval("functionName() ",
time); for example
TIME TO PRACTICEI
Now that you know the basics of event programming, try writing a script
containing a button that keeps track of how many times it has been clicked.
Realize that variables defined outside a function are considered global. They
are accessible inside any function, so you can use that fact to your advantage.
Also remember that the text on a button is set by its attribute value.
Another fun thing to do is an event log. Create a form with different types
of inputs, such as radio buttons, regular buttons, text and password fields, and
text areas. Now make sure that you have at least one large text area that you
will use to keep track of all events that occur. Set up each input you created
with all the events you might want to test out, and have each event function
display the latest event at the end of the large text area. Remember that you
can access the contents of a text area through the value field of the tag, and
also that you can concatenate text using the plus (+) sign. Also, if you wish
to include a "clear" button, you can either simply include a "reset" button or
create a regular button with an event that will write an empty string ("") in
the value field of your text area by doing
document.myForm.textAreal.value = "";
Finally, use intervals or timeouts to create a banner changer. Have a set of
images with their URLs stored in an array, and set a timer that will change
the image every few seconds.
16
Windows and Frames
In the previous chapter we studied the window object and its contents,
concentrating on the document object. The goal of this chapter is see how
JavaScript can communicate between windows and frames, which effectively
means communicating between separate Webpages.
When you create a frame in a Webpage, each frame will have its own window
object; it is therefore possible to access any of the object window contains on
each separate frame. You can always check the name of any created frame
by accessing the name field of your frame, which is accessed by writing
window. name. To make matters even nicer for us developers, you may also
access the parent of any frame you have, as well as any child. Imagine that
you have created a frameset page containing two frames called frameLeft and
frameRight. When you are in either frame, you can access the page that
created those frames (the one with the frameset definition) by simply typing
window.parent. This will refer to the window object of the parent; from there
you can access anything defined in the parent as if you were in the parent's
page, including functions, variables, and form references. Whenever you wish
to access a function or variable defined in your parent's page, you can do so
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
197
198 WINDOWS AND FRAMES
by writing the name of the method or variable after window. parent. Here is
an example of a frameset page containing a method that will pop up an alert
box saying "Hello." The frameset will define two children, frameLeft and
frameRight, with one button each. Whenever the user clicks on either button,
we will call the method written in the parent frameset. To make things more
interesting, our method will accept the name of the calling frame as a param-
eter. Obviously our left and right frames do the same, except that they will
send a different value to the parent's method. We can use window. name in
the frame's code to directly send the right name.
Frameset definition:
<HTML>
<HEAD>
<TITLE>Basic Frames Example</TITLE>
<SCRIPT LANGUAGE= "JavaScript">
function sayHi (name)
{
alert ("Hello " + name);
}
</SCRIPT>
</HEAD>
<FRAMESET cols="50%, *">
<FRAME name="frameLeft" SRC="page.html">
<FRAME name="frameRight" SRC="page.html">
</FRAMESET>
</HTML>
Frame's page:
<HTML>
<HEAD>
</HEAD>
<BODY>
<INPUT type="button" value="Click me!"
onclick= "window.parent. sayHi (window. name) ">
</BODY>
</HTML>
frameset (usually called the "root" or the "top"), you can do window.top. The
most important step when you are attempting to work with more complex
frames is to really know your frame's hierarchy well.
Let us suppose that our page is cut into three frames, with frameTitle on
top, and frameMenu and frameBody underneath. Our menu frame will have
a dropdown menu with several city names; when a city is selected, we will
keep track of all selected cities on the frameBody inside a text area. The
frameTitle will have a page showing how many times you changed cities,
writing the message using a button, since we haven't seen how to modify
regular text yet.
Frameset definition:
<HTML>
<HEAD>
<TITLE>Frames Example</TITLE>
</HEAD>
<FRAMESET ROWS="200, *">
<FRAME name="frameTitle" SRC="title.html">
<FRAMESET cols="200, *">
<FRAME name="frameMenu" SRC="menu.html">
<FRAME name="frameBody" SRC="body.html">
</FRAMESET>
</FRAMESET>
</HTML>
frameTitle:
<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
var count = 0;
function change_button ()
{
count++;
documen t . myForm. myBu t ton. val ue count +
"selected cities so far";
}
</SCRIPT>
</HEAD>
<BODY>
<FORM name="myForm">
<INPUT type="Button" name="myButton" value="O
selected cities so far">
</FORM>
</BODY>
</HTML>
200 WINDOWS AND FRAMES
frameMenu
<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
function select_onchange ()
{
window. top. frameTitle. change_button ();
window.parent. frameBody. change_text ();
}
var test = 0;
</SCRIPT>
</HEAD>
<BODY>
<FORM name="myForm">
<SELECT name="mySelect"
onchange=Hselect_onchange()H>
<OPTION value=O>Alicante
<OPTION value=l>Hoboken
<OPTION value=2>New York City
<OPTION value=3>Barcelona
</SELECT>
</FORM>
</BODY>
</HTML>
frameBody:
<HTML>
<HEAD>
<SCRIPT LANGUAGE= "JavaScript H>
function change_text ()
{
var myTextArea = document.myForm.myText;
var menuSelect = window.parent.frameMenu.
document.myForm.mySelect;
myTextArea.value = myTextArea.value + menuSelect.
options [menuSelect. selectedIndex] . text + "\n"
}
</SCRIPT>
</HEAD>
<BODY>
<FORM name ="myForm">
<TEXTAREA name="myText" COLS=50
ROWS=25> </TEXTAREA>
</FORM>
</BODY>
</HTML>
WINDOWS AND JavaScript 201
Probably one of the most annoying things on the Internet are the popup
windows that 90% of pages abuse. Well, now it is your chance to create popup
windows! JavaScript allows the creation of windows and the communication
between different windows. Of course, we will not concentrate on how to
annoy users, but rather how to make intelligent popups that close themselves
when they are no longer needed.
We already saw a basic technique for creating popup windows. The idea
was to provide a name in the target field of a link, making sure that the name
had not been used yet (creating the new window with that name), or by using
_blank, which would always create a new window with no name. JavaScript
will allow us to go a step further and create new windows with the set of
properties we need.
The basic syntax of window creation is calling the open method from the
window object. The function takes three parameters: the page to open, the
title to give to the window, and a list of window features. For example, if you
wanted to create a popup that opens a file called popup.html, you could have
the following script. In order to make our popup intelligent, we are adding
an onUnload in the BODY. This event will be triggered when you leave the
page that opened the popup, and it will close the popup window that was
created. To close a window, simply use the method closer):
<HTML>
<HEAD>
<TITLE>Popup example</TITLE>
<SCRIPT LANGUAGE= "JavaScript">
var newWindow = window. open (''http://www.google.com'',
rmywi.ndowr, "width=500,height=500");
function closeIt ()
{
alert ( "Goodbye! " ) ;
newWindow. close () ;
return true;
}
</SCRIPT>
</HEAD>
<BODY onunload= "return closeIt () ">
Go <A HREF=''http://www.stevens.edu''>elsewhere</A>.
</BODY>
</HTML>
A good thing about the open method is that if you attempt to open a new
popup with the same name under the same variable, the previous popup is
202 WINDOWS AND FRAMES
Imagine that you want to create a window that will be opened right in the
middle of the screen, meaning that its center should be the same as the
screen's center. Then you want the window to be a third the size of the screen.
The first thing to do is to calculate the size. This is done using screen.height
and screen.width. We just need to divide the numbers there by 2 to get our
"half-size." The position is a bit harder. If you used half of the screen's height
and width, you would be basically choosing the center of the screen as a
coordinate, but using those values on our top and left field would make our
window's top left corner to be at the center of the screen, and we do not want
that. Since our window is meant to be centered and we already know its size,
we know that the number of pixels from (for example) the top of the window
and its center will be the window's height divided by 2. Since we know the
WINDOWS AND JavaScript 203
distance from the top of the screen to the center of the screen, we can simply
subtract that value by half the size of the window, letting us know the coor-
dinate to use for our top. Use the same principle to calculate the left coordi-
nate. The code would be something like this:
Var newWindow;
function open_cen tered_window (urlToOpen)
{ var height = screen.height / 3;
var width = screen. width / 3;
var top = (screen.height / 2)- (height / 2);
var left = (screen.width / 2) - (width / 2);
var features = "width=" + width + ", height=" +
height + ", top=" + top + ", left=" + left;
newWindow = window. open (urlToOpen, "myWindow",
features);
}
When we create a new window, since we get an object reference to the new
window, the popup creator can always access the contents of the popup. Now,
if you wish to do the opposite (accessing the creator window from the popup),
use the opener object of your window. If you have a window main that opens
a pop-up child that opens a window grandchild, you can access child from
grandchild doing window.opener and even main from grandchild doing
window.opener.opener. Each opener object will refer to the window object of
you opener; from there you may access any form element, image, and so on.
One last fun thing you can do with windows is moving and resizing them.
This can be done through the window object, so it can be done to any opener
window, popup, or the window itself. There are two ways to resize and move:
changing the coordinates/size through an offset, or giving the final value
the fields it should have. Moving is done with theWindow.moveTo(left, top)
or theWindo w.moveBy(leftoffset, topOffset). Resizing is done through
theWindow. resize'To (width, height) or theWindow. resizeBy (width Offset,
heightOffset). To show this, we are going to create two windows. The main
one will simply contain a button to open or close the second window. We
will actually use the same button to open and close the window. Our popup
window will contain two text fields and two buttons. The text fields will allow
us to enter a number of pixels for height and width, and will contain an
onChange event that will apply the changes whenever they are made. The
two buttons will be used to either center the window, or have it move to a
random location. If the user manually changes the size of the main window,
we will update the remote controller with the new size of the window. The
randomizing of the location and size of the main window will be done in
such a way that the resulting window will always be inside the limits of the
screen, and with a size small enough so that the bottom right corner will not
protrude out of the desktop.
204 WINDOWS AND FRAMES
Main window:
<HTML>
<HEAD>
<TITLE>Popup example</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var newWindow;
var status = 0;
function popupopenclose ()
{
if (status == 0)
{
openWindow () ;
document.forml.myButton.value "Close Window";
status = 1;
}
else
{
closeWindow () ;
document.form1.myButton.value "Open Window";
status = 0;
}
}
function openWindow()
{
newWindow = window. open ("remote.html", "Remote",
"width=250,height=250") ;
}
function closeWindow ()
{
if (typeof (newWindow) != "undefined")
{
if (newWindow.closed -- false)
{
newWindow. close () ;
}
}
}
function changeSize ()
{
if (window.outerHeight > 0)
{
newWindow. documen t . myForm. heigh t . val ue window.
outerHeight;
WINDOWS AND JavaScript 205
newWindow.document.myForm.width.value = window.
outerWidth;
}
}
</SCRIPT>
</HEAD>
<BODY onunload="closeWindow()"
onResize= "changeSize () ">
<FORM NAME=forml>
<INPUT TYPE="button" VALUE="Open Remote"
NAME=myButton onclick= "popupopenclose () ">
</FORM>
</BODY>
</HTML>
There is only one thing in the code that you might not know yet: outerHeight
and outerWidth. These are basically properties of any window object that tell
you the size of the outside of the browser window. If you want to know the size
of the actual document, ignoring its borders, use innerlleight and innerWidth.
Unfortunately, these properties depend on the platform. They work great on
Firefox but not on Internet Explorer (IE) version 6+, for example. That is the
reason why there is a condition checking window.outerlleight in the main
window. If you try to access that value on IE, you will get "undefined."
ASSIGNMENTS
At this point you can do most of the fun features of JavaScript, so open up
your mind, use your imagination, and try writing scripts that allow you to
communicate between different frames in different windows. Try playing
around with forms, updating data remotely, and have fun! The more fun you
have practicing, the better you will learn.
try it out, be advised that I am not responsible for any problems that may
arise. Nothing major should happen, but if you don't watch out, you might
end up with several hundred browser windows moving around your desktop.
When you are tired of seeing the effects, you should kill all the windows either
through your task bar or task manager. That being said, let me explain how
this little devilish window works, and why you need to be careful with it
(unless you have a popup blocker). The idea of this popup window is to show
several things. First we have an example of interval timers, which we use to
call a method that will calculate the new coordinates and size of the window.
Then we see how to move and resize an existing window. We also see how to
use events to detect when a key is being pressed or the mouse is clicked inside
the window. Finally, we see an example on how to create a popup window.
What the script will do is constantly move and resize a window around your
desktop (on a very basic pattern). This should be annoying enough, but to
make matters worse, the moment a key is being pressed, we will create a new
window that loads the same page, so that we have two annoying windows.
Clicking anywhere on the page will have the same effect. Note that the event
used for the key detection is onKeyDown, which means that the event is not
happening as a combination of key down and key up (full key press), but just
when the key goes down. Now, since most operating systems will repeat the
key if it stays pressed, holding the key down will be considered as a lot of
separate events. I tried pressing it for about a full second and ended up with
around 20 windows. Of course, having onKeyDown as the event also means
that if the users tries using ALT + F4 (default combination of keys to close a
window), they will open a new window (because of the button being pressed)
and close it (because of the "closing" combination of keys), but if they hold
the key down too long, the windows might be created faster than they are
deleted. Well, here is the code, I hope you enjoy it ©:
<HTML>
<HEAD>
<TITLE>OMG THIS SUCKS! </TITLE>
<SCRIPT language="JavaScript">
var size = 800;
var direction = 1;
var myTimerID = setInterval ("startannoying()", 1);
function newwindow()
{
window. open ("annoyingwindow. h tml ", "", "II) ;
}
function startannoying ()
{
if (direction == 0)
{
size += 10;
208 WINDOWS AND FRAMES
i f (size == 800)
direction = 1;
}
else
{
size -= 10;
i f (size == 100)
{
direction = 0;
}
}
window.resizeTo (size, size);
window.moveTo (size, size);
}
</SCRIPT>
</HEAD>
<BODY otikeydowtivrriewwi.ndow t) " onmousedown="newwindow()">
I wouldn't touch the keyboard or click on the window
i f I was you!!
</BODY>
</HTML>
You could actually make this worse by, for example, adding an onUnload,
in case the user tries (and manages) to hit the "back" button. Any "improve-
ments" to make the page more annoying are entirely up to your imagination.
17
String Manipulations
Revisited
OVERVIEW
Back in Chapter 14, we saw that arrays had a method called join that allowed
the creation of a string from a set of array elements. This was the same as a
PHP implode. You might be wondering whether there is an equivalent to
PHP's explode in JavaScript, and the answer obviously is "Yes." The function
is called split() and takes a delimiter as parameter. For example, assuming
that you have a string called myString, you could write myString.splitt',') if
you wanted to use the comma as a separator. There is something very impor-
tant to realize when you use split. If your string finishes with the separator,
you will have an entry that is an empty string. So if you do
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
209
210 STRING MANIPULATIONS REVISITED
your array would actually hold "a." "b," "c.' "d? and "",
Another interesting function, which will acquire an entirely new dimen-
sion in a few paragraphs after we do regular expressions, is replace(match,
replacement). For example, you could do myString. replace C'winter",
"summer") to have a sunnier day. As we will see later on, the match can
actually be a regular expression, which will allow you to change as many
matches as needed.
Next we have search; for example, myString.search("Bewchy") would
return the string's position or -1 if the string were not found. You might
wonder what the difference is between this and indexOf. Simply put, search
accepts regular expressions; indexOf does not.
The final basic method is match, for example, myString.match("1234").
This creates an array with all the matches found on the string. In our example
it would create an array with as many entries as times you found 1234 on
myString. Each entry will have the exact same 1234 data. You might wonder
why you would use this method! Well, it will become much more useful when
we combine it with regular expressions, as it will give us all matches on our
expression.
The idea is to change all "bar" iterations with "Club," but if you try the
example, the result will be "Club, barman, barmaid, Bar, barcode." Only the
first one would be replaced. If you wish to match all iterations, you need to
add the "global match" modifier, which will try to match the expression in
the entire string. Simply add a "g" after the closing slash. This would still raise
an issue, as we have a string Bar with capital B. Since B is different from b,
it would still not match the second word Bar. You can solve this with the
"case-insensitive" modifier, by putting a letter "i'' at the end of the regular
expression. Our regular expression becomes
With this regular expression, the result would be "Club, Clubman, Clubmaid,
Club, Clubcode",
To make expressions more useful, you can use any of the following special
characters:
For example, to find a number like 1-800-555-5555, we can use either one
of these two:
It is also possible to use a series of characters that allow forcing the posi-
tion of a regular expression. Here is the list:
In this little piece of code we are replacing word boundaries all across the
string (due to the global match modifier) with a pipe (I). The resulting string
would be "IHelloIIWorldl!!! Ithisllisnl'ltl Ireallyilcooillisilitl?" Therefore, if
we wanted to improve our previous bar example, to have only the full word
bar matched, you would use the regular expression /\bbar\b/gi .
Remember that you can group regular expression in parentheses; so, for
example /\b ((ab) [2,3}c) + \blgi would match globally (and case-insensitively)
any full word (surrounded by word boundaries) that will have two or three
groups of ab followed by a c, 1 or more times. For example, "ababc" is a match,
and so is "abababcababc," but not "ababab c," since there is a word boundary
before c is found.
Another useful feature of regular expressions is the reuse of previous
matches. For example, you could have a string with comma-separated strings,
and you could try to see if the same word appears twice in a row anywhere
in the string. To do this, we must first group in parentheses the pattern that
REGULAR EXPRESSIONS IN PHP 213
will be repeated, and then refer to it with a backslash followed by the position
of the pattern (only the parenthesized patterns count). Our regular expression
to match successive identical words separated by a comma and a white space
would be I(\w+), \11. Basically, we try to find any word character one or more
times, followed by a comma, a white space, and the exact same group of word
characters found before the comma.
Sometimes you might have two possible choices of matches, and you might
want to match only one of two choices. You can use a pipe (I), which is the
"OR" character. For example, writing/a (ble)dl would match either abd or aed,
but never abed, abc or ad.
You may also use eregi, which does the same, but ignoring the character
case. It is like adding the i modifier at the end of a regular expression in
JavaScript.
214 STRING MANIPULATIONS REVISITED
I #begin pattern
\b #find word boundary
php #Iollowed by "php"
\b #then another word boundary
Ixi
Another modifier that can be added after the closing slash is the letter e.
When used, it allows the use of subpattern matches similar to \1 in JavaScript.
This feature will be usable with the function preg_replace(), with the differ-
ence that it needs a double backslash (as shown below).
Finally, you may use any of the following special characters with any
PCRE: \d for digit, \D for nondigit, \s for white space character, \5 for non-
white-space character, \w for word character, \ W for nonword character, \b
REGULAR EXPRESSIONS IN PHP 215
for word boundary, \B for nonword boundary, \A for start of subject, \z for
end of subject, and \Z for end of subject or new line. For more information
you may go to www.pcre.or~.
Here is an example of how to use the e attribute to replace all tag names
in a string to uppercase. To match all tag names, and not its attributes, find a
character "less than," maybe followed by a slash (in case of a closing tag) and
a series of word characters, followed by another set of characters different
from "greater than," followed by "greater than." Since the character slash is
a special character, to use it we need to "escape" it by preceding it with a
backslash, so if you see "\/," it is not a strange capital V (or inverted uppercase
Greek letter lambda); it is a backslash followed by a forward slash. Our
regular expression would be "/( < \/?)(\W+)([A> ]* > )/e". The three groups
in parentheses are as follows: opening "less than," tag name, parameters, if
any, with closing "greater than." To change the string to enable it to hold a11-
uppercase tags, you would do
OVERVIEW
You might be wondering what DHTML is, and, as do many people, you probably
think it is a new language. Well, you would be wrong. DHTML stands for
Dynamic HTML, which is a "high-tech" word used to define the possibility of
changing an already loaded page. When wechanged images, and moved windows,
we were doing DHTML. In this chapter we will take this one step further, seeing
how to change text, positioning of elements, and almost anything.
One very important thing to realize is that DHTML is technically done
through JavaScript; therefore the scripts we will write might not work in every
single browser. It is important to test your scripts and try to force yourself to
use cross-platform objects and properties.
POSITIONING ELEMENTS
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
217
218 JavaScript AND DHTML
provided is calculated from the top left of the container. Note that the actual
coordinates can be set as part of the item's style by using the top and left
properties. To illustrate positioning, we will create a colored box, using the
height and width style attributes. Imagine that you have the following classes
in your style sheet:
<'--
.Box {top: lOOPXi
left: lOOPXi
height: 300PXi
width: 300PXi
background-color: redi
position: absolutei }
.ParagraphStyle { top: lOOpXi
left: lOOpXi
color: yel.Low,
position: rel er ive, }
-->
This example yields a red box of 300 x 300 pixels, with its top left at 100 x
100 pixels from the top left of the browser:
<HTML>
<HEAD>
<TITLE>Positioning Example</TITLE>
<LINK rel=stylesheet href=mystyle.css type=text/css>
<BODY>
<DIV CLASS= "Box">
<P CLASS="ParagraphStyle">
This is cool!!!
<IP>
<IP>
<IBODY>
<IHTML>
Once you have a set of opening/closing tags with an ID set to it, you may
access the text inside it using the attribute innerText. For example, if we
POSITIONING ELEMENTS 219
have the previous paragraph, you could change its contents by changing
myParagraph. innerlext. Note that inner'Iext does not work on Firefox; instead,
you should use textContent. As with any of the basic tags we saw earlier, you
can update any property of the elements. Properties include any of the attri-
butes in the style sheet. To change a style simply use the word style, followed
by the style attribute to change. For example, you can change the left position
of a paragraph to "200" by doing
myParagraph.style.left = "200px";
You can also add any event handler to paragraphs or other items, to enable
you to change text when the mouse gets over it or out, even when you click
it. This way you can create sections of your page that will behave like links
without being links! Simply add an onclick property that will change the
location.href, and you have made a link for yourself.
Be creative, but do not abuse the flourishes as they might become annoying
to users. A nice use of paragraph positioning is scrolling news headers. You
could have a section on top of your page with a paragraph that will scroll text
thanks to an interval timer.
You can actually use coordinates that are negative when positioning an
element. This means that they are placed outside the actual body of the page,
making them hidden. From there you can use events to bring those sections
in or out of the page, which is great for dynamic menus. Later on we will see
how we can create this sort of menus.
As you probably realized using innerText, it only captures text skipping
any HTML in the block. If you wish to set the contents of a paragraph or
other element to contain HTML tags, you can use the properties innerHTML
and outerHTML. The first will allow setting or reading all the contents
between the opening and closing tags. The latter actually allows you to change
the contents as well as the containing tags. This can be used to create an
HTML code preview viewer as in the following example. This example works
only with Microsoft Internet Explorer (IE). After it you will see a similar
example that works on Firefox:
<HTML>
<HEAD>
<SCRIPT LANGUAGE=JavaScript>
function setHTML()
{
if (radInnerOuter[Ol.checked == true)
{
divl. innerHTML = textareal. value
}
else
220 JavaScript AND DHTML
{
divl.outerHTML textareal. value;
}
}
function getHTML()
{
if (radInnerOuter[OJ . checked == true)
{
textareal.value = divl.innerHTML;
}
else
{
textareal.value = divl.outerHTML;
}
}
</SCRIPT>
</HEAD>
<BODY>
<DIV ID="divl">
Write your HTML code in the box below!</Hl>
</DIV>
<BR><TEXTAREA COLS=50 ROWS=20 ID=textareal
NAME=textareal></TEXTAREA>
InnerHTML <INPUT TYPE= "radio" NAME= "radInnerOu ter"
CHECKED>
outerHTML <INPUT TYPE="radio" NAME="radInnerOuter">
<INPUT TYPE="button" VALUE="Get HTML" NAME="bttnGet"
onclick="getHTML()">
<INPUT TYPE="button" VALUE="Set HTML" NAME="bttnSet"
onclick="setHTML()">
</BODY>
</HTML>
<HTML>
<HEAD>
<SCRIPT LANGUAGE=JavaScript>
function set()
{
if (document.forml.radTextHTML[OJ . checked -- true)
POSITIONING ELEMENTS 221
(
divl . innerHTML document. Eoxml., textareai. value
)
else
(
dis/l . textContent document. Eortiil., textareai. value i
)
)
function get ()
{
if (document.formi.radTextHTML[O] . checked == true)
(
document. iiorml . textareai. val ue = divi. innerHTML i
)
else
(
document. Eoxml . textareai. value disrl . t.excconcentu
)
)
</SCRIPT>
</HEAD>
<BODY>
<DIV ID="divi">
<Hi>Write your H~L code in the box below!</Hi>
</DIV>
<FORM NAME="formi">
<BR><TEXTAREA COLS=60 ROWS=10 ID=textareal
NAME =textareal></TEXTAREA>
<BR>
<BR>
InnerHTML <INPUT TYPE="radio" NAME="radTextHTML"
CHECKED>
ContentText <INPUT TYPE="radio" NAME="radTextHTML"><P>
<INPUT TYPE="button" VALUE="Get" NAME="bttnGet"
onclick="get()">
<INPUT TYPE="button" VALUE="Set" NAME="bttnSet"
onclick="set()">
</BODY>
</HTML>
If you wish to update the inner or outer text or HTML of a block without
changing the entire contents, you can use insertAdjacentText or insertAdja-
centHTML. These are two methods that accept the location of the insertion,
followed by the block to insert. The value of the first parameter can be before-
Begin to insert before the opening tag of a block, afterBegin to insert after
222 JavaScript AND DHTML
the opening tag, and before the current text/HTML, beforeEnd to insert right
before the closing tag, and afterEnd to insert after the closing tag. For example,
myDiv.insertAdjacentText("beforeEnd", "<BR>"); would insert a break of
line at the end of myDiv but before its closing tag.
Another fun feature of DHTML is the ability to detect the source of an
event. In IE, for example, you can use the event object, which holds informa-
tion on the location of the mouse cursor, or what caused each event. Here are
the contents of the event object:
Imagine that you are trying to imitate the typical window menus that every
application has (with File, Edit, View, etc.) but inside a Webpage. The idea is
that you want to show a table with a set of options; if you click on any of them,
you "activate" the menus, which would show a table with all the submenus
for each of those options, right under the main title. In order to do so, we
could have a set of tables with the submenus, each table would be a submenu
and would be in a separate DIV section. The idea is to keep the submenus
"hidden" and make them appear in the page when the right option is
selected.
To "hide" a submenu, we will place its DIV at a set of negative coordinates,
placing it in a higher and further left position than the top left corner of
the browser, effectively making it invisible. Once the option is selected,
we will place the submenu right under the main option. We will combine
this technique with several onmouseover, onmouseout, and onclick maneuvers.
The onclick will be used to know whether you are in "menus" mode or
not, just like when you click on File. After the first click, you want to show
WRITING DYNAMIC MENUS IN DHTML 223
all the submenus by simply placing the mouse over its title. Whenever we
move out of at menu title, we will hide its submenu, unless we place the cursor
on that same submenu. Finally after a click is made, we will switch back to
"no-menu" mode, hiding all submenus. Below you will see the code to achieve
this on Internet Explorer (this is just a basic example; most links will not even
work). Be sure to check the companion Website for the Firefox-compatible
version, as well as many other examples:
<HTML>
<HEAD>
<TITLE>DHTML Menus Example - MSIE Version</TITLE>
<SCRIPT LANGUAGE= "JavaScript">
var showMenus 0; =
function hideMenu(num)
(
var toHideId = (num.id) .substring(]);
var destinationId = (event.srcElement.id).
substring(J) ;
i f (toHideId ! = destinationId// (showMenus 0))
{
num.style.top = -500;
num.style.left = -500;
}
}
function pickMenu(num)
{
hideMen u ( divO ) ;
hideMenu (divl);
hideMenu (div2);
var src = event.srcElement;
i f (showMenus == 1)
{
num.style. top = parseInt (src.style. top) + src.
height;
num.style.left = parseInt (src.style.left);
}
}
function toggle (num)
{
if (showMenus == 1)
{
hideMenu (divO);
hideMenu (divl);
hideMenu (div2);
224 JavaScript AND DHTML
showMenus 0;
}
else
{
showMenus = 1;
pickMenu (num) ;
}
}
</SCRIPT>
</HEAD>
<BODY>
<IMG SRC="file.gif" ID="imgO" onmouseover="pickMenu
(divO)" onmouseout="hideMenu(divO)" onclick="toggle(divO)"
style="position:absolute; left :10px; top:10px;">
<IMG SRC= "links. gif" ID= "img1" onmouseover= "pickMenu
(divl)" onmouseout= "hideMenu (divl)" onclick= "toggle (divl) "
style="position:absolute; left :115px; top:10px;">
<IMG SRC="help.gif" ID="img2" onmouseover="pickMenu
(div2)" onmouseout="hideMenu(div2)" onclick="toggle(div2)"
style="position :absolute; left:220px; top:10px;">
<DIV ID="divO" STYLE="position:
absolute;top:-500;left:-500;width:100px;">
<TABLE border=l>
<TR>
<TD><A HREF="">Option l</A></TD>
</TR>
<TR>
<TD><A HREF="">Option 2</A></TD>
</TR>
<TR>
<TD><A HREF="">Option 3</A></TD>
</TR>
<TR>
<TD><A HREF="">Option 4</A></TD>
</TR>
</TABLE>
</DIV>
<DIV ID="div1" STYLE="position:absolutei top:-500i
left:-500;">
<TABLE border=l>
<TR>
<TD><A HREF= ..http://www.google.com ..>Google</A></TD>
</TR>
<TR>
<TD><A HREF= ''http://www. stevens. edu ">Stevens</A></TD>
YOUR TURN!! 225
</TR>
<TR>
<TD><A HREF= ..http://www.wiley.com ..>Wiley</A></TD>
</TR>
</TABLE>
</DIV>
<DIV ID="div2" STYLE="position:absolute;top:-500;
left:-500;">
<TABLE border=l>
<TR>
<TD><A HREF="">About</A></TD>
</TR>
<TR>
<TD><A HREF="">Help Me</A></TD>
</TR>
</TABLE>
</DIV>
</BODY>
</HTML>
YOUR TURN!!
Now that you know about DHTML, try to write a script that will show moving
paragraphs on the screen. Remember, you can set the position of a paragraph
myParagraph by doing
OVERVIEW
With so many techniques and approaches, you might feel a bit lost trying to
know how to organize your development phases, what you should start with,
and what language should be used for what. This chapter provides the guide-
lines for applying the design techniques I have used in the past and that have
always proved to work. As an example, we will imagine that we are writing
a Web-based commerce site. These guidelines are general to any language;
at the end of this chapter I will get more specific on the strong points of each
language and what languages should be used and when.
PROCEDURE
Step 1-Understanding the Problem and Finding the Solution
This is probably one of the most important steps in Web development,
and actually any type of programming. Designing your scripts properly
depend on this. You must understand what is that you are trying to achieve
and then figure out how to solve that problem. Usually the solution is found
through several meetings between the developer's group and their managers.
It is a good idea to have project sponsors at the first meetings so that they can
state clearly what they are paying for and what they would like to accomplish.
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
227
228 PUTTING IT ALL TOGETHER!
Once the first meeting has taken place with the decided scope of the
project, you need to visualize how the final product will behave and what
modules will be required. For example, if we are writing an e-business site,
we know that we will need a payment module for costumers to pay for their
purchases, a shopping cart system to keep track of purchases, a username/
password system to remember regular users, an administrator panel to add
items to our store, and scripts that will show the products to the clients by
extracting the details from the database, allowing items to be searched by
name, price range, or even category. To keep the example simple, and since
I know what most computer science students like to do in their spare time,
we will assume that we are coding a Website that will sell videogames.
Obviously this table still does not tell us which categories a game belongs
in, so we need to create a game_category table with id_game_category (not
strictly needed, but I want to keep it simple and avoid the need to combine
two attributes as my primary key), id_game, and id_category. This will allow
me to store all the categories of all the games. If a game has more than one
category, it will have two entries in that table. This is a good example of a
n.m relationship, where each game can have many categories, and each cate-
gory can be applied to many games.
Following the same type of logic, even though the number of possible game
platforms is limited, there are always new platforms appearing every few
years. In order to keep our database as robust and flexible as possible, we
will have a platforms table with id_platform and platform, similar to the cat-
egories table. As you probably noticed earlier, the videogames table had no
reference to platform or price, because the same game may be available in
different platforms, and its price will likely depend on its platform. For
example, a handheld version of a game will always be less expensive than the
same game on the newest generation of consoles. We will therefore use a
game_platform with id_game_platform (this is the id used), id_game,
id_platform, and price.
We then need to keep track of shopping carts. Most basic commercial
Websites simply store the shopping cart in a session or a set of cookies, loosing
all its contents if the user leaves the current computer and logs in on a differ-
ent one later on. Instead of this behavior, we instruct the computer to memo-
rize all shopping carts of registered users, so that the next time they log in,
the items they tried to purchase will still be available. Each user is supposed
to have only a single cart, so to keep things simple, we will use id_user as the
primary key for the carts. If the user is not logged in, we will not store the
cart in the database, using sessions instead. Basically, shoppers would get in
the page, start shopping, and if they log in, their shopping carts will be stored
in the database. If they were already logged in, updating the carts would
update the database as well. Our table cart will hold id_user, date, and
total_price. To store the items in the cart and its quantities, we can use a table
game_in_cart with id_game_in_cart (dull id), id_user (reference to a specific
shopping cart), id_game_platform (reference to a game in a specific plat-
form), and quantity. The price can be calculated through the game_platform
table.
Once the user decides to check out the shopping cart (i.e., finishes
shopping), you need to ask for information such as shipping address, billing
address, and payment information. Each user may have several credit cards,
each associated with its own billing address information, and can also have a
group of possible shipping addresses (in case the order is to be sent home, to
the office or to a friend). To make our database as flexible as possible, we will
have a table addresses with id_address, id_user, linel, line2, city, zip, and
phone; and a table payment with id_payment, id_address, type (Visa,
MasterCard, American Express, or other payment method), number, expiration
230 PUITING IT ALL TOGETHER!
·:·"::.II·:":;~I.l":._:;·.:i:.;:;I·~. i:::.:.:.~---1-";
PK Id address!
FK1 id_user" ....·'·····i
line 1 I
line 2 ~
city
zip
FK11 id user
~_~~_1h_one .-,Wh •• Wh
date I
~ total
FK2! id_payment
~~~~~J.-""-IFK3 id_address
id_address L
shippin~~~.!.~~,~.
type
number
expiration
ccv
FK2 id_user
date, ccv (security code), and id_user (we could do without it, since we can
extract the user information through the id_address, but it would simplify the
task of searching for payment methods for a specific user).
After the user confirms the payment method as well as the shipping and
billing address, the shopping cart is upgraded to an "order," and will be stored
in a table orders with id_order, id_user, date, total, id_payment (for payment
method and billing address), id_address (for shipping address), shipping_
method. The specific items of each order will be in a table order_item with
id_order_item, id_order, id_game_platform, quantity.
The final layout of our database is shown in Figure 19.1.
posed to do, rather than a pretty page that has errors all over the place and
does nothing at all.
Try to start with the important tasks first, as they will be the key parts of
the project, but keep in mind what will need to be done in further steps. It is
a good idea to set some data inside the database so that you can tell whether
the scripts work well.
In our game-selling Website I would probably start writing the code to
show all the games in the database, with 10 titles per page, taking advantage
of the LIMIT property used in MySQL when performing a SELECT. The
next step would be to extract the categories and platforms for which we have
games from the database and write a script that would show the games for a
specific platform and/or category by simply clicking on a link.
Once you can display all items correctly, work on the user login procedure.
This should not take too long. At the same time create the forms to attract new
users and add information like addresses and payment information. Make sure
that the login script creates a session and that the session is kept alive until the
user logs out. Of course, write the logout procedure that will destroy the session.
Next, start working on the add-to-cart function that should be attached to
each displayed game on the page. Then work on the scripts that would help
you update the cart, such as removing items, adding items, or changing the
quantities of items already in there. Finally, work on the checkout procedure,
turning a cart into an order.
If you write all the previously mentioned functionalities, the core of the
project is done, and you can start pitching the progress to your team mates
to try and find usability problems and bugs.
Step 4-Backside
You should always create an administrator panel to help you handle the data
in your Website. For example, to add a new user or other entry in the database,
it is much more recommendable to do so via your own scripts, rather than
going straight to the database manager and adding the data manually.
Since you already wrote a login page, and in your database you have a flag
level, add a check during login that will test whether the user is an adminis-
trator, and, if so, direct the user to an Admin panel.
The Admin panel should have scripts allowing the removal of items, as
well as adding new categories, platforms, games, removing users, making a
user an Admin, and pretty much anything that would update the contents of
the database. To test out the functionalities, simply try adding a few items
through the newly built Admin panel, then switch to a regular user and see
if the products appear as they should.
functionality. This could include a searching tool to look for items by name,
platform, esbr, price, or anything you might want to provide. You can do a
"news" page that would show the most recent releases, based on the release
date on the database, as well as the current date. You could also have an
"upcoming" section with the games that are about to appear. The whole point
of this is to improve the functionality of your Webpage, based on recommen-
dations from tester users, project managers, and other team mates. Do not get
too far away from your initial agreement; if you ask any project manager, you
will learn that "Scope creep will kill you!"-meaning that if you keep chang-
ing the specifications of the project after you already agreed on them, your
project will be delayed, potentially making you loose your window of oppor-
tunity as well as many development hours (and time is money). The "updates"
should concentrate on bug fixes, and increased robustness on the project.
A typical thing that should be done in this step is to add forms verification
for every single form on the Website. You should check all the data transmit-
ted from page to page and make sure that it contains what it should.
At the end of this step your entire Website should be functional, but might
not look the best. So let us advance to step 6.
Step 8-Presentation
The last important step after you are sure that you have produced the best
Website ever is to present it to the program sponsors (the people who paid
for it) and make sure that they like it. You probably think this is the easiest
step, but unfortunately project sponsors always want new features in their
sites, so be prepared for criticism, and other remarks on things that should
be included that you did not work on. It is also a good chance to get some
input that might help you do nice updates on the site. The approach I would
recommend is to start explaining your project in general, discussing only the
main features and then focusing a little more on details of the functionalities
only if you are asked to. This is assuming that you are talking to a person
with no Web programming knowledge. If you present to a fellow programmer,
you might want to skip the "commercial talk" and go straight to the function-
alities, emphasizing security features and administrator panel.
Step 9-Publication
After the project has been approved, it is time to release it. Upload it to the
Web server of your choice, and make sure that everything is set up properly.
All pages should be accessible, all include files should be in secured folders,
234 nrmue IT ALL TOGETHER!
all the links and images should be working, and the page should be accessible
by anyone in the world. If you did the previous steps properly, this should not
take long.
You finally know how to go step by step from a single idea to a full project,
but you still might have a very important question, namely: "What language
should I use?" Most Web programming books concentrate on a single
approach and a maximum of one or two technologies, yet here we have talked
about four programming languages as well as a database management tool,
so how should you combine all these languages?
First, you should familiarize yourself with PhpMyAdmin. Since the cre-
ation of the database should be one of the first development steps on the
project, you should use this tool to set everything up before writing a single
line of code.
For scripts such as login procedures, logout, session handling, and anything
that requires extracting information from the database and creating dynamic
pages, you should use PHP combined with HTML for the layout. Of course,
any query to gather information from the database should be done in MySQL
syntax, but submitted to the database through PHP scripts. All the informa-
tion gathered should be retrieved from PHP.
Actually PHP is probably the language that you will use for about three-
quarters of your project as it is the backbone of your project, and handles
every minute detail on things that need to get done for the user to see a nice
output.
JavaScript should be used for enhancements, such as, for example, form
verification. Many people want to check the forms in PHP, but that means
that all the data are sent from your form to PHP, then verified, and, in case
of problems, the user is redirected to the same first form. This takes time as
you need to communicate several times with the server. Handling forms in
JavaScript is an excellent idea for things like required fields that cannot be
WHAT LANGUAGE TO USE? 235
empty, valid email addresses, and other basic checks that should be done
before sending any data to the processing PHP script. Here is where you
should practice all those regular expressions in JavaScript and keep the user
in the form (remember to return false) as long as there are one or more prob-
lems in the form. Once JavaScript verifies that all the required data are there
and formatted as required, you may allow the form to send its data to PHP
(return true) and have PHP run a second series of tests. I always recommend
a two-phase verification to get rid of as many possible errors and security
holes as possible. My JavaScript side takes care of required fields and format-
ting, and PHP will verify things like compatibility with the values in the
database, user level, and so on.
JavaScript is also very useful in providing some visual enhancements such
as dropdown menus or rollover buttons. The most basic rollovers you could
do would be to change an image with onmouseover and onmouseout if you
are using images for your menu items. You can otherwise change a text
style.
In a nutshell, HTML will organize the output layout, PHP will populate
the page with the appropriate data, and JavaScript will make it all look nicer,
as well as verify that the user enters the required information. MySQL will
be the tool used by PHP to manipulate the database.
Well, I hope this book will help you understand the ins and outs of Web
programming, the folklore, and good and poor design, and I hope that
creating Websites will be as gratifying for you as it is for me. I wish you all
the best!
Appendix A
Special Characters
••
♠ ~ black spade suit
♣ black club suit
•
♥ black heart suit
♦ black diamond suit
‾ overline, = spacing overscore
&Iarr; leftward arrow
↑ upward arrow
→ ---+ rightward arrow
↓ t downward arrow
TM
™ trademark sign
" double quotation mark
& & ampersand
⁄ / slash
&It; < less-than sign
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavcScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
237
238 APPENDIX A
Installing on UNIX
OVERVIEW
In most cases, your UNIX distribution will install everything for you, but if you
are one of the unlucky UNIX users who have to install everything manually,
follow these directives on Apache, PHP, and MySQL installation. This just
reflects installation steps, as the configuration is pretty much the same as when
installing on a Windows-based computer. I will assume that you have root
access in your UNIX server, since you will need it on many of the steps. If you
do not know what root access is, I advise you to contact your system administra-
tors and have them install everything for you. This should spare you some head-
aches, and your system administrators will be much happier as they will make
sure that everything is done properly. The installation steps will assume that
you are using default configuration options. For more advanced options, check
www.apache.or~, www.php.net, and www.mysql.com. I will not explain how to
install phpBB or phpMyAdmin, as it is the same as a Windows installation.
Download the most recent version of Apache 2.2 and a fitting PHP version
from the abovementioned places. This quick guide covers only the basics to
get you started with Apache 2.0 and PHP. For more information, read the
Apache documentation. The version numbers have been omitted here, to
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
241
242 APPENDIX B
ensure that the instructions are not incorrect. You will need to replace the
"NN" here with the correct values from your files. (Note: The following
guidelines were excepted directly from the PHP online manual.)
1. gzip -d httpd-2_2_NN.tar.gz
2. tar xvf httpd-2_2_NN.tar
3. gunzip php-NN.tar.gz
4. tar -xvf php-NN.tar
5. cd httpd-2_2_NN
6../configure --enable-so
7. make
8. make install
Now you have Apache 2.2.NN available under /usr/local/apache2,
configured with loadable module support and the standard MPM prefork.
To test the installation use your normal procedure for starting the Apache
server, e.g.:
/usr/local/apache2/bin/apachectl start
and stop the server to go on with the configuration for PHP:
/usr/local/apache2/bin/apachectl stop.
9. cd ../php-NN
10. Now, configure your PHP. This is where you customize your PHP with
various options, like which extensions will be enabled. Do a ./configure
-help for a list of available options. In our example we'll do a simple
configure with Apache 2 and MySQL support. Your path to apxs may
differ, in fact, the binary may even be named apxs2 on your system.
./configure --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql
11. make
12. make install
If you decide to change your configure options after installation, you only
need to repeat the last three steps. You only need to restart apache for
the new module to take effect. A recompile of Apache is not needed.
Note that unless told otherwise, "make install" will also install PEAR,
various PHP tools such as phpize, install the PHP eLI, and more.
13. Setup your php.ini
cp php.ini-dist /usr/local/lib/php.ini
You may edit your .ini file to set PHP options. If you prefer having php.
ini in another location, use --with-config-file-path=/some/path in step 10.
If you instead choose php.ini-recommended, be certain to read the list of
changes within, as they affect how PHP behaves.
INSTALLING ON UNIX 243
14. Edit your httpd.conf to load the PHP module. The path on the right hand
side of the LoadModule statement must point to the path of the PHP
module on your system. The make install from above may have already
added this for you, but be sure to check.
For PHP 5:
LoadModule php5_module modules/libphp5.so
15. Tell Apache to parse certain extensions as PHP. For example, let's have
Apache parse the .php extension as PHP. You could have any extension(s)
parse as PHP by simply adding more, with each separated by a space.
We'll add .phtml to demonstrate.
AddType application/x-httpd-php .php .phtml
It's also common to setup the .phps extension to show highlighted PHP
source, this can be done with:
AddType application/x-httpd-php-source .phps
16. Use your normal procedure for starting the Apache server, e.g.:
s/usr/local/apache2/bin/apachectl start
INSTALLING MySQL
(Note: The following notes are quoted directly from the online reference
manual of MySQL.)
• MySQL-shared-compat-VERSION.i386.rpm
This package includes the shared libraries for both MySQL 3.23 and
MySQL 4.0. Install this package instead of MySQL-shared if you
have applications installed that are dynamically linked against MySQL
3.23 but you want to upgrade to MySQL 4.0 without breaking the
library dependencies. This package has been available since MySQL
4.0.13.
• MySQL-embedded-VERSION.i386.rpm
The embedded MySQL server library (available as of MySQL 4.0).
• MySQL- VERSION. src. rpm
This contains the source code for all of the previous packages. It can
also be used to rebuild the RPMs on other architectures (for example,
Alpha or SPARe).
To see all files in an RPM package (for example, a MySQL-server
RPM), run a commnd like this:
shell> rpm -qpI MySQL-server-VBRSION.i386.rpm>
To perform a standard minimal installation, install the server and client
RPMs:
shell> rpm -i MySQL-server-VJ:RSION.i386.rpm
shell> rpm -i MySQL-cIient-VERSION.i386.rpm
To install only the client programs, install just the client RPM:
shell> rpm -i MySQL-client-VERSION.i386.rpm
The server RPM places data under the /var/lib/mysql directory.
The RPM also creates a login account for a user named mysql (if one
does not exist) to use for running the MySQL server, and creates the
appropriate entries in /etc/init.d/ to start the server automatically
at boot time. (This means that if you have performed a previous instal-
lation and have made changes to its startup script, you may want to make
a copy of the script so that you don't lose it when you install a newer
RPM.)
If you want to install the MySQL RPM on older Linux distributions that
do not support initialization scripts in /etc/init.d (directly or via a
symlink), you should create a symbolic link that points to the location
where your initialization scripts actually are installed. For example, if
that location is /etc/rc .d/init .d, use these commands before install-
ing the RPM to create /etc/init.d as a symbolic link that points
there:
shell> cd /etc
shell> In -s rc.d/init.d.
246 APPENDIX B
However, all current major Linux distributions should support the new
directory layout that uses /etc/init.d, because it is required for LSB
(Linux Standard Base) compliance.
If the RPM files that you install include MySQL-server, the mysqld
server should be up and running after installation. You should be able
to start using MySQL.
Note: The accounts that are listed in the MySQL grant tables initially
have no passwords. After starting the server, you should set up pass-
words for them.
Appendix C
Advanced phpBB
If you followed the steps of Chapter 4, you should know how to create forums
in phpBB as well as setting up its rights. Let us now see more advanced
features!
The first thing we will do is set up groups. This allows a faster rights han-
dling on who has access to different boards. Any board that should be hidden
except for specific user groups should have its rights set to PRIVATE, MOD,
or ADMIN. The PRIVATE right will block everyone from accessing the
forum in question unless you manually add the user in question to the allowed
list, or if that user is in a group with the proper rights. Using groups is much
faster in the long run.
In the Admin panel, under "Group Admin," click on "Management"; this
will show a dropdown menu with the current groups. Selecting a group and
clicking on "Look up group" will take you to the group editing page. The
button "create group" takes you to the same page, but for a new group. In
there, select the group name, its description, and a moderator, who will have
the right to add new users to the group. A group can be open, allowing anyone
to join it, closed so that everyone can see it but may only be part of the group
if added by the group moderator, or hidden; in which only the group members
can see the existence of the group. Admin groups should be hidden; if you
have a "Members" area, it should be closed, for example.
To add users to a group, you must be the group moderator or an adminis-
trator of the boards. On the main page, click on "Usergroups" (top menu)
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarro
Copyright © 2007 by John Wiley & Sons, Inc.
247
248 APPENDIX C
and select the group in which to add a member. Click on "View information,"
which will bring the list of all users of the group. Under the list you have a
text area in which you can enter a member name; do so and click "Add
member" to add the user to the group.
To change the forum access rights of a group, click on "Permissions" under
"Group Admin" in the administrator page. Choosing a group will show all
the forums in your database. In each line corresponding to a forum, you will
see a "Moderator status" dropdown menu that will allow you to make (or not
make) the group members moderators of a specific forum. In any forum that
has one of its rights set to PRIVATE, you will have another option "Allowed
Access" or "Disallowed Access," which will decide whether the group is part
of the "private" group of the forum. If you wish to set up the same kind of
rights for a specific user, click on "Permissions" under "User Admin."
There is a feature in phpBB that most users look forward to, called "ranks."
A rank represents your notoriety in the forums and can be special or post-
count-based. Click on "Ranks" under "User Admin" to access the current
list of ranks. To add a new rank, click on "Add New Rank" and fill the form
with this information: Rank Title is the string that will appear under the user's
name to show that person's rank. Special rank (yes or no) distinguishes
between fixed ranks (e.g., "moderator," "admin," "ruler of the world") and
ranks based on the number of messages posted. Minimum Posts are used for
nonspecial ranks, and signify the number of posts needed to reach the rank.
Finally, the Rank Image should be an image path, relative to the forum's root.
For example, to use "5stars.gif" as a rank image, assuming that it is inside an
"images" folder on the root, you would write .Zimages/Sstarts.gif. Rank images
should be fairly small. Usually they are stars or other symbols associated with
the forum's theme. The more stars, the more notoriety. Don't be afraid to
create outrageous ranks needing thousands of messages, since, as sad as it
may sound, if your forums become popular enough, you might have people
with those numbers. For example, in the forums I use for my courses, I use
the following ranks: nOOb (0 posts), Visitor (10 posts), Frequent Visitor (25
posts), Known Face (50 posts), and Friendly Face (100 posts). I could have
pushed it further with things like "Friend" (250 posts), "Family" (500 posts),
"Are you stalking me?" (1000 posts), and "Get a life!" (2500 posts). Be
original with the names, and lots of people will look forward to what their
next rank will be (as sad as it may sound).
Another important thing to know how to use in phpBB is how to moderate
forums. When you are an administrator or moderator of a specific board, you
will have a link on the bottom right appearing when you visit a forum that
reads "Moderate this forum." Clicking it will show the list of topics in the
forum with a checkbox at the end of each name. Selecting one or more topics
and using one of the four buttons will allow you to moderate entire topics.
The options are "Delete," to delete the entire topic along with all its replies;
"Move," to move the topic to a different forum (in which case you may leave
a "shadow" of the topic, basically the name will appear but will link to the
ADVANCED phpBB 249
class. FastTemplate.php
This is the code for my version of the class FastTemplate. It is very similar to
the one found in www.webmasters.net with some minor changes to avoid
notices with PHP5:
<?PHP
1*
CVS Revision. 1.1.0 with modifications by Steven
Gabarr6
*1
class FastTemplate {
var $FILELIST = exrey t )» II Holds the array of
filehandles
II FILELIST[HANDLE] == "fileName"
var $DYNAMIC = exrey t)» II Holds the array of dynamic
II blocks, and the fileHandles they
II live in.
var $PARSEVARS =arraY()i II Holds the array of Variable
II handles.
II PARSEVARS[HANDLE} == "value"
var $LOADED = erxey t)» II We only want to load a
template
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
251
252 APPENDIX D
II ************************************************************
II A quick check of the template file before reading it.
II This is -not- a reliable check, mostly due to
inconsistencies
II in the way PHP determines i f a file is readable.
function is_safe ($filename)
(
iff !file_exists ($filename))
(
$this->error(" [$filename] does not exist", 0);
return false;
}
return true;
}
II ************************************************************
II Grabs a template from the root dir and
II reads i t into a (potentially REALLY) big string
function get_template ($ template)
(
if(empty($this->ROOT) )
(
$this->error("Cannot open template. Root not
valid.",l);
return false;
}
$:fi.lename = "$this->ROOT". "$ templa te";
$contents = implode ("", (@file ($filename)));
iff (! $contents) or (empty ($con tents) ) )
(
$this->error("get_template() failure: [$filename]
$php_errormsg",l) ;
}
return $contents;
} II end get_template
II ************************************************************
II Prints the warnings for unresolved variable
references
II in template files. Used i f STRICT is true
function show_unknowns ($Line)
(
$unknown = array ();
i f (ereg (" ({ [A-ZO-9_1 +}) ", $Line, $unknown))
(
$UnkVar = $ unknown [11;
if(! (empty ($ UnkVa r) ))
class. FastTemplate.php 255
(
@error_log("[FastTemplateJ Warning: no value found
for variable: $UnkVar ",0);
}
}
} I I end show_unknowns ()
II ************************************************************
II This routine get's called by parser) and does the
actual
II {VAR} to VALUE conversion within the template.
function parse_template ($ template, $tpl_array)
{
while ( list ($key, $val) = each ($tpl_array) )
{
if (! (empty($key)))
(
if(gettype($val) != "string")
{
settype ($val, "string");
}
II php4 doesn't like '{$' combinations
$key = '{'."$key".'}';
$template =
ereg_replace ("$key", "$val", "$ templa te") ;
II$template =
str_replace ("$key", "$val", "$template");
}
}
if(! $this->STRICT)
{
II Silently remove anything not already found
$template = ereg_replace (U{( [A-ZO-9_J+)}", "", $ template) ;
}
else
{
II Warn about unresolved template variables
i f (ereg(U ({ [A-ZD-9_J+})", $ template) )
(
$unknown = split(U\n",$template);
while (list ($Element, $Line) = each ($unknown)
(
$UnkVar = $Line;
if(! (empty($UnkVar)))
(
$this->show_unknowns($UnkVar);
256 APPENDIX D
}
}
}
}
return $template;
} II end parse_template();
II ************************************************************
II The meat of the whole class. The magic happens here.
function parse ( $ReturnVar, $FileTags )
{
$append = false;
$this->LAST = $ReturnVar;
$this->HANDLE[$ReturnVar] = 1;
i f t ! isset ($this->$ReturnVar))
$this->$ReturnVar = "";
$val = $FileTagsi
iff (substr($val,O,1)) == '.' )
(
II Append this template to a previous ReturnVar
$append = true;
$val = substr($val,1);
}
if ( (! isset ($this->$val)) // (empty($this->$val)) )
{
$this->LOADED["$val"] = 1;
if(isset ($this->DYNAMIC ["$val"]))
(
$this->parse_dynamic($val,$ReturnVar);
}
else
{
$tileName $this->FILELIST["$val"];
$this->$val = $this->get_template ($fileName);
}
}
if($append)
{
$this->$ReturnVar .=
$this->parse_template
($this->$val,$this->PARSEVARS);
}
else
{
$this->$ReturnVar = $this->parse_template
($this->$val,$this->PARSEVARS);
}
II For recursive calls.
$this->assign(array( $ReturnVar => $this->$ReturnVar) );
}
return;
} II End parser)
II ************************************************************
function FastPrint ( $template = "" )
(
if(empty($template) )
{
$template = $this->LAST;
}
iff (! (isset ($this->$template))) // (empty($this-
>$template)) )
{
258 APPENDIX D
(
$template = $this->$ParentTag;
$DataArray = split(n\n",$template);
$newMacro = "":
$newParent = "":
$outside = true;
$start = false;
$end = false;
while ( list ($lineNum, $lineData) = each ($DataArray) )
(
$lineTest = trim ($lineData);
if(n<!-- BEGIN DYNAMIC BLOCK: $Macro -->" --
n$lineTest" )
{
$start = true;
$end = false;
$outside = false;
}
if(n<!--" END DYNAMIC BLOCK: $Macro -->" -- n$lineTest" )
{
$start = false;
$end = true;
$outside = true;
}
iff (!$outside) and (!$start) and (!$end) )
{
$newMacro .= "$lineData\n"; II Restore linebreaks
}
iff ($outside) and t! $startl and t t $end) )
{
$newParent n$lineData\n"; II Restore linebreaks
}
if($end)
{
$newParent .= '{'."$MacroName}\n";
}
I I Next line please
if($end) { $end = false; }
if($start) { $start = false; }
} I I end While
$this->$Macro = $newMacro;
$this->$ParentTag = $newParent;
return true;
} II $ParentTag NOT loaded - MAJOR oopsie
else
260 APPENDIX D
(
@error_log("ParentTag: [$ParentTag] not loaded!",O);
$this->error("ParentTag: [$ParentTag] not loaded!",O);
}
return false;
}
II ************************************************************
II Strips a DYNAMIC BLOCK from a template.
function clear_dynamic ($Macro="")
(
if(empty($Macro)) { return false; }
II The nle must already be in memory.
$ParentTag = $this->DYNAMIC["$Macro"];
iff (!$this->$ParentTag) or (empty($this->$ParentTag))
(
$nleName = $this->FILELIST[$ParentTag];
$this->$ParentTag = $this->get_template($nleName);
$this->LOADED[$ParentTag] = 1;
}
if($this->$ParentTag)
(
$template = $this->$ParentTag;
$DataArray = split("\n",$template);
$newParent = "";
$outside = true;
$start = false;
$end false;
while ( list ($lineNum, $lineData) each ($DataArray) )
(
$lineTest = trim ($lineData);
if("<!-- BEGIN DYNAMIC BLOCK: $Macro -->"
"$lineTest" )
{
$start = true;
$end = false;
$outside = false;
}
if("<!-- END DYNAMIC BLOCK: $Macro -->" -- "$lineTest" )
{
$start = false;
$end = true;
$outside = true;
}
iff ($outside) and t ! $start) and (! $end) )
{
class. FastTemplate.php 261
(
unset ($this->$val);
}
return;
}
}
I I Empty - clear all of them
while ( list ( $key, $val) = each ($this->HANDLE) )
{
$KEY = $ key;
unset ($this->$KEY);
}
return;
} II end clear()
II ************************************************************
function clear_all ()
(
$this->clear() ;
$ this-> clear_assign () ;
$this->clear_detine ();
$this->clear_tpl o,
return;
} I I end clear_all
II ************************************************************
function clear_tpl ($:fileHandle = "")
(
if(empty($this->LOADED) )
{
II Nothing loaded, nothing to clear
return true;
}
i f (empty ($tileHandle) )
{
/ I Clear ALL tileHandles
while ( list ($key, $val) = each ($this->LOADED) )
(
unset ($this->$key);
}
unset ($this->LOADED);
return true;
}
else
(
iff (get type ($fileHandle)) != "array")
{
class.FastTemplate.php 263
II function clear_parse ()
II (
II $ this->clear_assign () ;
II }
II ************************************************************
II Clears all variables set by assign ()
function clear_assign ()
(
iff 1 (empty($this->PARSEVARS)))
{
while (list ($Ref, $Val) = each ($this->PARSEVARS)
{
unset ($this->PARSEVARS ["$Ref"]);
}
}
}
II ************************************************************
function clear_href ($href)
(
iff 1empty ($href) )
(
iff (get type ($href)) 1= "array")
{
unset ($this->PARSEVARS [$href]);
return,·
}
else
{
while (list ($Ref, $val) = each ($href)
(
unset ($this->PARSEVARS[$Ref});
}
return;
}
}
else
(
I I Empty - clear them all
$this->clear_assign();
}
return;
}
II ************************************************************
function assign ($tpl_array, $trailer="")
{
class. FastTemplate.php 265
return;
} II end error()
II ************************************************************
II ************************************************************
} II End class.FastTemplate.php3
?>
Appendix E
Here is a little script for uploading a file to a server. There are two files: a
form in which to enter all details of the file to be uploaded, and the PHP file
that will process the uploading and place the file in the desired folder:
<html>
<head>
<title> A Simple Form for Uploading a File </title>
</head>
<body>
<hl>A simple form for uploading a file <rb.l»
<form action="upload.php" method="post"
enctype = "mul tipart/form-da ta">
Enter file name: <Input type=file name=usernle><br>
<input type=submit><br>
</form>
</body>
</html>
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
267
268 APPENDIX E
<html>
<head>
<title>
Upload File Example
</title>
</head>
<body>
<?php
printf("<b>Uploaded File Details </b><br><br>" I :
printf("Name: %s <br>", $_FILES["userfile"} Lrriemerl )»
printf("Temporary Name: %s <br>",
$_FILES["userfile"} ["tmp_name"});
printf("Size: %s <br>", $_FILES ["userfile"} ["size"});
printf("Type: %s <br> <br>", $_FILES["userfile"} ["type"});
i f (move_uploaded_file ($_FILES["userfile") ["tmp_name"),
"D:/Web/UploadedFiles/". $_FILES["userfile"} ["name"})) (
printf("<b>File successfully copied</b>");
} else (
printf("<b>Error: failed to copy file</b>");
}
?>
«rbo dy>
</html>
Bibliography
Apache Installation Notes (included in the Apache installation files; used as guide-
lines on how to install an Apache server).
Bellis, Mary, The History of Communication, http://inventors.about.com/library/
inventors/bI history of communication.htm (a timeline of communication-
related inventions; I used those dates in Chapter 1).
Bernstein, Lawrence, and C. M. Yuhas, Trustworthy System through Quantitative
Software Engineering, Wiley, October 2005 (nice guide on software development
and quantitative software engineering).
Cambridge Advanced Learner's Dictionary (used for the definitions of "cookie").
Classes and Objects (PHP5), chapter of the PHP online manual http://www.php.net/
manual/en/lanaua~e.oop5.php (used in Chapter 9 to explain the object-oriented
programming principles, as well as to present basic examples).
Englander, Irv, The Architecture of Computer Hardware and Systems Software: An
Information Technology Approach, 3rd ed., Wiley, January 2003 (I have used this
book as a reference on the basics of TCP/IP and also in one of my courses; it has
a nice easy approach to the technologies presented).
Internet Society, A BriefHistory ofthe Internet, http://www.isoc.org/internet/history/
brief.shtml (a brief explanation of how the Internet developed to the point it has
reached now).
Jacobs, Ian (Head of W3C Communications), About W3C: History, http://www.w3c.
org/Consortium/history (a description of how the World Wide Web concept origi-
nated, leading to the creation of the W3C).
Web Application Design and Implementation: Apache 2, PHP5, MySQL, IaveScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
269
270 BIBLIOGRAPHY
abs function, in PHP, 62. See also Math. Add-to-cart function, for videogame
abs method store Website, 231
Absolute positioning, with DHTML, ADD UNIQUE alter_spec, for MySQL
217-218 ALTER TABLE instruction, 146
Absolute URL, 18 Administration
in <A> tag, 32-33 of phpBB bulletin board, 53, 247-248
Abstract classes, 106 of videogame store Website, 228
abstract methods, 106 of Web projects, 2, 234
acos function, in PHP, 62 Admin panel, for videogame store
acosh function, in PHP, 62 Website, 231
action attribute, in <FORM> tag, Adobe, 15
111-112, 115 Advanced Research Projects Agency
Action scripts, in <BODY> tag, 29 (ARPA),6
Active links, in <BODY> tag, 29 Affectation operators, in PHP, 61
Active Server Pages (ASP), 22-23 Affectation symbol (=), in PHP, 60. See
ADD COLUMN alter_spec, for also Equal sign (=)
MySQL ALTER TABLE afterBegin method, with DHTML,
instruction, 146 221-222
ADD PRIMARY KEY alter_spec, for afterEnd method, with DHTML, 222
MySQL ALTER TABLE alert function, 172, 173
instruction, 146 with Window objects, 185
Addresses. See IP addresses; Symbolic Aliases
addresses MySQL, 142
addslashes method, in PHP, 91 in MySQL SELECT instruction, 149
Web Application Design and Implementation: Apache 2, PHP5, MySQL, JavaScript, and
Linux/UNIX, by Steven A. Gabarr6
Copyright © 2007 by John Wiley & Sons, Inc.
271
272 INDEX
for Cascading Style Sheets, 132-134 fopen function, for PHP files, 86-87, 88
as directories, 89 for command, in JavaScript, 177
downloading work environment, foreach command
45-46 PHP arrays and, 71-73, 80
with FastTemplate, 129-131 in retrieving form information on
for MySQL database, 50 PHP scripts, 116
PHP and, 48-50, 85-89, 95-96 in retrieving session information on
with phpBB bulletin board, 52 PHP scripts, 121
PHP file explorer and, 97-98 for loop, 81-82
PHP functions in, 82 PHP arrays and, 71-73
for phpMyAdmin application, 51 Form method, document object and,
with sessions, 121-122 189, 190
template, 127, 128 Formatting
uploading to servers, 267-268 of HTML text, 30-31
filesize function, in PHP, 89 of strings, 94-95
File Transfer Protocol (FTP), 11 Forms, 111-117
origin of, 6 dynamically creating, 116-117
programming tools for, 13 GET versus POST for, 112, 115
World Wide Web and, 6 PHP scripts and, 115-116
filetype function, in PHP, 89 text areas in, 194
final keyword, in PHP, 103 writing in HTML, 111-115
Firefox browser, 7, 13 forms array, in document object,
DHTML and, 219, 220-221 188-189
Fireworks software, 15 Forms verification, 193-194
Fixed ranks, phpBB, 248 for videogame store Website, 232
Flash software, 15 <FORM> tag, 111-115
FLOAT data type document object and, 189
in MySQL, 143 Forums, with phpBB bulletin board,
in PHP, 63 52-53,247-249
Floating-point numbers, in MySQL forward () method, in history object, 186
strings, 142 fpassthru function, in PHP, 87
floor function, in PHP, 62. See also [puts function, in PHP, 87
Math.floor method FRAMEBORDER parameter, in
Flow of control, in PHP, 69, 77-83 </FRAME> tag, 42
focus() method, text areas in forms and, Frames
194 in HTML, 34, 36, 39-42
Folders JavaScript and, 197-200, 206
for Apache server, 48 name attribute for, 197-198
indexer/searcher and, 124-125 in OSI data link layer, 8
PHP and, 49-50, 89-90 <FRAMESET> tag, 39-41,198,199-200
with phpBB bulletin board, 52 <FRAME> tag, 40, 41, 198, 199-200
PHP file explorer and, 97-98, 123-124 fread function, in PHP, 87
for phpMyAdmin application, 51 FreeHand software, 15
for submitting MySQL queries, fromCharCode method, for JavaScript
160-161 strings, 178
Font attributes, with HTML, 30-31 fromElement function, in DHTML, 222
<FONT> tag, 28 FrontPage software, 15
attributes in, 30-31 fseek function, in PHP, 87
in cleaning up output, 131 ftell function, in PHP, 87
280 INDEX
password input type, for <INPUT> tag, interactive Websites with, 111-125
112 loops in, 58, 65, 80-82
Password parameter, for mysql_connect mathematical functions in, 61-63
method, 159 object-oriented programming with,
Passwords 101-110
in forms, 112 objects in, 58
with MySQL database, 50, 51 operators in, 61
with phpBB bulletin board, 52, 53 Perl-compatible regular expressions
with phpMyAdmin application, 51 in, 214-216
in PHP/MySQL login procedures, regular expressions in, 213-216
162-163 as server-side language, 25, 57-67
path attribute, for setcookie command, strings in, 90-96
118-119 syntax of, 58, 59, 60
Paths, URLs and, 18 variables in, 59-60, 64, 65-67
PCRE (Perl-compatible regular versions of, 57
expressions), 214-216 when to use, 234-235
Period (.), in FastTemplate append PHP5
parsing, 130 installation of, 48-50
Perl language, 23-24 object-oriented programming with,
regular expressions in, 214 101-110
Permissions, phpBB, 53, 248 phpBB bulletin board tool, 45
Phishing, 233 advanced features of, 247-249
PhotoShop software, 15 downloading, 46
PHP (Hypertext PreProcessor), 22, 25 installing, 52-54
arrays in, 69-77 PHP code
ASP.NET versus, 23 cleaning up, 127-135
classes in, 102-103 templates and, 127, 128-129, 129-131
comparisons in, 60 PHP engine, 45
conditions in, 58, 59, 60, 77-80 downloading, 46
connecting to MySQL server with, installing, 48-50
159-160 with phpBB bulletin board, 52
constants in, 59, 64-65 security for, 54
in creating Websites, 159-170 testing, 50
data types in, 63-64 PHP-GTK library, 22
exceptions in, 109-110 phpinfo() function, in PHP, 97
expressions in, 59-61 PHP methods, grouping in classes,
FastTemplate code in, 251-266 164-168
file explorer in, 97-98, 123-124 phpMyAdmin application, 45, 151-158
files in, 85-89 accessing tables with, 154
flow of control in, 69, 77-83 creating databases with, 151-152
folders in, 89-90 creating tables with, 152-154
functions in, 58, 59, 60-61, 82-83 creating Websites with, 159
HMTL and, 58 downloading, 46
HTML files and, 95-96 exporting/importing database
indexer/searcher in, 98-100, 124-125, structure and content with, 154-157
168-170 installing, 51-52
information functions in, 96-97 with phpBB bulletin board, 52
installing on UNIX, 241-243 PHP engine and, 49
instructions in, 58-61 when to use, 234
288 INDEX