Jump to content
Larry Ullman's Book Forums

Same-Page Shopping Cart


Recommended Posts

Hello - I would love some guidance here. The book redirects the user from sales page to a separate shopping cart page, but I'd like to create a mini same-page shopping cart page with a dynamic subtotal on the bottom of the page. More specifically, I'd like to create simple subtotal box that autopopulates quantity and price based on options the user have made. So, if a user selects quantity of "3" and then selects goods that are worth "$30", then on the same page at the bottom, it should dynamically show text as "quantity:3", "price per product: $30", and "subtotal: "$90."

Here's the HTML I've been working with to select options of quantity and price. Both will have values which will dynamically be populated based on some javascript and PHP written beforehand, hence each only has one option value. I've been trying to "call" the id of each options but I can't seem to get a value or text. Thank you in advance for your help!

 

<pre><code>

<!--*define quantity-->

<h3><a href="#"><b>3. Select quantity</b></a></h3>

<div>

<select name="quantity" id="quantity">

<option value ="">Select a Number</option>

</select>

</div>

 

<!--*define product-->

<h3><a href="#"><b>4. Select product</b></a></h3>

<div>

<select name="product" id="product">

<option value ="">Select Product</option>

</select>

</div>

</code></pre>

Link to comment
Share on other sites

The main thing is that you need to have the select elements within a form. Also, you need to use JavaScript to detect changes to the select elements, and then add up the numbers accordingly.

 

Below is a sample script that does what I think you're asking for. The first half of the script autogenerates the select elements and options and the second half uses events to detect a change in a select element and retally the total accordingly.

 

Please note that my code is very sloppy and rudimentary, but I just wanted to make the concept itself clear. Hope this helps.

 

<!DOCTYPE html>

<html lang="en">

 <head>

   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

   <title>Getting values from select elements</title>

   <style type="text/css">

     label {

       display: block;

       float: left;

       width: 110px;

     }

   </style>

 </head>

 <body>

   <form method="#" action="#"></form>

   <div id="total"></div>

   <script>

     // Use JS to autopopulate the drop-down lists.

     var i,
         quanOptions = '<p><label for="quantity">Select a quantity:</label><select name="quantity" id="quantity">',
         priceOptions = '<p><label for="price">Select a price:</label><select name="price" id="price">';

     for (i = 1; i <= 50; i++) {

       quanOptions += '<option>' + i + '</option>';

       priceOptions += '<option>' + i + '</option>';

     }

     quanOptions += '</select></p>';

     priceOptions += '</select></p>';

     document.forms[0].innerHTML = quanOptions + priceOptions;

     // Set up events to capture the select tag values.

     var quantity = 1,
         price = 1,
         total = 0;

     document.forms[0].quantity.onchange = function () {

       quantity = parseInt(this.options[this.selectedIndex].innerHTML);

       total = quantity * price;

       document.getElementById('total').innerHTML = '$' + total;

     };

     document.forms[0].price.onchange = function () {

       price = parseInt(this.options[this.selectedIndex].innerHTML);

       total = quantity * price;

       document.getElementById('total').innerHTML = '$' + total;

     };

   </script>

 </body>

</html>

 

Edit: The JS used to grab the select element values is for IE6 (i.e., old Internet Explorer). The process is much simpler for modern browsers. Please see an appropriate resource.

Link to comment
Share on other sites

Just a note - layering your application with JS to improve the user experience is fine but it should not replace proper server side validation of the shopping cart prior to checkout to ensure malicious users haven't manipulated prices etc...

Link to comment
Share on other sites

Yes, that is true. I more or less just wanted to show him how to display things.

 

JS can be used for basic validation though, to save on server calls.

 

Thank you very much HartleySan! What you wrote out is exactly what I was looking for, except I'd appreciate your guidance on a couple of more things:

1) Rather than using javascript to autopopulate, is there a way I can use php to "fetch" data from the database to autopopulate?

2) I'm most interested in learning how the selected value can be shown in a text box - for instance, after selecting "2" under quantity, there's text box called quantity which dynamically shows "2" again. and then another text box underneath that shows selected price. And then a third box at the bottom that does "subtotal" and then shows the multiplication...

 

Thank you so much!

Link to comment
Share on other sites

To answer your first question, PHP can very easily be used to autopopulate a drop-down menu. In fact, it's much easier than JS, I think, and more effective, because you have access to a databases, etc. Larry talks about this extensively in his PHP 6 & MySQL 5 book, which is a great intro to both languages and a great primer to the e-commerce book.

 

The basic flow in PHP is something like the following:

 

echo '<select>';

for ($i = 0; i < something; i++) {

 echo '<option>' . value . '</option>';

}

echo '</select>';

 

As for your second question, it's a matter of combining both PHP and JS. If what a user chooses has no effect on later choices, then you can simply use PHP when necessary and JS when necessary to create the desired effect. However, if a selected choice will affect later choices, then you're getting into Ajax, which again, Larry has a great book about.

 

Hope that helps.

Link to comment
Share on other sites

Hello - Thank you for your reply and help again. As you suggested in parts of your response, I decided to use php to autopopulate options and the post method (at least until I learn Ajax) to capture the value of the selected options. But now I'm stuck in a different way and, if you wouldn't mind, would appreciate your insight once more.

I am building a website that lists meals and price per meal. So each meal has its own unique price. I've laid out the options below and the problem I now have is to separate the meal and price from each other when I do $_POST["menus"]. I can't seem to figure out how to separate the meal from the price as POST captures the entire selected value. Any idea?

 

<form action="views/checktest.php" method="post" name="shopcart" id="shopcart">

<select name="menus">

<option> Select your meal here </option>

<option> '.$row['meal1'].' at '.$row['meal_price1'].' </option>

<option> '.$row['meal2'].' at '.$row['meal_price2'].'</option>

<option> '.$row['meal3'].' at '.$row['meal_price3'].'</option>

</select>

<input type ="submit"/>

</form>

 

Then once submitted, checktest.php has the following codes which conjoin the price and the meal when I need them separated

<p>You selected <?php echo $_POST["menus"]; ?>!</p><br />

 

Thank you!

Link to comment
Share on other sites

I suppose there are two possibilities:

 

1) You could divide up the information differently, so that the prices are not in the options. This would involve using JS akin to what we talked about before; changing the price when the onchange event fires for the select element. As an item is selected, you could put the price in a hidden input that is submitted with the form.

 

2) Use a regex (regular expression). This is the more immediate fix, but it requires knowledge of regexes. People (including myself at one time) tend to shy away from regexes 'cause "they're hard". Nevertheless, they're very useful.

 

If necessary, here's a great primer on regexes:

 

http://www.regular-expressions.info/tutorial.html

 

And here's the specific PHP function you'll want to use:

 

http://php.net/manual/en/function.preg-match.php

("preg" is short for "Perl regular expression".)

 

In your case, the regex is relatively simple. From the views/checktest.php script, you'd do something like the following:

 

$meal_and_price = $_POST['menus']; // Don't forget to validate the posted value as necessary.

$regex = '/(.+) at (.+)/';

preg_match($regex, $meal_and_price, $matches);

 

Now, let's imagine an example:

 

If $meal_and_price contains the string 'Potato salad at $3.99', then the $matches array will contain the following data:

 

$matches[0]: Potato salad at $3.99
$matches[1]: Potato salad
$matches[2]: $3.99

 

Once you have that data, I'm sure the rest is pretty straightforward. Note that the regex I used is just one way of getting the necessary data. Good luck.

Link to comment
Share on other sites

Just my 2c. but I'd approach it slightly differently. You're creating the dropdown off the array returned from your database so just use the meal ID from the database to assign to the option value like:

 

echo '<option value="' . $row['meal1_id'] . '">' . $row['meal1'] . ' at $' . $row['meal_price1'] . '</option>';

 

Then server side use the ID returned to re-query the database to get the price. This way if the price calculated meant anything (e.g. allowed someone to order meals) they couldn't alter the price charged.

 

As a side note it also looks like you're storing the price alongside with the currency symbol? If so then I think best practice would be to remove that - storing just the numbers allows you to perform math of them. E.G. All prices increasing 10%, converting to another currency for multi-national site and forcing the correct format are all easier to do.

Link to comment
Share on other sites

Stuart, you make a good point about not adding the currency symbol to the prices. I actually should have accounted for that in my regex as well. I think the following would be a better regex:

 

$regex = '/(.+) at \$(.+)/';

 

Note that you have to escape the dollar sign, since it has a special meaning in regexes.

 

As for querying the database again, that seems unnecessary. The regex will more than suffice and be faster than querying the DB again. Also, I don't see how a customer would be able to alter the price from their side.

 

Well, there are multiple ways of dealing with this, but perhaps the best is to simply restructure the way the data is presented.

Link to comment
Share on other sites

WHOO HOO! Thank you very much Hartleysan and Stuart! I took all that you've suggested above and was able to FINALLY end this nightmarish problem I've been trying to resolve for days now! I actually skipped the chapter Larry had about regex in his php book but after reading your suggestion above, Hartleysan, I read it and it makes a lot of sense now. Your codes worked beautifully! Thanks so much!

Link to comment
Share on other sites

So I guess the alias skim5 isn't just a clever name, huh? Just kidding. Glad to hear you got it working.

 

I also didn't read Larry's regex chapter (or anything else about regexes, for that matter) for the longest time. I finally decided to learn about regexes when I got to the point that they were essential and I could no longer deny the power they have.

 

In general, whenever you want to parse a string a certain way, regexes are the answer. Sometimes, it's better (faster) to use a function built in to PHP, if the function does exactly what you want. However, if there isn't a function to do what you want, then regexes are the solution.

 

Good luck with everything.

Link to comment
Share on other sites

Just for completeness let me explain re: changing the price submitted from the client side. It would be relatively easy - in it's simplest form create a HTML page with the same structure and form action as the page in question and simply alter the prices. I guess this attack would be foiled by the use of a form nonce however intercepting a HTTP request with a proxy like BURP, modifying and submitting it would also be pretty straight-forward. Again if these prices aren't part of a e-commerce system it's not a major consideration.

Link to comment
Share on other sites

 Share

×
×
  • Create New...