Use an IF STATEMENT with INSERT IGNORE - php

I have a voting system, which users can use to vote on posts. Thing is, they can't vote twice on the same post. Which is good. I did that like this:
$query = "INSERT IGNORE INTO vote_id (vote, postid, userid)
VALUES ('1', '{$postid}', '{$userid}')";
$result = mysqli_query($db, $query);
header('Location: index.php');
(The $db is my variable that connects to the database.)
They can still click on the vote, even if it doesn't insert into the table. The problem is, when it is IGNORE they shouldn't be able to click.
How do I separate the INSERT and IGNORE, so I can use the IGNORE in an if statement? Or in any other way, that can change the layout of the page?

Without code showing "vote" it's hard to say, but if it's button, then you can simply query a SELECT for a user_id and post_id, and if it finds at least one row, then add disabled to button. Like that:
<button name="vote" value="1" disabled>Vote</button>
Or just don't display anything "to vote" at all when query returns rows.
Other way is to check session, but it'd let the same user to vote again after relogging.

Thing is, they can't vote twice on the same post. Which is good. I did that like this:
What you've shown us here doesn't prevent people from voting twice (a unique index on postid and userid will - but that's not in your post). I do hope you are cleaning those parameters before splicing them into a an SQL statement like that.
But that is a comment.
How do I separate the INSERT and IGNORE, so I can use the IGNORE in an if statement
While I'm not 100% certain, I would expect mysqli_affected_rows() to return 0 if no rows were inserted. A more robust solution would be to omit the 'IGNORE' from the SQL statement and handle the duplicate key error:
$result = mysqli_query($db, $query);
$error=mysqli_errno($db);
switch ($error) {
case 0:
// all good
header('Location: index.php');
break;
case 1062:
print "Please don't vote twice\n";
exit;
default:
trigger_error("Query failed " . $query . " // " . mysqli_error($db));
print "whoops";
exit;
}

Related

I want to achieve row level locking using php in mysql

I am designing this page where users will see the change orders for the day. I want only one person to edit one change order at a time. While other user can still edit other change order. The code i am pasting is for final page where the user is redirected after clicking on particular change order. Please help me by giving an example as i am very new to php and mysql. Thanks in advance.
`
<?php
$change = $_GET['value'];
mysqli_query('BEGIN');
$sql="SELECT * FROM cat_firewall USE INDEX(id) WHERE chg_id='$change' FOR UPDATE";
$result=mysqli_query($con,$sql);
// Count table rows
$count=mysqli_num_rows($result);
?>
---MORE CODE----
while ($row = mysqli_fetch_array($result)){ ?>
<tr>
---MORE CODE----
<?php
$source_FW = $_POST['source_FW'];
$source_ACL = $_POST['source_ACL'];
$destination_FW = $_POST['destination_FW'];
$destination_ACL = $_POST['destination_ACL'];
if(isset($_POST['Submit'])){
foreach($source_FW as $key=>$value){
$sql1="UPDATE cat_firewall SET source_FW='$value' WHERE entry_id='$key' AND chg_id='$change' ";
$result=mysqli_query($con,$sql1);
}
foreach($source_ACL as $key1=>$value1){
$sql2="UPDATE cat_firewall SET source_ACL='$value1' WHERE entry_id='$key1' AND chg_id='$change' ";
mysqli_query($con,$sql2);
}
foreach($destination_FW as $key2=>$value2){
$sql3="UPDATE cat_firewall SET destination_FW='$value2' WHERE entry_id='$key2' AND chg_id='$change' ";
mysqli_query($con,$sql3);
}
foreach($destination_ACL as $key3=>$value3){
$sql4="UPDATE cat_firewall SET destination_ACL='$value3' WHERE entry_id='$key3' AND chg_id='$change' ";
mysqli_query($con,$sql4);
}
echo "update complete";
}
sleep(120);
mysqli_query($con,'COMMIT');
?>'
`
I want to lock it as soon as user clicks on the change order and gets to this page to edit rows and release the lock on the row once the submit button is clicked.
That's a big red flag. You should not expect InnoDB locking to run at the glacial speed of a human.
Optmistic version:
Have a sequence number for the updates that happen.
Grab that number at the start of the user looking at the values and scratching his head.
Let the user (at glacial speed) make changes.
Now send the updates and the sequence number back to the client API which does
The following:
BEGIN;
SELECT seq_num ... FOR UPDATE;
if the seq_num has changed, ROLLBACK this transaction and tell the user to start over.
else...
do the UPDATEs
update seq_num to a new number
COMMIT;
Pessimistic approach...
BEGIN;
SELECT who_is_editing FROM ... FOR UPDATE;
if someone else is editing, ROLLBACK and tell user to "try again later".
else...
UPDATE ... who_is_editing = $this_user;
COMMIT;
Now proceed to let the user do whatever he wants. But, at the end, clear who_is_editing.
Caveat: If a user simply vanishes, this 'lock' may never be released. So...
Have some job check for that.
Warn the user that he has a limited amount of time to enter the changes.
Verify inside the UPDATE transaction that the user still matches who_is_editing. If not slap him around, telling him "you took too long!".
(Caveat: both of these approaches were hastily typed; please study carefully, looking for holes in the logic.)

How get value from POST

This piece of code has been tripping me out for the past four hours. It is deleting a row of photos by the primary ID.
I have var_dump($selectedPhoto) and it is the correct ID, a number. My code will run every time I press delete photo, get to the mysqli_stmt_store_result part and shoots out the $txtMessage, But the database does not update.
This is really weird because I have used the exact same code, with different variables on another page and it works perfectly fine.
Can you see any errors by looking at this? OR have a better way to writing the delete statement.
if (isset($_POST['btnDeletePhoto']))
{
$selectedPhoto = $_SESSION['selectedPhoto'];
$deleteString = "DELETE FROM Photos WHERE PhotoID = ?";
$preparedDeleteStmt = mysqli_prepare($link, $deleteString);
mysqli_stmt_bind_param($preparedDeleteStmt, 'i', $selectedPhoto);
if (!mysqli_stmt_execute($preparedDeleteStmt))
{
mysqli_close($link);
die("The system is not available, try again later");
}
if(mysqli_stmt_store_result($preparedDeleteStmt))
{
$txtMessage = "Delete successfull";
}
To add: $selectedPhoto is a value of a select, drop down list value.
If the photo comes from the value of a select, it is not going to be stored in a session variable, so you probably need to change:
$selectedPhoto = $_SESSION['selectedPhoto'];
to:
$selectedPhoto = $_POST['selectedPhoto'];
Apart from that you need to add error handling to all database operations.

multipage session storing in database

i'm trying to set up a simple multipage form, with the use of sessions to be later stored in a database in multiple tables.
however, i seem to have run into a problem. while the values of the last page get posted to the database, the session variables do not.
please, keep in mind.. me and my project partner are complete newbies to php/sql and might not have payed as much attention in class as we should have. most of the code is pretty much thrown together randomly. and identifying problems does not seem to be our strong suit.
first page / b_tickets.php
(simple html form with the values 'ticket_a', 'ticket_k' and 'ticket_vip')
second page / b_rooms.php
<?php
session_start();
$_SESSION['ticket_a'] = $_POST['ticket_a'];
$_SESSION['ticket_k'] = $_POST['ticket_k'];
$_SESSION['ticket_vip'] = $_POST['ticket_vip'];
?>
third page / b_ucp.php
<?php
session_start();
$_SESSION['room_s'] = $_POST['room_s'];
$_SESSION['room_s_extra'] = $_POST['room_s_extra'];
$_SESSION['room_d'] = $_POST['room_d'];
$_SESSION['room_d_extra'] = $_POST['room_d_extra'];
$_SESSION['room_3'] = $_POST['room_3'];
$_SESSION['room_3_extra'] = $_POST['room_3_extra'];
$_SESSION['room_10'] = $_POST['room_10'];
$_SESSION['room_10_extra'] = $_POST['room_10_extra'];
$_SESSION['pension'] = $_POST['pension'];
?>
which leads to
insert_ucp.php
(at this point an echo ยง_SESSION of the previous variables reveals that they are in fact still stored.)
<?php
session_start();
$con = mysql_connect("localhost","XX","XX");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("fatcity", $con);
$sql="INSERT INTO tickets (ticket_a, ticket_k, ticket_vip)
VALUES
('$_SESSION[ticket_a]','$_SESSION[ticket_k]','$_SESSION[ticket_vip]')";
$sql="INSERT INTO rooms (room_s, room_s_extra, room_d, room_d_extra, room_3, room_3_extra, room_10, room_10_extra, pension)
VALUES
('$_SESSION[room_s]','$_SESSION[room_s_extra]','$_SESSION[room_d]','$_SESSION[room_d_extra]','$_SESSION[room_3]','$_SESSION[room_3_extra]','$_SESSION[room_10]','$_SESSION[room_10_extra]','$_SESSION[pension]')";
$sql="INSERT INTO ucp (title, name, n_family, adress, a_housenumber, continent, country, province, region, city, telephone, email, password, payment, client, comment)
VALUES
('$_POST[title]','$_POST[name]','$_POST[n_family]','$_POST[adress]','$_POST[a_housenumber]','$_POST[continent]','$_POST[country]','$_POST[province]','$_POST[region]','$_POST[city]','$_POST[telephone]','$_POST[email]','$_POST[password]','$_POST[payment]','$_POST[client]','$_POST[comment]')";
if (!mysql_query($sql,$con))
{
die('Error: ' . mysql_error());
}
echo "1 record added";
mysql_close($con);
?>
at this point the question is not in fact about how terrible we are when it comes to php/sql- thank you.. we already figured that out. with only pretty much three days to our deadline..
but why exactly the session variables aren't saved to the database. what exactly are we overlooking?
thank you very much in advance..
RUN query every time!!!
You create variable, then overwrite it 2 times than execute it
should be:
$sql = 'smth';
mysql_query($sql);
$sql = 'smth';
mysql_query($sql);
$sql = 'smth';
mysql_query($sql);
you have
$sql = 'smth';
$sql = 'smth';
$sql = 'smth';
mysql_query($sql);
And as I've said do not use mysql_*. And your code allows sql injection
First problem I see, is that $sql variable gets overriden 2 times in the last piece of code. So, only the last query gets executed.
Second, you should use this syntax to inject non-tribial vars into strings: "INSERT ... ${someArray[someKey]} ..." - note curly braces. This is not required here, but it will save you from troubles in the future.
Third, sanitize all the input data! You will have SQL injection in the last code example.
Last, no need to session_start() in each file - just place it once in bootstrapping file and require_once it.
I agree with E_p in that only one of your queries is ever going to be executed. doing what he suggested will allow all your queries to execute.
You may also want to take a look at your tables, just from looking at your query structure I see nothing wrong with them, but you may end up having a hard time getting the info you want back out. I could be wrong since you didn't post your table structures nor was your question really regarding this, but its just something I noticed and figured I would share. Your tables do not look like they are connected to each other by any foreign keys. This may not be needed for your project, but if you needed to pull all the form data related to all ticket_a entries then you would only get a list of sessionIDs corresponding to the ticket_a column, without any info from your 'rooms' or 'upc' tables. If that is what you are going for then its fine, otherwise you may want to look into it.

PHP/MySQL form not posting data to database

New to learning PHP form validation on same page. Please advise as to why my data might not be posting to the database. After filling out the form, it redirects to thank you page without sending data. Thanks!
http://pastebin.com/3T1W9Krx
Edit: Now that I know where my problem was, I have updated the Pastebin file to show the working code, which validates in the same page and checks the database for duplicate email addresses.
I was able to use Rick Kuipers suggestion below to find this error. I was trying to include a column for the primary key under VALUES, however I only needed the values for the INSERT keys, not ID or timestamp, as ID is set to auto-increment.
$sql = "INSERT INTO table (last_name, first_name, age)
VALUES (".
PrepSQL($last_name) . ", " .
PrepSQL($first_name) . ", " .
PrepSQL($age) . ")";
mysql_query($sql);
header("Location: volthankyou.php");
exit();
}
}
This could be because of a problem with your query.
Try doing the following:
echo mysql_error($db);
//header("Location: volthankyou.php");
This should display the error if there is any.
Check if mysql_query is true or false for your insert. Otherwise, it will ALWAYS try and then, redirect to thankyou. And as spencercw points out, mysql_select_db could also be failing. Always check the result of such methods.
P.S.: always check server logs

deleting a comment you posted with php code?

I was wondering if you can maybe help me out here... I created a link sharing website and managed to create a comment on a shared link.
I want to give you a scenario of what I would like to achieve. Every comment made by user_1 for instance, can only be deleted by user_1 and admin.
I understand that when "deleting" it from the php page it must also be dropped from the database. How can you do this?
//I pressume where I INSERTED my post's 'vales' I must DELETE them again from there??
//It is very much alike from reply.php's code where you INSERT the data into the database. Now I just want to delete it.
//I don't know if this code below is correct??
$sql = "DELETE FROM
posts(post_content,
post_date,
post_topic,
post_by)
WHERE ('" . $_POST['reply-content'] . "',
NOW(),
" . mysql_real_escape_string($_GET['id']) . ",
" . $_SESSION['user_id'] . ")";
$result = mysql_query($sql);
if(!$result)
{
echo 'Your reply has not been saved, please try again later.';
}
else
{
echo 'Your comment has been deleted!';
}
Your Delete query has major syntax errors. You don't delete individual fields from a table - you CAN'T. you can only delete entire records. The proper syntax is:
DELETE FROM sometable WHERE (...)
Your where clause also has errors. You're not doing any comparison operations, just listing some values. Again, a syntax error. Most like you'd want this (guessing at your post's table primary key field name):
DELETE FROM posts WHERE (post_id = $id);
You should give your comments ID's, and simply perform delete from posts where ID = $id.
The SQL statement you currently have won't even execute. Look at the manual for how the syntax works.
What would really be helpful is some separation of presentation logic from db logic from bus. logic. Try a MVC pattern, which makes it a lot easier to parse through the code and to only look at DB or presentation or bus. logic code. Then, we could focus on the answer to the question posted.

Categories