📄 ch23.htm
字号:
as she comes to the Web site. This session ID is then passed either
through the URL itself or through a hidden input field in a form.
<P>
By maintaining state in this way you avoid having to constantly
pass all of the customer data every time a new page is generated.
You can simply query the file containing the information about
the session for any data you need.
<P>
Session IDs are recorded in a file along with relevant information
and generally expire after a day or even after a few hours.
<H3><A NAME="HTTpcookies">HTTP Cookies</A></H3>
<P>
HTTP cookies are a way to maintain state through the browser itself,
even between sessions.
<H4><A NAME="CookieRecipes">Cookie Recipes</A></H4>
<P>
You can use the <TT><FONT FACE="Courier">Set-Cookie</FONT></TT>
call in two ways to establish a cookie with the browser visiting
your site: include it in the HTTP header information or use the
<TT><FONT FACE="Courier"><META HTTP-equiv></FONT></TT> tag.
<P>
Here is a code example that uses HTTP header information to set
cookies.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">print "HTTP/1.0 200 OK\n\rSet-Cookie:
";<BR>
print "cookie=";<BR>
<BR>
for (keys %input){<BR>
print "$_=$input{$_}&" unless $input{$_} eq $empty;
<BR>
}<BR>
print "; path=/; expires=09-Nov-99 GMT\n\r\n\r";</FONT></TT>
</BLOCKQUOTE>
<H3><A NAME="SettingCookieswithMETAHTTPequiv">Setting Cookies
with <TT><FONT SIZE=4 FACE="Courier"><META HTTP-equiv></FONT></TT></A>
</H3>
<P>
Using the <TT><FONT FACE="Courier"><META HTTP-equiv></FONT></TT>
tag, you can set cookies even without using CGI. All that is required
is including the <TT><FONT FACE="Courier">Set-Cookie</FONT></TT>
arguments within the <TT><FONT FACE="Courier"><HEAD></FONT></TT>
definition of your Web page.
<P>
<CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Caution</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
Many features are not universally supported among different Web browsers. At the time of this writing, <TT><FONT FACE="Courier"><META HTTP-equiv></FONT></TT> is not standard HTML and not universally supported. If you plan to use the <TT><FONT
FACE="Courier"><META HTTP-equiv></FONT></TT> tag to set cookies or any other nonstandard HTML tag, you should be careful to rigorously test your Web pages with any of the browsers you want to support.
</BLOCKQUOTE>
</TD></TR>
</TABLE></CENTER>
<P>
<P>
Here is a code example using <META HTTP-EQUIV> to set cookies.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">print "<HTML><HEAD>\n<META
HTTP-EQUIV=\"Set-Cookie\" ";<BR>
print "Content=\"cookie=";<BR>
<BR>
for (keys %input){<BR>
print "$_=$input{$_}&" unless $input{$_} eq $empty;
<BR>
}<BR>
print "; path=/; expires=09-Nov-99 GMT\">\n";
<BR>
}<BR>
else {<BR>
print "<HTML><HEAD>\n";</FONT></TT>
</BLOCKQUOTE>
<H3><A NAME="BuildingCustomerProfiles">Building Customer Profiles</A>
</H3>
<P>
Using either client-side cookies or <TT><FONT FACE="Courier">.htaccess</FONT></TT>,
it becomes very simple to store data about your customers. The
uses for this information include the following:
<UL>
<LI><FONT COLOR=#000000>Saving customers from having to re-enter
vital information every time they shop</FONT>
<LI><FONT COLOR=#000000>Offering special deals to customers who
deal in high volumes</FONT>
<LI><FONT COLOR=#000000>Customizing your shopping cart to the
areas that each customer uses most frequently</FONT>
</UL>
<P>
With either the cookies or the <TT><FONT FACE="Courier">htaccess</FONT></TT>
method, each customer should have a unique identifier. In the
case of <TT><FONT FACE="Courier">.htaccess</FONT></TT>, this is
their login name, and in the case of cookies, it can be whatever
you decide.
<P>
Here's a sample customer profile (<TT><FONT FACE="Courier">cust127.profile</FONT></TT>):
<P>
<TT><FONT FACE="Courier">alias:cust127<BR>
name:Maggie O'Connell<BR>
address:121 Sycamore Rd.<BR>
city:Cicely<BR>
state:Alaska<BR>
</FONT><FONT COLOR=#000000 FACE="Courier">zip code:90210</FONT></TT>
<H2><A NAME="DatabaseManagement"><FONT SIZE=5 COLOR=#FF0000>Database
Management</FONT></A></H2>
<P>
Although the goal of shopping carts is to provide a sophisticated
means of interacting with the consumer, a sophisticated shopping
cart system integrated into a real database back end can make
life simpler for both customer and company. With true database
integration, it's possible to add and delete new products quickly,
change prices, keep track of inventory, and so on. If there is
already a database with this information available, it should
be built into the overall scheme of your shopping cart implementation.
<H3><A NAME="UsingDBMs">Using DBMs</A></H3>
<P>
To those familiar with working with databases on UNIX systems,
DBM files should be old news. I mention them here specifically
in order to discuss the way that Perl handles DBMs. To those who
are not familiar with DBMs, this brief discussion could also prove
useful, if only for future reference.
<P>
In Perl, it is reasonably simple to turn an entire DBM file into
an associative array, editing both the array and the DBM at the
same time.
<P>
Here is an example of how to print the contents of a DBM file
with Perl. The file that is being opened is an inventory DBM located
in the directory <TT><FONT FACE="Courier">files, and the file
is being opened into an associative array called INVENTORY</FONT></TT>.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">dbmopen (%INVENTORY, '/files/inventory');
<BR>
while(($key, $val) = each %INVENTORY) {<BR>
print "$key = $val";<BR>
</FONT></TT>}<BR>
<TT><FONT FACE="Courier">dbmclose (INVENTORY);</FONT></TT>
</BLOCKQUOTE>
<P>
Using DMBs allows you to manipulate and extract information from
large files without having to know the specific structure of the
file itself. If DBM and NDBM (New Data Base Management) are available
on your system, I highly recommend you become familiar with their
use.
<H2><A NAME="TheResultofYourLaborscartcgi"><FONT SIZE=5 COLOR=#FF0000>The
Result of Your Labors, cart.cgi</FONT></A></H2>
<P>
The program listed here is a simple shopping cart with two pages
of products. The information for the products is contained in
the file <TT><FONT FACE="Courier">catalog.txt. </FONT></TT>The<TT><FONT FACE="Courier">
</FONT></TT>program outputs HTML pages, including forms with hidden
fields containing the current state of the shopping cart. This
program produces either the cart contents page or a list of products
for sale, or it mails the order depending on how the form was
submitted<TT><FONT FACE="Courier">.<BR>
</FONT></TT>
<HR>
<BLOCKQUOTE>
<B>Listing 23.4. cart.cgi: A simple shopping cart using hidden
fields to transmit state.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">#!/usr/bin/perl<BR>
print "Content-type: text/html\n\n";<BR>
<BR>
# Simple Shopping Cart Using Hidden Fields to Transmit State<BR>
<BR>
# Set Variables<BR>
<BR>
$mailto="ken.hunt\@anadas.com";<BR>
$filename="catalog.txt";<BR>
$;=";";<BR>
$empty="";<BR>
$taxrate=.07;<BR>
<BR>
# Determine Method and Get Input<BR>
<BR>
if($ENV{'REQUEST_METHOD'} eq "GET") {<BR>
$input = $ENV{'QUERY_STRING'};<BR>
}<BR>
elsif ($ENV{'REQUEST_METHOD'} eq "POST") {<BR>
read(STDIN,$input,$ENV{'CONTENT_LENGTH'});<BR>
}<BR>
else {<BR>
print('Request method Unknown');<BR>
exit;<BR>
}<BR>
<BR>
# Remove URL encoding and place input in two-dimensional associative
array.<BR>
<BR>
@input = split (/&/,$input);<BR>
foreach $i (0 .. $#input) {<BR>
$input[$i] =~ s/\+/ /g;<BR>
$input[$i] =~ s/%(..)/pack("c",hex($1))/ge;
<BR>
($name, $value) = split(/=/,$input[$i],2);<BR>
($item, $variable) = split (/ /,$name);<BR>
$input{$item, $variable} = $value;<BR>
}<BR>
<BR>
# Hidden form input variable names have been "pre-pended"
with "old"<BR>
# To distinguish them from current input. This loop adds previously
<BR>
# "added" quantities to the currently ordered quantity.
<BR>
<BR>
foreach (sort keys %input) {<BR>
($item, $variable) = $_ =~ /^(\w+);(\w+)/;<BR>
if ($item =~ /old/) {<BR>
$currentitem = $item;<BR>
$currentitem =~ s/old//g;<BR>
unless (defined ($input{$currentitem, add}))
{<BR>
$input{$currentitem, add} = "on";
<BR>
$input{$currentitem, qty} = 0;<BR>
}<BR>
$input{$currentitem, qty} =<BR>
int($input{$currentitem, qty}
+ $input{$item, qty})<BR>
if ($olditem ne
$item);<BR>
$input{$item, add} = "off";<BR>
$olditem = $item;<BR>
}<BR>
}<BR>
<BR>
<BR>
<BR>
# This loop adds items to the order and removes deleted items.
<BR>
foreach (sort keys %input){<BR>
($item, $variable) = $_ =~ /^(\w+);(\w+)/;<BR>
$input{$item, add} = "off" if defined $input{$item,
del};<BR>
$input{$item, qty} = $empty if defined $input{$item,
del};<BR>
$input{$item, add} = "off" if ($input{$item,
qty} <= 0) ;<BR>
if ($variable eq "add") {<BR>
push (@orderlist, $item) if ($input{$item,
add} eq "on");<BR>
}<BR>
}<BR>
<BR>
# Get Product Descriptions<BR>
&readproducts;<BR>
<BR>
# Generate HTML and exit if a shopping page has been selected.
<BR>
&pageone if ($input{button,$empty} eq "Page One");
<BR>
&pagetwo if ($input{button,$empty} eq "Page Two");
<BR>
<BR>
# Mail the Order if the customer has selected that option.<BR>
& mailorder(@orderlist) if ($input{button,$empty} eq "Place
this Order");<BR>
<BR>
# Print the HTML header for the Cart Contents page.<BR>
&cartheader;<BR>
<BR>
# Display the current order, if there is an order.<BR>
if ($#orderlist > -1) {<BR>
<BR>
# Table Header<BR>
print "<tr><th>Qty.</th><th>Item</th><th>Price</th>";
<BR>
print "<th>Item Total</th><th>Put<br>Back</th></tr>\n";
<BR>
<BR>
# Order Body<BR>
foreach (@orderlist){<BR>
($name, $price) = split (/@/,$iteminfo{$_});<BR>
$input {$_, qty} = int ($input{$_, qty});<BR>
print "<tr><td align=right>$input{$_,
qty}</td><td>$name</td>";<BR>
print "<td align=right>\$$price</td>";
<BR>
$itemtotal = $price * $input{$_, qty};<BR>
$subtotal = $subtotal + $itemtotal;<BR>
printf "<td align=right>\$%4.2f</td>",
$itemtotal;<BR>
print "<td align=center><INPUT TYPE=checkbox
name=\"$_ del\"></td>";<BR>
print "</tr>\n";<BR>
}<BR>
<BR>
# Display Subtotal, Tax and Grandtotal for the order.<BR>
print "<tr><td colspan=3 align=right><font
size=+1>Subtotal:</font></td>";<BR>
printf "<td align=right><font size=+1>\$%4.2f</font></td>",
$subtotal;<BR>
print "</tr>";<BR>
print "<tr><td colspan=3 align=right><font
size=+1>Tax:</font></td>";<BR>
$tax = $subtotal * $taxrate;<BR>
printf "<td align=right><font size=+1>\$%4.2f</font></td>",
$tax;<BR>
print "</tr>";<BR>
$grandtotal = $subtotal + $tax;<BR>
print "<tr><td colspan=3 align=right><font
size=+1>Total:</font></td>";<BR>
printf "<td align=right><font size=+1>\$%4.2f</font></td>",
$grandtotal;<BR>
print "</tr>";<BR>
}<BR>
<BR>
# If there is no current order display the empty cart.<BR>
else{<BR>
print <<EOT;<BR>
<tr><td align=center><BR>
<font size=+2>Your Cart is Empty.</font><br>
<BR>
We have two pages of great products to choose from,<br>
<BR>
so go fill up your cart.<BR>
</td></tr><BR>
EOT<BR>
}<BR>
<BR>
# Print the HTML footer for the Cart contents page and exit<BR>
& cartfooter;<BR>
exit 0;<BR>
<BR>
# *** SUBROUTINES ***<BR>
<BR>
# Read the Product information from a file. Fields are separated
by tabs<BR>
# Records are separated by newline.<BR>
sub readproducts {<BR>
open (PRODUCTS, $filename);<BR>
while (<PRODUCTS>) {<BR>
($code, $name, $price) = split (/\t/);<BR>
$iteminfo{$code} = "$name\@$price";<BR>
}<BR>
}<BR>
<BR>
# Produce the HTML for Page One of Product listings<BR>
sub pageone {<BR>
<BR>
@itemlist = ("T", "hat", "keychain",
"mousepad");<BR>
$gobutton = "Page Two";<BR>
&printheader;<BR>
&makehidden;<BR>
&printbody (@itemlist);<BR>
&printfooter ($gobutton);<BR>
exit 1;<BR>
}<BR>
<BR>
#Produce the HTML for Page Two of product listings.<BR>
sub pagetwo {<BR>
<BR>
@itemlist = ("bball", "plate", "coaster",
"nitelite");<BR>
$gobutton = "Page One";<BR>
&printheader;<BR>
&makehidden;<BR>
&printbody (@itemlist);<BR>
&printfooter ($gobutton);<BR>
exit 2;<BR>
}<BR>
<BR>
# The HTML header for both products page is the same.<BR>
sub printheader {<BR>
<BR>
print <<EOT;<BR>
<HTML><HEAD><BR>
<TITLE>CGI Unleashed Accessory Depot</TITLE><BR>
</HEAD><BR>
<BR>
<BODY bgcolor="#FFFFFF"><BR>
<CENTER><BR>
<H2>CGI Programming Unleashed<br>Accessory Depot</H2>
<BR>
</CENTER><BR>
<BR>
<FORM METHOD=post ACTION=cart.cgi><BR>
<TABLE width=100% border><BR>
<TR><TH>Qty.</TH><TH>+/-<br>Qty.</TH>
<BR>
<TH>Item</TH><TH>Price</TH><TH>Add<br>to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -