5

Hi does anyone knows how to avoid/stop duplicate insertion for php and html? Whenever I refresh, the same data repeats which is not what I want. Is there anything that I can change from here? I heard that adding UNIQUE INDEX can avoid/stop it. Maybe it works, but I place it wrongly which makes it unable to work. Any help? Thanks in advance!!! Will really appreciate it!

<?php
session_start();
include("Validation.php");

$connect=mysqli_connect("localhost","root","","jailbird");
if(mysqli_error($connect))
{
die("Could not connect.");
}

if(isset($_POST["insert_click"]))
{
//Bookingid is auto increment, therefore no need
//$Bookingid=$_POST["BookingID"];
$Prisonerid=$_SESSION['Prisonerid'];
$Visiting_method=$_POST["VisitingMethod"];
$Visiting_location=$_POST["VisitingLocation"];
$Date=$_POST["Date"];
$Time=$_POST["Time"];

$query=$connect->prepare("insert into Booking(PrisonerID, VisitingMethod, VisitingLocation, Date, Time) values (?,?,?,?,?)");
$query->bind_param('sssss', $Prisonerid, $Visiting_method, $Visiting_location, $Date, $Time);
$query->execute();
}

$query=$connect->prepare("select * from booking WHERE Prisonerid=?");
$query->bind_param('s',$_SESSION['Prisonerid']);
$query->execute();
$query->bind_result($Bookingid, $Prisonerid, $Visiting_method, $Visiting_location, $Date, $Time);

while($query->fetch())
{
echo "<tr>";
//echo "<td width=60>".$Bookingid."</td>";
echo "<td>$Prisonerid</td>";
echo "<td>$Visiting_method</td>";
echo "<td>$Visiting_location</td>";
echo "<td>$Date</td>";
echo "<td>$Time</td>";
echo "</tr>";
}   
?>
stupidgal
  • 171
  • 1
  • 2
  • 11
  • SHould this be protected? – Mohammad Areeb Siddiqui Jul 27 '13 at 12:40
  • You can also control it with PHP, for example: set session after you insert, `$_SESSION['insert'] = 'yes'`, then add it as check to `if(isset($_POST["insert_click"]) && $_SESSION['insert'] != 'yes')` –  Jul 27 '13 at 12:43
  • Plus this question has been asked, [See here](http://stackoverflow.com/questions/2133964/how-to-prevent-multiple-inserts-when-submitting-a-form-in-php) – nt.bas Jul 27 '13 at 12:48

3 Answers3

1

Here is a small class I wrote (not tested)

<?php
class FormID {
    private $lastFormID = "";
    private $newFormID = "";

    function __construct(){
        $this->lastFormID = $_SESSION['__frmid__'];
        $_SESSION['__frmid__'] = uniqid('sm');
        $this->newFormID = $_SESSION['__frmid__'];
    }

    public function isFormDataValid(){
        return (isset($_POST['__frmid__']) && $_POST['__frmid__']==$this->lastFormID);
    }

    public function FromIDHTML(){
      return "<input type=\"hidden\" name=\"__frmid__\" value=\"{$this->newFormID}\"/>";
    }

}
?>

You can use it like this

<?php
    $frmid = new FormID();

    if ($frmid->isFormDataValid()){
      //do your insert here
    }
?>

<form method="post">
<?php echo $frmid->FromIDHTML(); ?>
<input .... />
</form>

Edit: Here is how to use this in your code

change

if(isset($_POST["insert_click"]))
{

to

$frmid = new FormID();
if(isset($_POST["insert_click"]) && $frmid->isFormDataValid())
{

And in the file where you generate the HTML form do something like this

<form method="post">
<?php $frmid = new FormID(); echo $frmid->FromIDHTML(); ?>
<!--Below is your form with all the fields -->
<input type="text" name="VisitingMethod" />

</form>

Note i have just added one line in the form <?php $frmid = new FormID(); echo $frmid->FromIDHTML(); ?>

let me know if you have any problems.

bansi
  • 55,591
  • 6
  • 41
  • 52
0

You can make the PrisonerID a primary key in your MySql table that way no duplicates will be allowed.

Neo
  • 779
  • 5
  • 13
  • But the prisonerid for the user is fixed – stupidgal Jul 27 '13 at 13:04
  • Yes that's why it is unique. You can update any new info to it but can't add a new entry with the same PrisonerID. – Neo Jul 27 '13 at 13:06
  • No. I mean.. The user who login has only 1 prisonerid. So every entry the user insert will be using the same prisonerid – stupidgal Jul 27 '13 at 13:07
  • Then make another table that will have the PrisonerID (not set as primary) and an additioanl column lets say entries and you number them. This way when you want to get information for yourself you can use both tables. So the second table will be just for filling out while the first just used for logging. – Neo Jul 27 '13 at 13:10
  • you mean like create an id right? i tried. but it does not seems to work. when it refresh, the id auto increments and the same record enter – stupidgal Jul 27 '13 at 13:52
  • @stupidgal If the PrisonerId is fixed (means also unique), then it is best you can create a table for `prisoners` and another for `bookings` and add `PrisonerId` as field in `bookings` with the following contraints: `INDEX` in order to use `JOIN` on both tables and `UNIQUE` to make sure you don't have two bookings for the same prisoner. (But I have to admit, this unique contraint in bookings is strange :-)) – nt.bas Jul 27 '13 at 13:56
  • For the second table, you'll have a column named PrisonerId(NOT primary key) and another column named i.e. ID (int not null Auto_Increment) and ID is the primary key. Every time you insert a data you'll get a new ID automatically and hence a new info with same PrisonerID is entered. If you DO NOT want the same info to be repeated when you are inserting, a way is to add a select statement before inserting that searches if the same particular thing i.e. based on visiting_method, is found.If found then update or do nothing.If not found then insert a new entry. – Neo Jul 27 '13 at 14:19
0

Like you've already said, you need to add a UNIQUE constraint to a field in your table you know can't have two values. When you say maybe it works it means to haven't you really tried that method. And we can't help unless you give more details about how you tried that and what went wrong.

For the UNIQUE constraint to work, you need to choose which fields in your table uniquely represent each row. For example, let's assume the PrisonerId uniquely represent each row. Then when your create the table you need to add the UNIQUE contraint to the PrisonerId field as follows:

CREATE TABLE `Booking` (
  `PrisonerId` int(10) NOT NULL,
  `VisitingMethod` varchar(100) NOT NULL,
  # Put other fields here #
  UNIQUE KEY `uc_PrisonerId` (`PrisonerId`)
) ENGINE=InnoDB;

You run that query when creating the table, or you can ALTER the table to add the new contraint or use phpMyAdmin/MySQL Workbench or whatever else method you prefer and when you insert a new record MySQL will make sure it respects the new constraint.

Also, note that you can still insert duplicate can't insert duplicate rows but can silence error messages if you want using the IGNORE keyword in your query. See insert documentation

The other approach, and expensive, would be to check if the new records aren't in the database yet. If they are, don't insert them, else do.

Finally consider redirecting from the form handler (the url in the action of the form) after the form submission. See here

Community
  • 1
  • 1
nt.bas
  • 736
  • 1
  • 6
  • 13
  • Actually, I tried. But from other websites it is ALTER then UNIQUE . So I tried $query=$connect->prepare("insert UNIQUE into Booking(PrisonerID, VisitingMethod, VisitingLocation, Date, Time) values (?,?,?,?,?)"); and $query=$connect->prepare("insert into Booking UNIQUE(PrisonerID, VisitingMethod, VisitingLocation, Date, Time) values (?,?,?,?,?)"); – stupidgal Jul 27 '13 at 12:51
  • I said may it works because I know I put it wrongly so I said may it works but not in that way – stupidgal Jul 27 '13 at 12:53
  • @stupidgal No try to modify the schema itself. I'm updating the answer to illustrate. Sorry! :-( – nt.bas Jul 27 '13 at 13:26
  • No need to sorry! You tried to help me :) I really appreciate that! I'll try it. – stupidgal Jul 27 '13 at 13:45
  • @stupidgal :-) The `UNIQUE` constraint is supposed to be executed when creating (or modifying) the table **not** when inserting new data! The `ALTER` is a command to alter(modify) a table structure that has been created already. – nt.bas Jul 27 '13 at 13:48