Link to home
Start Free TrialLog in
Avatar of LezlyPrime
LezlyPrimeFlag for United States of America

asked on

PHP: reload page adds quantity to cart

I am an experienced .NET programmer learning PHP. The project I'm working on is a pizza shop menu where the user can create a custom pizza & add it to the cart.  

When the user clicks the Add to Cart button, which is on the menu page, the add_item function is called & one new item is added to the cart. The user is redirected to the cart page, using the include function.

include('cart_view.php');

At this point, if the user reloads the page (F5), the quantity of the item is increased by one. The browsers even warn about this. I've searched the Internet & I believe the header function is the solution, but I don't know where to place it or what to check for, to make it work.

header('Location: cart_view.php');

If I put it after the add_item function, (where the include function currently is) the cart page displays, but with zero items in the cart. But if you go back to the menu page & click on the cart button, which calls the show_cart function, the items are in the cart.

Thanks in advance for any help or suggestions.
Avatar of Kim Walker
Kim Walker
Flag of United States of America image

I'm not getting the picture here. When the user clicks the Add to Cart button, I'm assuming a form is being submitted or some javascript is being executed which sends the pizza configuration to a PHP page which returns a page with the cart contents. How is the pizza configuration being passed to the cart? If you are using a query string or form to send the configuration, refreshing the page will resend the query string or form and would indeed add another pizza. Can you be more specific?
ASKER CERTIFIED SOLUTION
Avatar of Dave Baldwin
Dave Baldwin
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I'll have to look into this further tomorrow unless another expert is able to comment sooner. But I think the problem is in the include method. It doesn't redirect. It's more of an insert. It embeds the contents of the other file in the current file. This much I'm sure of. When I need to redirect, I usually return an HTML shell page with a refresh meta tag. But there may be a better way.
Buy these books.  It will help a lot with the ways of thinking that PHP programmers use.  Your experience will enable you to read these and make progress very quickly.
http://www.sitepoint.com/books/phpmysql4/
http://www.amazon.com/PHP-5-Practice-Elliott-White/dp/0672328887

A teaching example of the solution to prevent multiple submits of the same data is shown in the code snippet.  You can copy it and install it on your own machines, or test it on my server here.
http://www.laprbass.com/RAY_multi_submit.php

Best of luck with your studies, ~Ray
<?php // RAY_multi_submit.php
error_reporting(E_ALL);


// PREVENT MULTIPLE SUBMISSIONS DUE TO REPEATED REFRESH, CLICKS ON SUBMIT BUTTON OR FIRING THE BACK BUTTON
// EXAMPLE:
//    if ( multi_submit() )
//    {
//       handle error
//    }
//    else
//    {
//       normal processing
//    }


// ALWAYS START THE PHP SESSION ON EVERY PAGE
session_start();



// A FUNCTION TO RETURN TRUE OR FALSE ABOUT MULTI-SUBMIT CONDITIONS
function multi_submit($type="POST")
{
    // MAKE THE FUNCTION WORK FOR EITHER GET OR POST SUBMITS
    $input_array = (strtoupper($type) == "GET") ? $_GET : $_POST;

    // GATHER THE CONTENTS OF ALL THE SUBMITTED FIELDS AND MAKE A MESSAGE DIGEST
    $string = NULL;
    foreach ($input_array as $val)
    {
        // CONCATENATE ALL SUBMITTED VALUES
        $string .= $val;
    }
    $string = md5($string);

    // IF THE SESSION VARIABLE IS NOT SET THIS IS NOT A MULTI-SUBMIT
    if (!isset($_SESSION["_multi_submit"]))
    {
        // SAVE THE SUBMITTED DATA MESSAGE DIGEST
        $_SESSION['_multi_submit'] = $string;
        return FALSE;
    }

    // IF THE SESSION DATA MATCHES THE MESSAGE DIGEST THIS IS A MULTI-SUBMIT
    if ($_SESSION['_multi_submit'] === $string)
    {
        return TRUE;
    }
    else
    {
        // SAVE THE MESSAGE DIGEST TO DETECT FUTURE MULTI-SUBMIT
        $_SESSION['_multi_submit'] = $string;
        return FALSE;
    }
}



// SHOW HOW THIS IS DONE
if (!empty($_POST))
{
    if (multi_submit())
    {
        die("ALREADY GOT THAT");
    }
}



// CREATE THE FORM FOR THE DEMONSTRATION
$form = <<<FORM
<form method="post">
ENTER SOMETHING, THEN REENTER IT
<input name="foo" />
<input type="submit">
</form>
FORM;

echo $form;

Open in new window

Consider @DaveBaldwins post above. It seems like youre faced with a design issue, in that the way the process is designed is causing the problem. If you modify the design you should overcome the problem.

At the moment the design process seems to run this course

1.User clicks add pizza button
2. Re-direct or include the 'cart' page and add one pizza.

From Daves comment you could change the process to something more like this:

1. User clicks add pizza button
2. Send data to a standalone script and add the pizza
3. If adding the pizza was successful NOW re-direct to a cart page.

You can then refresh the cart page and you wont add anything as the data was added on the standalone script page. This is a failry simple re-design. The event that send data to the cart page now sends data to your standalone script. The function that adds the data on your current cart page is now moved to the standalone script. If the script is successful now re-direct using the header() function to your cart page.

Hope that helps.
Agree that it is something of a design problem.  Message digests can help reduce the risk of accidental duplicate submissions.  You are not limited to the use of the multi-submit() function I showed above; you can use the md5() function in all sorts of creative ways.  You might put it into a column of a data base table and let it carry the md5() encoding of the INSERT query.  If you had a UNIQUE index over the md5 column and the current time, (perhaps accurate to the minute) you could catch MySQLl_ErrNo() #1062 and reject duplicate attempts to insert the same information into the table.  Or you could make an md5() string from the IP address, the value of time() (perhaps to the minute or 5-minute interval, whatever you wanted) and the order details.  You might also use a session counter or some other method of detecting the path through the site.  Most PHP installations set HTTP_REFERER correctly.
Avatar of LezlyPrime

ASKER

Thanks for all the great input & ideas to try. I'll be working on it this weekend.

~later
So it took some tinkering, but I got it to work. It was a basic design problem. You all had good input, but Dave Baldwin nailed it first with a suggestion for a different approach that worked, so I'm awarding him the points. I hope that is acceptable.

I appreciate everyone's input. Ray, I'll be looking more closely at the alreadyGotThat code you posted & also more about message digests. Thanks!