Form Submission – The annoying back button

23 Aug, 2011  |  Written by  |  under MySQL, PHP, Tips and Tricks

fix-back-button-on-formsI have come accross coders who want to know a simple solution to stop users from using the back button to resubmit data if they have made a mistake. Now I have plenty of solutions for this situation but they would depend on your current system in place such as; do you require a user to login? Does your system create sales order numbers? and many more questions.

So to keep it simple I will assume that you basically have a form that anyone in your company can use to submit an order which reduces the amount of stock you hold. This would simply be a system that monitors the amount of stock you have and nothing else.

Let me explain the issue with a scenario so we are all on the same page here.

We have a company called ‘Annoying Sales People Ltd’ (you can guess I dont like sales calls :) ) This company has 5 sales staff that sell products ‘ASP Ltd’ (haha this gets better as I think it up) have in stock. Now in order to monitor this stock level they have a simple SQL database running with a simple form which allows its sales staff to submit an order which would reduce the stock by the current order amount.

Great, that seems simple enough but heres the catch… ‘ASP Ltd’ sales staff make a mistake when filling in the form for current sale volume. So they have entered 5 units instead of the actual 4 units sold. The staff decide that they will just click the back button and resubmit the form.

So the issue here is lets say ‘ASP Ltd’ had in stock 10 units of product X. The staff member submitted an order for 5 units which took the stock level down to 5 units left. But then realised the error and clicked the back button to amend the order. Then changes the sales value to 4 then resubmits. Great, sales person feels good that he has corrected the form and submitted it to update the stock volumes.

Woops! What has happened here is the stock was reduced to 5 units originally, but he clicked the back button and resubmitted another sales value of 4 units which would then reduce the stock level to 1 unit. Actually only selling 4 units from the beginning he has managed to reduce stock levels by 9 in total. (I think more staff training is in order)

So what would be a really simple fix and I mean simple? I would suggest using a Timestamp Theory when submitting the form.

So lets get down to the PHP code for this solution. First we are going to create the system without the fix to see how the problems works. Then we will add the simple fix and watch how you solve this back button issue.

Ok, lets get the table created in your chosen database. So I would assume you know how to use the basics of say PHPMyAdmin and can submit an SQL Query and that you have already created a test database to use. I have below the query to create the table within your database:

CREATE TABLE products (
name varchar(255) NOT NULL default '',
stock int(11) NOT NULL default '0',
PRIMARY KEY (name)
)

Now you have the table created you need to add some example values to work with. So I have provided the SQL Query to input these values within your table:

INSERT INTO products VALUES ('Laptop', 10);
INSERT INTO products VALUES ('Laptop Bag', 20);
INSERT INTO products VALUES ('Laptop Power Pack', 30);

Great, thats the database setup. Now for the code that would monitor the basic stock levels for sales staff:

<?php
    // connect with the database
    mysql_connect('yourhost','yourusername','yourpassword');
    mysql_select_db('yourdatabase');

    if (isset($_POST['update'])) {

      // perform an update
      $name = mysql_escape_string($_POST['name']);
      $change = mysql_escape_string($_POST['change']);

      $query = "UPDATE products SET stock = stock - $change WHERE name='$name'";
      mysql_query($query);

      // retrieve the products
      $products = array();

      $query = "SELECT * FROM products";
      $result = mysql_query($query);
      while ($row = mysql_fetch_assoc($result)) {
        array_push($products,$row);
      }

      // generate nice HTML output with the results we found

      echo '<table>';
      echo '<tr>';
      echo '<th>NAME</th>';
      echo '<th>STOCK</th>';
      echo '</tr>';

      foreach($products as $product) {

        echo '<tr>';
        echo '<td>'.$product['name'].'</td>';
        echo '<td>'.$product['stock'].'</td>';
        echo '</tr>';
      }

      echo '</table>';

    } else {

      // retrieve the products
      $products = array();

      $query = "SELECT * FROM products";
      $result = mysql_query($query);
      while ($row = mysql_fetch_assoc($result)) {
        array_push($products,$row);
      }

      // generate nice HTML output with the results we found

      echo '<table>';
      echo '<tr>';
      echo '<th>NAME</th>';
      echo '<th>STOCK</th>';
      echo '<td>SOLD ITEMS</th>';
      echo '</tr>';

      foreach($products as $product) {

        echo '<tr>';
        echo '<td>'.$product['name'].'</td>';
        echo '<td>'.$product['stock'].'</td>';
        echo '<td>';
        echo '<form method="post">';
        echo '<input type="hidden" name="name" value="'.$product['name'].'" />';
        echo '<input type="text" name="change" />';
        echo '<input type="submit" name="update" value="update" />';
        echo '</form>';
        echo '</td>';
        echo '</tr>';
      }

      echo '</table>';
    }
?>

So the above application would work exactly how we would expect it. You enter a sales volume and update the stock levels. Now when you have submitted a stock level you see a confirmation screen telling you the current stock. Hit the back button and then change the value to something else and resubmit the sale. Now you will see the confirmation page again but with a new stock level.

The record has not been amended but infact a new sale has been registered that has reduced the stock levels even further. Which is not what we want to do is it? :)

Ok so here is my very simple solution. First you will need to add another column to your table within your database so here is the SQL query for that:

ALTER TABLE products ADD lastupdate TIMESTAMP NOT NULL;

Then we would need to add a ‘hidden’ field to our form which the users submit the sales value too. (It is hidden because the user does not need to see it and also we dont want the user to be able to change the value otherwise this would not be a fix :) )

echo '<input type="hidden" name="lastupdate" value="'
.$product['lastupdate'].'" />';

Then our next step would be to add the verification code before we enter our values into our database:

// find out when this product was updated the last time

$query = 'SELECT * FROM products WHERE product_id='.$product_id;

$result = mysql_query($query);

$row = mysql_fetch_assoc($result);

// compare the lastupdate in our form with the lastupdate in the database

if ($_POST['lastupdate'] < $row['lastupdate']) {

    echo "If you have made an error please use the amend order page!!!!";

} else {

    // perform the update - but don't forget to set lastupdate to NOW()

}

So there you have it. You have the simple fix, so lets just put all the above code together and see what happens:

<?php

    // connect with the database

    mysql_connect('yourhost','yourusername','yourpassword');

    mysql_select_db('yourdatabase');

    if (isset($_POST['update'])) {

      $name = mysql_escape_string($_POST['name']);

      $change = mysql_escape_string($_POST['change']);

      // find out when this product was updated the last time

      $query = "SELECT * FROM products WHERE name='$name'";

      $result = mysql_query($query);

      $row = mysql_fetch_assoc($result);

      // compare the lastupdate in our form with the lastupdate in the database

      if ($_POST['lastupdate'] < $row['lastupdate']) {

        echo 'You should use the <a href="amend_order.php">amend order page
        </a> instead!!!!';

      } else {

        // perform an update

        $query = "UPDATE products SET stock = stock - $change, lastupdate=NOW()
        WHERE name='$name'";

        mysql_query($query);

        // retrieve the products

        $products = array();

        $query = "SELECT * FROM products";

        $result = mysql_query($query);

        while ($row = mysql_fetch_assoc($result)) {

          array_push($products,$row);

        }

        // generate nice HTML output with the results we found

        echo '<table>';

        echo '<tr>';

        echo '<th>NAME</th>';

        echo '<th>STOCK</th>';

        echo '</tr>';

        foreach($products as $product) {

          echo '<tr>';

          echo '<td>'.$product['name'].'</td>';

          echo '<td>'.$product['stock'].'</td>';

          echo '</tr>';

        }

        echo '</table>';

      }

    } else {

      // retrieve the products

      $products = array();

      $query = "SELECT * FROM products";

      $result = mysql_query($query);

      while ($row = mysql_fetch_assoc($result)) {

        array_push($products,$row);

      }

      // generate nice HTML output with the results we found

      echo '<table>';

      echo '<tr>';

      echo '<th>NAME</th>';

      echo '<th>STOCK</th>';

      echo '<td>SOLD ITEMS</th>';

      echo '</tr>';

      foreach($products as $product) {

        echo '<tr>';

        echo '<td>'.$product['name'].'</td>';

        echo '<td>'.$product['stock'].'</td>';

        echo '<td>';

        echo '<form method="post">';

        echo '<input type="hidden" name="lastupdate" value="'.$product['lastupdate']
        .'" />';

        echo '<input type="hidden" name="name" value="'.$product['name'].'" />';

        echo '<input type="text" name="change" />';

        echo '<input type="submit" name="update" value="update" />';

        echo '</form>';

        echo '</td>';

        echo '</tr>';

      }

      echo '</table>';

    }

?>

Brilliant, now do me a favour and try the same scenario that you tried earlier and you should get a message telling you that you should use the Amend Order Page with a link to your page that you would need to create.

Ok, this is not a fantastic fix but its a simple one. Personally, I would be using a system that requires sales staff to login which would allow me to monitor who submits what stock changes. I would also make sure my system assigned sales order numbers to each submission and that way I could check the database for an existing order number on submission.

The main draw backs of this quick fix would be the refresh button because if they click the back button but then the refresh button the timestamp would reset to the current time. This means the submission would be allowed. This does however provide a solution to stop the back button being used.

2 Responses so far | Have Your Say!

  1. jessica  |  August 24th, 2011 at 3:32 pm #

    thanks for this tutorial as i have been banging my head against a wall due to this happening for me so thanks a bunch and will try get this code workin on my site nice blog by the way

    jessica - Gravatar
  2. Shaun Ellerton  |  August 24th, 2011 at 3:38 pm #

    No worries Jessica, I am glad you can use this code. If you need help just give us shout ok.

    Best wishes

    Shaun Ellerton - Gravatar

Leave a Feedback

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*