⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch19_13.htm

📁 By Tom Christiansen and Nathan Torkington ISBN 1-56592-243-3 First Edition, published August 1998
💻 HTM
字号:
<HTML><HEAD><TITLE>Recipe 19.12. Writing a Multiscreen CGI Script (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen &amp; Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly &amp; Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:45:44Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="ch19_01.htm"TITLE="19. CGI Programming"><LINKREL="prev"HREF="ch19_12.htm"TITLE="19.11. Creating Sticky Widgets"><LINKREL="next"HREF="ch19_14.htm"TITLE="19.13. Saving a Form to a File or Mail Pipe"></HEAD><BODYBGCOLOR="#FFFFFF"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch19_12.htm"TITLE="19.11. Creating Sticky Widgets"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 19.11. Creating Sticky Widgets"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch19_01.htm"TITLE="19. CGI Programming"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch19_14.htm"TITLE="19.13. Saving a Form to a File or Mail Pipe"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 19.13. Saving a Form to a File or Mail Pipe"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch19-36190">19.12. Writing a Multiscreen CGI Script</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch19-pgfId-1328">Problem<ACLASS="indexterm"NAME="ch19-idx-1000005503-0"></A><ACLASS="indexterm"NAME="ch19-idx-1000005503-1"></A></A></H3><PCLASS="para">You want to write a single CGI script that can return several different pages to the browser. For instance, you want a single CGI script for administering a database of products. The script will be called to display the form to add a product, to process the add-product form, to display a list of products to delete, to process the delete-product form, to display a list of product to edit, to display a form of the product's attributes for the user to change, and to process the edit-product form. You can use these multiscreen CGI scripts to form an elementary <ACLASS="indexterm"NAME="ch19-idx-1000007382-0"></A>shopping-cart-type application.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch19-pgfId-1334">Solution</A></H3><PCLASS="para">Use a hidden field to encode the current screen.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch19-pgfId-1340">Discussion</A></H3><PCLASS="para">It is easy to generate sticky hidden fields with the CGI module. The <CODECLASS="literal">hidden</CODE><ACLASS="indexterm"NAME="ch19-idx-1000005509-0"></A> function returns HTML for a hidden widget and will use the widget's current value if you only give <CODECLASS="literal">hidden</CODE> the widget name:</P><PRECLASS="programlisting">use CGI qw(:standard);print hidden(&quot;bacon&quot;);</PRE><PCLASS="para">To determine which page ("display product list", "display all items in shopping cart", "confirm order") to display, use another hidden field. We'll call this one <CODECLASS="literal">.State</CODE> so it won't conflict with any field we might have called <CODECLASS="literal">State</CODE> (for instance, in credit card billing information). To let the user move from page to page, use submit buttons that set <CODECLASS="literal">.State</CODE> to the name of the page to go to. For instance, to make a button to take the user to the "Checkout" page, use:</P><PRECLASS="programlisting">    print submit(-NAME =&gt; &quot;.State&quot;, -VALUE =&gt; &quot;Checkout&quot;);</PRE><PCLASS="para">We wrap this in a function to make it easier to type:</P><PRECLASS="programlisting">sub to_page { return submit( -NAME =&gt; &quot;.State&quot;, -VALUE =&gt; shift ) }</PRE><PCLASS="para">To decide what code to display, check the <CODECLASS="literal">.State</CODE> parameter:</P><PRECLASS="programlisting">$page = param(&quot;.State&quot;) || &quot;Default&quot;;</PRE><PCLASS="para">Put the code to generate each page in separate subroutines. You could decide which subroutine to call with a long <CODECLASS="literal">if</CODE> ... <CODECLASS="literal">elsif</CODE> ... <CODECLASS="literal">elsif</CODE>:</P><PRECLASS="programlisting">if ($page eq &quot;Default&quot;) {    front_page();} elsif ($page eq &quot;Checkout&quot;) {    checkout();} else {    no_such_page();         # when we get a .State that doesn't exist}</PRE><PCLASS="para">This is tedious and clumsy. Instead use a hash that maps a page name to a subroutine. This is another strategy for implementing a C-style <CODECLASS="literal">switch</CODE><ACLASS="indexterm"NAME="ch19-idx-1000005595-0"></A> statement in Perl.</P><PRECLASS="programlisting">%States = (    'Default'     =&gt; \&amp;front_page,    'Shirt'       =&gt; \&amp;shirt,    'Sweater'     =&gt; \&amp;sweater,    'Checkout'    =&gt; \&amp;checkout,    'Card'        =&gt; \&amp;credit_card,    'Order'       =&gt; \&amp;order,    'Cancel'      =&gt; \&amp;front_page,);if ($States{$page}) {    $States{$page}-&gt;();   # call the correct subroutine } else {    no_such_page();}</PRE><PCLASS="para">Each page will have some persistent widgets. For instance, the page that lets the user order t-shirts will want the number of t-shirts to persist even when the user continues and orders shoes as well. We do this by calling the page-generating subroutines with a parameter that lets them know whether they're the active page. If they're not the active page, they should only send back hidden fields for any persistent data:</P><PRECLASS="programlisting">while (($state, $sub) = each %States) {    $sub-&gt;( $page eq $state );}</PRE><PCLASS="para">The <CODECLASS="literal">eq</CODE> comparison returns true if the page is the current page, and false if it isn't. The page-generating subroutine then looks like this:</P><PRECLASS="programlisting">sub t_shirt {    my $active = shift;    unless ($active) {        print hidden(&quot;size&quot;), hidden(&quot;color&quot;);        return;    }    print p(&quot;You want to buy a t-shirt?&quot;);    print p(&quot;Size: &quot;, popup_menu('size', [ qw(XL L M S XS) ]));    print p(&quot;Color:&quot;, popup_menu('color', [ qw(Black White) ]));    print p( to_page(&quot;Shoes&quot;), to_page(&quot;Checkout&quot;) );}</PRE><PCLASS="para">Because the subroutines all generate HTML, we have to print the HTTP header and start the HTML document and form before we call the subroutines. This lets us print a standard header and footer for all the pages, if we want. Here, we assume we have subroutines <CODECLASS="literal">standard_header</CODE> and <CODECLASS="literal">standard_footer</CODE> for printing the headers and footers:</P><PRECLASS="programlisting">print header(&quot;Program Title&quot;), start_html();print standard_header(), begin_form();while (($state, $sub) = each %States) {    $sub-&gt;( $page eq $state );}print standard_footer(), end_form(), end_html();</PRE><PCLASS="para">Don't make the mistake of encoding prices in the forms. Calculate prices based on the values of the hidden widgets, and sanity-check the information where you can. For example, compare against known products, to make sure they're not trying to order a burgundy XXXXXXL t-shirt.</P><PCLASS="para">Using hidden data is more robust than using cookies, because you can't rely on the browser supporting or accepting cookies. A full explanation is in <ACLASS="xref"HREF="ch19_11.htm"TITLE="Managing Cookies">Recipe 19.10</A>.</P><PCLASS="para">We show a simple shopping cart application as the program <EMCLASS="emphasis">chemiserie</EM> at the end of this chapter.<ACLASS="indexterm"NAME="ch19-idx-1000005505-0"></A><ACLASS="indexterm"NAME="ch19-idx-1000005505-1"></A></P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch19-pgfId-1468">See Also</A></H3><PCLASS="para">The documentation for the standard CGI module.</P></DIV></DIV><DIVCLASS="htmlnav"><P></P><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch19_12.htm"TITLE="19.11. Creating Sticky Widgets"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 19.11. Creating Sticky Widgets"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="book"HREF="index.htm"TITLE="Perl Cookbook"><IMGSRC="../gifs/txthome.gif"ALT="Perl Cookbook"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch19_14.htm"TITLE="19.13. Saving a Form to a File or Mail Pipe"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 19.13. Saving a Form to a File or Mail Pipe"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">19.11. Creating Sticky Widgets</TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="index"HREF="index/index.htm"TITLE="Book Index"><IMGSRC="../gifs/index.gif"ALT="Book Index"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228">19.13. Saving a Form to a File or Mail Pipe</TD></TR></TABLE><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><FONTSIZE="-1"></DIV<!-- LIBRARY NAV BAR --> <img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p> <a href="copyrght.htm">Copyright &copy; 2002</a> O'Reilly &amp; Associates. All rights reserved.</font> </p> <map name="library-map"> <area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map> </BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -