Tải bản đầy đủ - 0trang
Chapter 18. Processing Web Input with MySQL
The previous chapter describes how to retrieve information from MySQL and display it in web
pages using various types of HTML constructs such as tables or hyperlinks. That's a use of
MySQL to send information in one direction (from web server to user), but web-based
database programming can also serve to collect information sent in the other direction from
user to web server, such as the contents of a submitted form. If you're processing a survey
form, you might store the information for later use. If the form contains search keywords,
you'd use them as the basis for a query that searches the database for information the user
wants to see.
MySQL comes into these activities in a fairly obvious way, as the repository for storing
information or as the source from which search results are drawn. But before you can process
input from a form, you have to create the form and send it to the user. MySQL can help with
this, too, because it's often possible to use information stored in your database to generate
form elements such as radio buttons, checkboxes, pop-up menus, or scrolling lists:
You can select a set of items from a table that lists countries, states, or provinces and
convert them into a pop-up menu for use in a form that collects address information.
You can use the list of legal values for an
ENUM column that contains allowable
salutations (Mr., Mrs., and so forth) to generate a set of radio buttons.
You can use lists of available colors, sizes, or styles stored in an inventory database to
construct fields for a clothing ordering form.
If you have an application that allows the user to pick a database or table, you can run
SHOW DATABASES or SHOW TABLES query and use the resulting names to
create a list element.
By using database content to generate form elements, you lessen the amount of table-specific
knowledge your programs must have and allow them to determine what they need
automatically. A script that uses a database to figure out for itself how to generate form
elements adaptively handles changes to the database. To add a new country, create a new
row in the table that stores the list of countries. To add a new salutation, change the definition
ENUM column. In each case, you change the set of items in a form element by
updating the database, not by modifying the script; the script adapts to the change
automatically, without additional programming.
The first part of this chapter covers the following topics relating to web input processing:
Generating forms and form elements.
One way to use database content for form construction is by selecting a list of items
from a table and using them to create the options in a list element. But metadata can
be used as well. There is a natural correspondence between
ENUM columns and
single-pick form elements like radio button sets or pop-up menus. In both cases, only
one from a set of possible values may be chosen. There is a similar correspondence
SET columns and multiple-pick elements like checkbox groups; any or all of
the possible values may be chosen. To construct metadata-based form elements,
obtain the column description from the table information returned by
COLUMNS, extract the set of possible values, and use them for the items in the form
Initializing forms using database contents.
In addition to using the database to create structural elements of forms, you can also
use it to initialize form field values. For example, to allow a user to modify an existing
record, retrieve it from the database and load it into an editing form's fields before
sending the form to the user.
Processing input gathered over the Web.
This includes input not only from form fields, but also the contents of uploaded files, or
parameters that are present in URLs. Regardless of where the information comes
from, you'll face a common set of issues in dealing with it: extracting and decoding the
information, performing constraint or validity checking on it, and re-encoding the
information for query construction to avoid generating malformed queries or storing
The second part of the chapter illustrates a few ways to apply the techniques developed in the
first part. These include applications that show how to use MySQL to present a web-based
search interface, create paged displays that contain next-page and previous-page links,
implement per-page hit counting and logging, and perform general Apache logging to a
For the Perl, PHP, and Python example scripts discussed in this chapter, look under the apache
directory of the
recipes distribution. For JSP, the scripts are under the tomcat directory;
you should already have installed these in the process of setting up the mcb application
context (Recipe 16.4). Library routines used by the example scripts are located in files found
under the lib directory. Scripts to create the tables used here are located in the tables
Note that although the scripts in this chapter are intended to be invoked from your browser
after they have been installed, many of them (JSP pages excepted) can also be invoked from
the command line if you wish to see the raw HTML they produce.
To provide a concrete context for discussion, many of the form-processing examples in this
chapter are based on the following scenario: in the lucrative field of "construct-a-cow"
business endeavors, you run an operation that manufactures build-to-order ceramic bovine
figurines, and you want to design an online ordering application that lets customers make
selections for several aspects of the product. For each order, it's necessary to collect several
types of information:
The particular list of colors available at any particular time changes occasionally, so for
flexibility, the values can be stored in a database table. To change the set of colors
that customers can choose from, just update the table.
There is a fixed set of sizes that doesn't change often (small, medium, large), so the
values can be represented as elements of an
The all-important cow accessory items.
These include a bell, horns, a sporty-looking tail ribbon, and a nose ring. Accessories
can be represented in a
SET column, because a customer may wish to select more
than one of them. In addition, you know from past experience that most customers
order horns and a cow bell, so it's reasonable to use those for the column's default
Customer name and address (street, city, state).
The possible state names are already stored in the
states table, so they can be
used as the basis for the corresponding form element.
Given the preceding discussion, a
cow_order table might be designed like this:
CREATE TABLE cow_order
INT UNSIGNED NOT NULL AUTO_INCREMENT,
# cow color, figurine size, and accessory items
ENUM('small','medium','large') DEFAULT 'medium',
accessories SET('cow bell','horns','nose ring','tail ribbon')
DEFAULT 'cow bell,horns',
# customer name, street, city, and state (abbreviation)
PRIMARY KEY (id)
id column provides a unique identifier for each record. It's a good idea to have such a
value, and in fact will be necessary when we get to Recipe 18.5, which shows how to use web
forms to edit existing records. For that type of activity, you must be able to tell which record
to update, which is difficult without a unique record identifier.
The list of available colors is maintained in a separate table,
CREATE TABLE cow_color
For purposes of illustration, assume that the color table looks like this:
| Black & White |
| Red & White
An application can use these tables to generate list elements in an order entry form, making it
unnecessary for the application to have a lot of specialized built-in knowledge about the
available options. The next several sections describe how to do this, and how to process the
input that you obtain when a user submits a form.
18.2 Creating Forms in Scripts
You want to write a script that gathers input from a user.
Create a fill-in form from within your script and send it to the user. The script can arrange to
have itself invoked again to process the form's contents when the user submits it.
Web forms are a convenient way to allow your visitors to submit information, for example, to
provide search keywords, a completed survey result, or a response to a questionnaire. Forms
are also beneficial for you as a developer because they provide a structured way to associate
data values with names by which to refer to them.
A form begins and ends with
tags. Between those tags, you can
place other HTML constructs, including special elements that become input fields in the page
that the browser displays. The
However, that won't work under some configurations of PHP, such as when the
register_globals setting is disabled. Another way to get the script path is to
access the "PHP_SELF" member of the $HTTP_SERVER_VARS array or (as of PHP
4.1) the $_SERVER array. Unfortunately, checking several different sources of information
is a lot of fooling around just to get the script pathname in a way that works reliably for
different versions and configurations of PHP, so a utility routine to get the path is useful. The
get_self_path( ), shows how to use $_SERVER if it's available
and fall back to $HTTP_SERVER_VARS or $PHP_SELF otherwise. The function thus
prefers the most recently introduced language features, but still works for scripts running
under older versions of PHP:
register_globals is discussed further in Recipe 18.6.
function get_self_path ( )
global $HTTP_SERVER_VARS, $PHP_SELF;
if (isset ($_SERVER["PHP_SELF"]))
$val = $_SERVER["PHP_SELF"];
else if (isset ($HTTP_SERVER_VARS["PHP_SELF"]))
$val = $HTTP_SERVER_VARS["PHP_SELF"];
$val = $PHP_SELF;
$HTTP_SERVER_VARS and $PHP_SELF are global variables, but must be declared
as such explicitly using the global keyword if used in a non-global scope (such as within a
function). $_SERVER is a "superglobal" array and is accessible in any scope without being
declared as global.
get_self_path( ) function is part of the Cookbook_Webutils.php library file
located in the lib directory of the recipes distribution. If you install that file in a directory
that PHP searches when looking for include files, a script can obtain its own pathname and use
it to generate a form as follows:
$self_path = get_self_path ( );
Python scripts can get the script pathname by importing the
os module and accessing the
SCRIPT_NAME member of the os.environ object:
In JSP pages, the request path is available through the implicit
request object that the
JSP processor makes available. Use that object's getRequestURI( ) method as
18.2.4 See Also
The examples in this section all have an empty body between the opening and closing form
tags. For a form to be useful, you'll need to create body elements that correspond to the types
of information that you want to obtain from users. It's possible to hardwire these elements
into a script, but Recipe 18.3 and Recipe 18.4 describe how MySQL can help you create the
elements on the fly based on information stored in your database.
18.3 Creating Single-Pick Form Elements from Database
A form needs to present a field that offers the user a set of options but allows only one of
them to be selected.
Use a single-pick list element. These include radio button sets, pop-up menus, and scrolling
Single-pick form elements allow you to present multiple choices from which a single option can
be selected. Our example involves several sets of single-pick choices:
The list of colors in the
cow_color table. These can be obtained with the following
mysql> SELECT color FROM cow_color ORDER BY color;
| Black & White |
| Red & White
Note that some of the colors contain a
& character, which is special in HTML. This
means they will need HTML-encoding when placed into list elements. (Actually, we'll
perform encoding for all the list elements in the form, but these values illustrate why
it's a good idea to get in that habit.)
The list of legal figurine sizes in the
size column of the cow_order table. The
column is represented as an
ENUM, so the possible values and the default value can
be obtained using SHOW COLUMNS:
mysql> SHOW COLUMNS FROM cow_order LIKE 'size'\G
*************************** 1. row ***************************
The list of state names and abbreviations. These are available from the
mysql> SELECT abbrev, name FROM states ORDER BY name;
| abbrev | name
The number of choices varies for each of these lists. As shown, there are 3 sizes, 7 colors, and
50 states. The size values are best represented as a set of radio buttons or a pop-up menu; a
scrolling list is unnecessary because the number of choices is small. The set of colors can
reasonably be displayed using any of the single-pick element types; it's small enough that a
set of radio buttons wouldn't take a lot of space, but large enough that you may want to allow
scrolling—particularly if you make additional colors available. The list of states is likely to have
more items than you'd want to present as a set of radio buttons, so it's most suitable for
presentation as a pop-up menu or scrolling list.
I will discuss the HTML syntax for these types of elements, then show how to generate them
from within scripts.
A group of radio buttons consists of
elements of type radio, all with
the same name attribute. Each element also includes a value attribute. A label to
display can be given after the
tag. To mark an item as the default initial
selection, add a checked attribute. The following radio button group displays the
possible cow figurine sizes, using checked to mark medium as the initially
A pop-up menu is a list enclosed within
each item in the menu enclosed within
The pop-up menu can be changed easily to a scrolling list; just add a
size attribute to the