how to avoid/stop duplicate insertion for php and html? - php

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>";
}
?>

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.

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

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

Related

Insert Json object to database in php

I am working on an android app which uses APIs made with php. Here, i am dynamically creating columns and their values.
I am verifying the API via postman and a strange thing happens every time, While looping through the Json Object what i am doing is first creating column and then inserting its values.
The problem is only the 1st iteration saves the element and rest of them only creates the column but does not insert the values. I don't know if i am doing anything wrong, below is my php code.
<?php
include("connection.php");
$data = file_get_contents('php://input');
$json_data = json_decode($data);
foreach($json_data as $key => $val) {
$column_name = $key ;
$c_column_name = preg_replace('/[^a-zA-Z]+/', '', $column_name);
$column_value = $val ;
$table_name = "test2";
$email = "ht#t.com";
$result = mysqli_query($conn,"SHOW COLUMNS FROM $table_name LIKE '$c_column_name'");
$exists = (mysqli_num_rows($result))?TRUE:FALSE;
if($exists) {
$query1 = "INSERT INTO $table_name($c_column_name)VALUES('$column_value') ";
$data0=mysqli_query($conn,$query);
if($data0)
{
echo json_encode(array("success"=>"true - insertion","message"=>"Column existed, Successfully data sent."));
}
else{
echo json_encode(array("success"=>"false - insertion","message"=>"Column existed, data not inserted."));
}
}
else{
$query2="ALTER TABLE $table_name ADD COLUMN `$c_column_name` varchar(50) NOT NULL";
$data1=mysqli_query($conn,$query2);
if($data1){
$query3="INSERT INTO $table_name($c_column_name)VALUES('$column_value')";
$data2=mysqli_query($conn,$query3);
if($data2)
{
echo json_encode(array("success"=>"true - insertion","message"=>"Successfully data sent."));
}
else{
echo json_encode(array("success"=>"false - insertion","message"=>"Column created but data not inserted."));
}
}
else
{
echo json_encode(array("success"=>"false - column creation","message"=>"Failed to create column.'$column_name', '$table_name', '$conn'"));
}
}
}
?>
Here is the Json Object through postman.
{"Shape":"rewq","Trans.No.":"yuuiop","Color":"qwert"}
Please help me with this, any help or suggestions are highly appreciated.
The second column name is Trans.No. which contains a dot, this is why it fails, probably you have an error as a result which prevents further columns from being created.
I think it would be much better to have a table with this structure:
attributes(id, key, value)
and whenever a key-value pair is received, you just insert/update it, depending on the logic you need to be executed. Your current model will create a separate row for each attribute, which is probably not what you want to achieve.
EDIT
Based on the information received in the comment section I reached the following conclusion:
You could create the missing columns first and then generate the insert statement with all the columns, having a single insert.
But it would be better to not create a separate column for each value, as the number of columns could quickly get out of hand. Instead you could have a table:
myentity(id, name)
for storing the entities represented by the JSON and
attributes(id, myentity_id, key, value)
for storing its attributes. This would be a neat schema with all the dinamicity you could want.

How to DROP a table inside while loop of SELECT in PHP?

I have a table where I store all the machine details, I need to delete all data and drop all tables of a specific user.
I'm trying to DROP tables based on the result from Select query, but it's not working as it is inside WHILE of SELECT query. Kindly help me with this.
$sql="SELECT M_ID FROM machine_details WHERE Username='".$inname."'";
$result=mysqli_query($conn,$sql);
while($row=mysqli_fetch_assoc($result))
{
$delmid=$row['M_ID'];
$delsta=$delmid."_status";
$delpar=$delmid."_parameter";
$sql1="DROP TABLE IF EXISTS $delpar, $delsta";
if(!mysqli_query($conn,$sql1))
{
echo "Error in drop".mysqli_error($conn);
}
else
{
$sql2="DELETE FROM machine_details WHERE M_ID=".$delmid;
if(!mysqli_query($conn,$sql2))
{
echo "Error in machine delete".mysqli_error($conn);
}
}
I'm not getting any errors from PHP or MariaDB, but the code doesn't DROP the table(It exists in phpmyadmin).
Any alternate or more efficient methods are also welcome.
UPDATE : The above code works perfectly fine now, kindly see the edit logs for better understanding about the issue I faced.
ID is int type! Dont place it in quotes. Right method is:
$sql2="DELETE FROM machine_details WHERE M_ID=".$delmid;
Try with Following Code to Delete.
For Delete you can use this code.
<?php
//delete.php
include("connection.php");
if(isset($_POST["_id"]))
{
$query = "DELETE FROM app WHERE _id = '".$_POST["_id"]."'";
if(mysqli_query($connection, $query))
{
echo 'Data Deleted';
}
}
?>
Note: Don't Delete any user data from the table, because if you need any history or detail report you can use this, for this you can put one flag.
Just remove the backquotes(`)
With its use M_ID is being converted to String type. Which should not happen... Because the primary key is int in your case
DELETE FROM machine_details WHERE M_ID=".$delmid;

PHP + HTML: create a form dynamically

I'm trying to creat a form dynamically depending on the number of rows of a table in a database. I tried this and it's nor working:
require_once('mysqli_connect.php');
//I select the colum w_spanish from the table selected by the user
$q="SELECT w_spanish FROM ".$_GET['name'];
$r=#mysqli_query($dbc, $q);
echo '<FORM METHOD="POST" ACTION="Correction.php">';
echo '<TABLE BORDER="1">';
//Here is where I generate dinamically a table that can be filled by user
while ($row=mysqli_fetch_array($r, MYSQLI_ASSOC)){
$aux=$row['w_spanish'];
echo '<TR><TD>'.$aux.'</TD><TD><INPUT TYPE="TEXT" NAME="Sol_'.$aux.'" SIZE="20"></TD></TR>';
}
echo '</TABLE>';
echo '<P><INPUT TYPE="SUBMIT" VALUE="Submit" ></P></FORM>';
mysqli_close($dbc);
So when I press submit, the information is not sent to "Correction.php", and I think it's because I creating the HTML form inside php code. How could I do it right??
First off - remove the # from the #mysqli statement as it is masking any errors that maybe happening.
Secondly take the generated code and paste it into http://validator.w3.org/#validate_by_input and see if there are any HTML errors and adjust where necessary.
Thirdly, since the user can select which table to read then your data needs to be super-sanitised as you certainly don't want sql injection attacks here.
The problem may be the query you are running. Without knowing more information, my guess would be your query isn't getting anything. Try dumping the row in each iteration and see what spits out. You may be looking for something like:
$q="SELECT w_spanish FROM tableName WHERE name = " . $_GET['name'];
If that's not it, it could also be the fact that since you are only grabbing one column from the database, you don't need access the information with $aux=$row['w_spanish'];. You can just use:
$aux=$row;
That I'm not 100% on though. Try dumping each row with var_dump() and see what pops out.
First declare $row, then use a do-while loop.
$row = mysqli_fetch_array($r, MYSQLI_ASSOC) do{
$aux=$row['w_spanish'];
echo '<TR><TD>'.$aux.'</TD><TD><INPUT> TYPE="TEXT"NAME="Sol_'.$aux.'" SIZE="20"></TD></TR>';
}while ($row=mysqli_fetch_array($r, MYSQLI_ASSOC))

How to combine "add" and "edit" forms into 1 "script"?

I've always found myself creating two separate php files/scripts for adding a certain data and editing this data. These files weren't that much different, so I figured there should be a way how to make them into one file.
Here I'll present a very simple example to illustrate my point:
add.php:
<?php
$title = $_POST['title']; // ignore the unescaped data, this is a simple example
$text = $_POST['text'];
mysqli_query($connection,
"INSERT INTO `articles` (`title`, `text`) VALUES ('$title', '$text')");
echo'
<form>
<input type="text" name="title" value="'.$_POST['title'].'" />
<input type="text" name="text" value="'.$_POST['text'].'" />
<input type="submit" value="Add" />
</form>
';
?>
edit.php:
<?php
$id = $_GET['id'];
$title = $_POST['title']; // ignore the unescaped data, this is a simple example
$text = $_POST['text'];
// save data
mysqli_query($connection,
"UPDATE `articles` SET `title` = '$title', `text` = '$text'
WHERE `id` = $id");
// get current data
$q = mysqli_query($connection,"SELECT * FROM `articles` WHERE `id` = $id");
$d = mysqli_fetch_array($q);
$title = $d['title'];
$text = $d['text'];
echo'
<form>
<input type="text" name="title" value="'.$title.'" />
<input type="text" name="text" value="'.$text.'" />
<input type="submit" value="Add" />
</form>
';
?>
As you can see, the add and edit forms/codes are very similar, except that:
add inserts the data, while edit updates it
add inserts $_POST values into the form (if there's an error, so that the submitted data remains in the form, while edit inserts the current database values into the form (after the save is complete and the page refreshes, so that the form has the current db values)
Can these two somehow be merged into one file/code, so that if I want to add/change the form values, I don't need to edit two files separately, but will change the form only once?
You can use a INSERT ON DUPLICATE KEY UPDATE which roughly gave you :
<?php
$id = $_GET['id'];
$title = $text = '';
if ($_POST)
{
$title = $_POST['title'];
$text = $_POST['text'];
// save data
$query = "INSERT INTO `articles` (`id`, `title`, `text`)
VALUES ('$id', '$title', '$text')
ON DUPLICATE KEYS UPDATE title = title, text = text"
mysqli_query($connection, $query);
}
else if ($id)
{
// get current data
$q = mysqli_query($connection, "SELECT * FROM `articles` WHERE `id` = $id");
$d = mysqli_fetch_array($q);
$title = $d['title'];
$text = $d['text'];
}
echo '
<form>
<input type="text" name="title" value="'.$title.'" />
<input type="text" name="text" value="'.$text.'" />
<input type="submit" value="Add" />
</form>';
If it's a POST and no $id present : a new row is inserted just like an INSERT.
If it's a POST and an $id is present : if $id already exist in the table than the row is updated otherwise it's an INSERT.
If you only have an $id : show the form with existing data in it.
If it's not a POST and $id isn't populated : show an empty form.
You could use a combination of GET and POST parameters do achieve what you want. Use the GET parameters to distinguish between edit and add, i.e. /post?action=add or /post?action=edit. Based on the value of $_GET['action'] you'd know whether to render an empty form to add a post or to populate the form in with data from the DB. Then you could have a hidden field in your form, which you'd fill in with the value of $_GET['action'] and so you'd be able to know whether to INSERT or UPDATE when processing the form after submitting it.
It might be worth though to start using some framework, i.e. CakePHP, CodeIgniter, Zend Framework, etc.
I tend to make an interface for inserting and updating data which has only one method for inserting and updating. The key point for that to work is the user form that is being submitted must contain the id of the row being updated.
public method save( Object obj )
if obj.id is in database
query = "update table set attrA = obj.a, attrB = obj.b where id=obj.id"
else if obj.id < 1
query = "insert into table (a,b,c) values (obj.a,obj.b,obj.c)"
This implies that when you create a new object to be submitted, it must have id initialized to 0 or -1 (1 is the first key row for a table with int primary keys). Likewise, a form in a html file must have an <input type=hidden value=row.id name=DBID> that is populated either with a default value (null, 0, -1) or a valid id of the object being edited.
Essentially this means that the user may update arbitrary rows in the table, but granted they have authenticated themselves, this should not be a problem. Also, it is usually enough to know that the id > 0 to to an INSERT, and UPDATE otherwise. It is not necessary to verify that the id being submitted is in the database table, because when you insert you do not set the id, but rather let the DB auto-increment the primary key.
update
wow so many silly typos after only 3 beers. I hope this is readable
Here's an idea how it should look like using OOP (in my opinion).
Let's assume you have some class that represents form element called FormElement.
Then you have some generic form that should support what? Let's assume MVC:
displaying itself
adding elements
setting default values
parsing request values
getting values
validating values
So you'll build yourself an interface like
interface IForm {
public function Display();
public function AddElement( FormElement $element);
public function SetValues( array);
public function FetchPostValues();
public function GetValues();
public function Validate();
}
Then, what's common for both those forms (let's say that you want to prohibit change of email)? Everything except FetchPostValues()
So you'll build a class with one pure virtual method which will do everything that is similar:
abstract class FormArticle implements IForm {
// All methods implemented except FetchPostValues
abstract public function FetchPostValues();
}
And then just build two small classes that will define how to fetch post data:
class FormArticleEdit extends FormArticle {
public function FetchPostValues(){
if( isset( $_POST['email'])){
throw new Exception('What are you trying to achieve?');
}
// ...
}
}
And one more tip (two actually):
Implement abstract class like FormAbstract that will provide all generic methods like AddElement(), Display(). This will save you copying of those general methods every time, but will still provide you with ability to start from scratch (when using database or so directly to cache items).
Rather use framework that already has model for reusing forms (Zend is my personal favorite).

Best practice: Use same form for creation and update

I'm just curious and was wondering how you guys handle it if you want to use the same html form and as far as possible the same php code to create and update an item.
Example:
On one page you can create a database entry with name, email address and age.
On a different(?) page you see the form fields filled with your data and you can edit and save it.
I have my ways to accomplish this using pretty much the same code - but I'm hoping to learn something here. So how would you handle this task?
Thanks & Cheers, sprain
Pretty easily - if an ID of an existing item (which the user is authorised to edit) is supplied in the query string, then it's an edit operation.
If no ID is supplied in the query string, it's a create operation.
The fields are pre-populated based on the existing values from the database if it's an edit operation, or based on default values or empty strings if it's a create operation.
The way I see it is that reusing identical markup for form between create/edit works for some cases, but not for all. I find that forms -- though they may map to the same database table -- are really defined by their context. For example, if you had a 'users' table, you might have a 'create' form with username, email, password, but after that user exists you want them to retain their identity on their site, so the username field would not appear in an 'edit' context. I'm classically a PHP developer, but I have come to appreciate the approach that Django takes, where you create a model (table) that defines the basic validation for each field and you can create as many forms as you that build off of, or modify/extend from that definition. If you're writing from scratch, you'll probably find it practical to make your validation methods very portable and/or find ways to make your form fields context-sensitive.
That's the way I always do it now. Are you using an MVC system at all? I use one controller with two different actions (urls = person/new + person/edit/xxxx_id).
the code is then something like:
function new()
errors = []
if (get)
data = blank_record()
elseif (post)
data = posted_data
if (create(data))
redirect_to_listing()
else
errors = describe_errors
show_form(data, errors)
function edit()
errors = []
if (get)
data = get_from_db(id)
elseif (post)
data = posted_data
if (save())
redirect_to_listing()
else
errors = describe_errors
show_form(data, errors)
Note that once it gets to the form there's always an object called data that the form can render, it may be blank, from the db, or posted data. Either way it should always be the same format.
The reason I split new and edit is that I find that often enough they are actually quite different in their behaviours and the load and save steps.
I guess this is not the right answer but it might be interesting for you anyway.
There is an orm project called doctrine:
http://www.doctrine-project.org/projects/orm/1.2/docs/en
// User Id might be an existing id, an wrong id, or even empty:
$user_id = 4;
$user_id = null;
// Fetch the user from the database if possible
$user = Doctrine::getTable('Model_User')->find($user_id);
// If there was no record create a new one
if ( $user === false )
$user = new Model_User();
// Change some data
$user->title = $newValue;
// Perform an update or an insert:
$user->save();
As you see you don't have to care about sql.
Doctrine does that for you and your code becomes easier to read and to debug.
Yes, that's the only acceptable solution.
Here is a little example of CRUD application which store the input form in a template:
<?
mysql_connect();
mysql_select_db("new");
$table = "test";
if($_SERVER['REQUEST_METHOD']=='POST') { //form handler part:
$name = mysql_real_escape_string($_POST['name']);
if ($id = intval($_POST['id'])) {
$query="UPDATE $table SET name='$name' WHERE id=$id";
} else {
$query="INSERT INTO $table SET name='$name'";
}
mysql_query($query) or trigger_error(mysql_error()." in ".$query);
header("Location: http://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']);
exit;
}
if (!isset($_GET['id'])) { //listing part:
$LIST=array();
$query="SELECT * FROM $table";
$res=mysql_query($query);
while($row=mysql_fetch_assoc($res)) $LIST[]=$row;
include 'list.php';
} else { // form displaying part:
if ($id=intval($_GET['id'])) {
$query="SELECT * FROM $table WHERE id=$id";
$res=mysql_query($query);
$row=mysql_fetch_assoc($res);
foreach ($row as $k => $v) $row[$k]=htmlspecialchars($v);
} else {
$row['name']='';
$row['id']=0;
}
include 'form.php';
}
?>
form.php
<form method="POST">
<input type="text" name="name" value="<?=$row['name']?>"><br>
<input type="hidden" name="id" value="<?=$row['id']?>">
<input type="submit"><br>
Return to the list
</form>
list.php
Add item
<? foreach ($LIST as $row): ?>
<li><?=$row['name']?>
<? endforeach ?>
Of course, some fancy form constructor, like HTML_QuickForm2 coud be used instead of plain HTML template - you know its constant programmer's hunger not to repeat himself, even in naming an HTML field, field value and error key :)
But personally I prefer plain HTML.

Categories