negzero7 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Perl Monks!

I am working on a project that wants to use an HTML form to read in an order for pizza, and then use a cgi script to output the entered information onto another HTML page.

I have made good progress and my script does what it is suppose to except one thing, it is supposed to be able to read in multiple orders and then output all of them. So far, I can only do one order at a time, and I'm not sure how to make it do multiple orders.

You can view the HTML page and script in action so far if you visit http://nova.umuc.edu/~cm375a20/order_pizza.html . Once you submit my script should do it's magic for oone order.

Here is my script, please take a look and see if you can see a way to incorporate multiple orders.

#!/usr/local/bin/perl #Get the submitted data $content_length = $ENV{'CONTENT_LENGTH'}; #Read user data into script variable read (STDIN, $form_data, $content_length); $form_data =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack("C",hex($1))/eg; $form_data =~ s/\+/ /g; @fields = split (/&/, $form_data); #Init script variables with form data values #$form_name is the name of the form. #from the text fields... ($Pizza, $name) = split (/=/, $fields[0]); ($Pizza, $address) = split (/=/, $fields[1]); ($Pizza, $phone) = split (/=/, $fields[2]); ($Pizza, $pizzas) = split (/=/, $fields[3]); ($Pizza, $instructions) = split (/=/, $fields[4]); #from the radio button... ($Pizza, $size) = split (/=/, $fields[5]); #set up variables for the three check boxes. ($cheese, $pepperoni, $sausage) = (0, 0, 0); foreach $type (@fields) { if ($type =~ /cheese/i) { $cheese = 1; } if ($type =~ /pepperoni/i) { $pepperoni = 1; } elsif ($type =~ /sausage/i) { $sausage = 1; } } #Set toppings to be printed out if ($cheese == 1) {@topping[0] = Cheese;} if ($pepperoni == 1) {@topping[1] = Pepperoni;} if ($sausage == 1) {@topping[2] = Sausage;} #Set price if ($size =~ /small/i) {$price = 6.99;} if ($size =~ /medium/i) {$price = 9.99;} elsif ($size =~ /large/i) {$price = 12.99;} #Find Total $total = $price * $pizzas; #Send back to the user a confirmation print << "END_OF_REPLY"; Content-type: text/html <HTML> <HEAD> <TITLE>Confirmation Message</TITLE> </HEAD> <BODY> <p><font size="10">Thanks for Your Order!</font></p> <p><font size="5px" face="Verdana">Please check the following for accuracy.</font></p> Your Name: $name<br> Your Address: $address <br> Your Telephone: $phone <br> <br> Special Instructions: $instructions <br> <br> Here is a summary of your order: <br> # of Pizzas: $pizzas <br> Toppings: @topping <br> Size: $size <br> Price per Pizza: \$$price <br> <hr align="left" width="25%"><br> Total: \$$total </BODY> </HTML> END_OF_REPLY

Also, the only thing for multiple orders is where it prints out the info about the pizza like size, toppings etc.

Replies are listed 'Best First'.
Re: CGI script help
by CountZero (Bishop) on May 11, 2008 at 18:49 UTC
    I see you are doing this the hard way and that you are fond of reinventing wheels.

    CGI is a module that takes care of all the GET-ing and POST-ing of parameters and can make and read all your forms and their elements. It is definitely something worth looking into.

    Now for your question, I see a few possible solutions:

    1. You loop your script rather than using it once only. Every time you summarize the previous order(s) and you allow the user to add a new order. Only when he pushes the "I'm done ordering!" button, you go to the final screen.
    2. You use AJAX and dynamically add lines to your webpage for ordering more pizzas. Modules such as CGI::Ajax, HTML::AjaxTags, JQuery or OpenThought (it has a restaurant demo, which you might find inspiring) or ... can make this easy. For more info on AJAX go here.

    And of course, add use strict; and use warnings; to all your code.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Looks like a homework constraint
        Well the .edu in http://nova.umuc.edu/~cm375a20/order_pizza.html is a dead giveaway, isn't?

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: CGI script help
by psini (Deacon) on May 11, 2008 at 18:32 UTC

    Sorry I don't understand. As long as I can see your script runs fine. To allow users generating multiple orders you should change the user interface, not the script behind

    If this is what you want, I think that a couple of button "Add to your order" and "process order" in the response page could do the trick.

    The first button could resend the first page with a hidden field containing a serialized version of the order so far (this is a shortcut, better way would be mantaining a session server-side with the content of the user "cart").

    The second button would confirm the order as entered (sum of all the single entry)

    PS. Remember to be careful using serialized data in a HTML page. The most obvious way of serialize through Data::Dumper and deserialize with eval open the road to code injection when used on the internet! You should always be aware that anybody can put anything in your hidden fields, and avoid the possibility of exploitation

Re: CGI script help
by pc88mxer (Vicar) on May 12, 2008 at 05:03 UTC
    it is supposed to be able to read in multiple orders and then output all of them. So far, I can only do one order at a time, and I'm not sure how to make it do multiple orders.
    You need to store the order data someplace between page calls. Here are some of the standard techniques that are used with web applications:
    1. Store the data in a database (like mysql, sqlite, Oracle, etc.)
    2. Store the data in a file on the server.
    3. Store the data as client cookies.
    4. Store the data as form variables which get continually passed between the pages.
    The basic idea is that your CGI script will consult the datastore (whichever one you decide to use) for the old order data, add the new order data passed in via form variables and then store everything back out to the datastore so it's ready for the next call to the CGI script.

    Since this looks like a class assignment, you might see if the instructor has given any indication of a preferred way to do this. For instance, if this is an intro web programming class, I doubt you will be expected to learn how to interact with a database since that would take up a lot of time that could be used to introduce a lot of other concepts. On the other hand, if the class has already covered how to interact with databases, perhaps that's the approach you should pursue.

Re: CGI script help
by toolic (Bishop) on May 13, 2008 at 00:22 UTC
    I realize this does not answer your question, but I would like to suggest an improvement to the way in which you populate the @toppings array. The following code:
    • Eliminates warnings of the type "Scalar value @topping[0] better written as $topping[0]" when you use warnings;
    • Eliminates compiler errors of the type "Bareword "Cheese" not allowed while "strict subs" in use" when you use strict;
    • Replaces N scalar variables with 1 hash. In your case, N=3; but N would grow as you add onions, mushrooms, etc. $cheese, $pepperoni and $sausage are replaced by %types.
    • Reduces the number of lines of code by about 50% as N grows.
    my %types; for (@fields) { $types{Cheese}++ if /cheese/i; $types{Pepperoni}++ if /pepperoni/i; $types{Sausage}++ if /sausage/i; } my @toppings = sort keys %types;
Re: CGI script help
by leocharre (Priest) on May 12, 2008 at 23:56 UTC

    As expressed by fellow monks- this seems like homework.

    Aside of whether it is or not- you may actually want to solve the problem for yourself out of curiosity or interest- not just for a grade.

    If you want to solve the problem- I suggest you set aside the code, get some pencil and paper.

    Forget perl. Think of what an 'order' is. Think of it perhaps as a data structure, or a set of steps. Each of which may or may not be complete.

    Think of orders as some concept you can take out of and put back into a bag. Try to separate the problems and create in your thinking a hierarchy of what is what.
    You analize one order at a time, change it, etc.- Put it back in the bag. Be vague.

    Look at GGI::Session.. Find a way to store an array of 'orders' in a CGI::Session object.

Re: CGI script help
by Starky (Chaplain) on May 15, 2008 at 14:57 UTC
    On a related note, you might enjoy taking a look at Pizza Party, which allows you to order a Domino's pizza from the command line. Really.

    The Pizza Party script is, as you might imagine, written in Perl.