Delete the record if its exist , else insert - php

I have a click favorite star , i want to check in data base if the record is exist it will delete the record , if it not exist it will insert the record ,what is the problem the record not inserted
<?php
include "config.php";
header('Content-Type: application/json');
$landmarkid = $_GET['landmarkid'];
$userid = $_GET['userid'];
try {
$query = mysqli_query($con,"SELECT * from favourite WHERE userid =$userid AND L_ID = $landmarkid");
if(mysqli_num_rows($query) > 0)
{
$q1 = mysqli_query($con,"DELETE from favourite WHERE userid =$userid AND L_ID = $landmarkid");
if($q1){
echo '{"Deleted":"true"}';
}
else {
echo '{"Deleted":"false"}';
}
}
else {
$q2 = mysqli_query($con,"INSERT INTO favourite (userid,L_ID) VALUES ( $userid, $landmarkid) ");
if($q2){
echo '{"inserted":"true"}';
}
else {
echo '{"inserted":"false"}';
}
}
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
?>

Try to add single quotation marks to your insert statement and see if it works. Change this statement;
$q2 = mysqli_query($con,"INSERT INTO favourite (userid,L_ID) VALUES ( $userid, $landmarkid) ");
To this;
$q2 = mysqli_query($con,"INSERT INTO favourite (userid,L_ID) VALUES ( '$userid', '$landmarkid') ");
Let me know if it helps or if you find a problem.

I have rewritten your code below.
Some points:
Your code was vulerable to SQL injection so assuming id is a numeric value I forced the input vars ($userid and $landmarkid) to be integers using (int) casting.
Your first checking query can return a COUNT value, it's better than returning a * and then you can check a specific value for your if statements, $result['numb'].
I have properly escaped your php variables in the SQL, but you really should be trying to use Prepared Statements for this.
I dont think you need the try{} catch {} here as your current code will never throw exceptions (as far as I'm aware)
Add a LIMIT to your delete statements so you can never delete more than an intended number of row. This acts as a failsafe so you don't inadvertantly manage to delete the whole table.
<?php
include "config.php";
header('Content-Type: application/json');
$landmarkid = (int)$_GET['landmarkid'];
$userid = (int)$_GET['userid'];
try {
$query = mysqli_query($con,"SELECT COUNT(*) as numb FROM
favourite WHERE userid = ".$userid." AND
L_ID = ".$landmarkid);
$result = mysqli_fetch_aray($query);
if($result['numb'] > 0)
{
$q1 = mysqli_query($con,"DELETE FROM favourite
WHERE userid = ".$userid." AND L_ID = ".$landmarkid."
LIMIT 1");
print "deleted";
}
else {
$q2 = mysqli_query($con,"INSERT INTO favourite (userid,L_ID)
VALUES ( ".$userid", ".$landmarkid.") ");
print "inserted";
}
}
catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
?>

Related

How to count your user userID to count/select a row in a table?

I'm making a function that i have to check if a userid is in this table already: if not he has to get into another page yet. But for some reason I get "NULL" back instead of the number of the userID.
my class:
public function countHobbies($userID){
try{
$conn = Db::getConnection();
$statement = $conn->prepare("select * from hobby where userID = '".$userID."'");
$userID = $this->getUserID();
$statement->execute();
$aantal = $statement->fetchAll(PDO::FETCH_ASSOC); //
$aantal->execute();
}
catch(throwable $e){
$error = "Something went wrong";
}
}
and this is on my html page:
$userArray = $_SESSION['user_id'];
$userID = implode(" ", $userArray);
$hobby = new Hobby();
$count = $hobby->countHobbies($userID);
if($count == false){
echo "no";
//header('Location: hobby.php');
}
else{
echo "yes";
}
There are at least two things you need to fix:
Always use parameter binding on the SQL statement. It may not be a security problem in this particular instance, but do get into the habit of using prepared statements. Because otherwise you'll find yourself in situations where you should've but didn't. https://www.php.net/manual/en/security.database.sql-injection.php
The $userID variable must be assigned before it is used.
In the end, it could look like this:
$userID = $this->getUserID();
$statement = $conn->prepare("select * from hobby where userID = ?");
$statement->bind_param("s", $userID);

No Update done with PDO php

I have problem without any error in my code that update row ..
if(!isset($error)){
try {
$sql = "UPDATE `invoice` SET `client`='".$client."', `company`='".$company."' , `clientemail`='".$clientemail."' , `mobailclient`='".$mobailclient."' , `startdate`='".$startdate."' , `enddate`='".$enddate."' WHERE `id` ='".$id."'";
$count = $db->exec($sql);
//redirect to invoice page
header('Location: invoice.php');
exit;
//else catch the exception and show the error.
} catch(PDOException $e) {
$error[] = $e->getMessage();
}
}
This is my code , i try to get variable $sql and go to mysql phpmyadmin and its work good ,, but in file not work and i dont get any error
==== Update ====
i try this and not work
try {
$sql = 'UPDATE invoice SET client = :client, company = :company, clientemail = :clientemail, mobailclient = :mobailclient, startdate = :startdate, enddate = :enddate WHERE id = :id';
$statement = $db->prepare($sql);
$statement->bindParam(":client", $client);
$statement->bindParam(":company", $company);
$statement->bindParam(":clientemail", $clientemail);
$statement->bindParam(":mobailclient", $mobailclient);
$statement->bindParam(":startdate", $startdate);
$statement->bindParam(":enddate", $enddate);
$statement->bindParam(":id", intval($_GET['id']) );
$statement->execute();
if($statement->rowCount() > 0) // will return 1 if any row is updated
{
echo "<script>alert('".$statement->rowCount()."')</script>";
}
else
{
echo "<script>alert('No record updated')</script>";
}
Your query is opened for SQL Injection. You should use parameterized query which provide a kind of protection against SQL injection but will not provide 100% of protection. Kindly visit this Post for more details.
Try the following code by replacing table and column names.
$client = "my name";
$company = "my-company";
$id= 2;//make sure your table has a record with that specific id
$sql = 'UPDATE invoice SET client = :client, company = :company WHERE id = :id'; // here i am updating only two columns
//You can add more column that you want to upate like ColumnName = :ParameterIdentifier
//Where ParameterIdentifier Is the name of parameter used in bindParam as in my example company
$statement = $db->prepare($sql);
$statement->bindParam("client", $client); //Binding parameter for client
$statement->bindParam("company", $company); //Binding parameter for company
$statement->bindParam("id", $id);
$statement->execute();
if($statement->rowCount() > 0) // will return 1 if any row is updated
{
echo "Record updated successfully";
}
else
{
echo "No record updated";
}

PDO: Query does not produce the right results the first time

I have three queries on my login script. One select query checks the users' credentials, another to update the last login, and the third one is a select query to see whether the user exists in another table, so if the user exists in the table, go some where. If the user doesn't exist, go somewhere else.
The third query is the one is acting weird. Below:
require_once '../includes/sessions.php';
//echo 'hello';
$employerlogindata = $_POST['employerlogindata'];
$data = json_decode($employerlogindata);
$employeremailfromjs = $data->employeremail;
$employerpasswordfromjs = $data->employerpassword;
//sanitization
$employeremail = htmlentities($employeremailfromjs);
$employerpassword = htmlentities($employerpasswordfromjs);
//PHP validation rules
$validflag = true;
function checkblanks($variable){
if($variable == ''){
$validflag = false;
print_r('Empty Inputs. Please try again.');
}else {
$variable = trim($variable);
$variable = stripslashes($variable);
return $variable;
}
}
checkblanks($employeremail);
checkblanks($employerpassword);
if($validflag == false) {
echo 'You have problematic entries. Try again.';
} else {
try{
$sql = "SELECT EID AS dbeid, EMPLOYER_EMAIL AS dbemail, `PASSWORD` AS dbpwd, EMPLOYER_NAME AS dbcompanyname, LAST_LOGIN AS dblastlogin FROM userpwd WHERE EMPLOYER_EMAIL = :employeremail;";
$query = $conn->prepare($sql);
$query->bindParam(":employeremail", $employeremail);
$query->execute();
//echo "select statement successfully executed";
//echo $sql;
} catch(PDOException $e){
echo "Error connecting to server: " . $e->getMessage();
die;
}
//echo $query->rowCount();
if ($query->rowCount() == 0){
echo "Email/Password combo was not found in the system.";
}else {
$result = $query->fetch(PDO::FETCH_OBJ);
//print_r($result);
$dbeid = $result->dbeid;
$dbemail = $result->dbemail;
$dbpwd = $result->dbpwd;
$dbcompanyname = $result->dbcompanyname;
$dblastlogin = $result->dblastlogin;
//echo $dbeid;
if(password_verify($employerpassword, $dbpwd)){
try{
$sql = "UPDATE userpwd SET LAST_LOGIN = NOW() WHERE EMPLOYER_EMAIL = :employeremail; ";
$query = $conn->prepare($sql);
$query->bindParam(":employeremail", $employeremail);
$query->execute();
}catch (PDOException $e){
echo "Error connecting to server: " . $e->getMessage();
die;
}
$_SESSION['EID'] = $dbeid;
$_SESSION['EMPLOYER_EMAIL'] = $dbemail;
$_SESSION['EMPLOYER_NAME'] = $dbcompanyname;
$_SESSION['LAST_LOGIN'] = $dblastlogin;
//echo "Logged in";
} else {
echo "Email/Password combination is invalid. Please Try Again.";
}
try{
$select = "SELECT EID from e_profile WHERE EID=:eid";
$stmt = $conn->prepare($select);
$stmt->bindParam(":eid", $sessemployerid);
$stmt->execute();
}catch(PDOException $e){
echo "Error connecting to server: " . $e->getMessage();
die;
}
$res = $stmt->fetch();
$eid = $res['EID'];
$count = $stmt->rowCount();
if($stmt->rowCount() == 1){
echo "employerdashboard.php $eid $count";
$stmt->closeCursor();
} else if ($stmt->rowCount() == 0){
echo "e_profile.php $eid $count";
$stmt->closeCursor();
}
}
}
?>
After a set of login credential is successful, the script hits both the second and the third queries. However, the third query takes on the results of the previous ran query. After a second click on the frontend with the same credentials, it produces the right results.
I thought maybe I could find the functionality of mysqli_free_result() in PDO's closeCursor, but that doesn't work. I want it to produce the right result the first time.
Any clues as to why this is happening?
Your variable is out of date (or at least that is my theory), as I said in the comments.
If you have
global $sessemployerid = $_SESSION['EID'];
Then you do
$_SESSION['EID'] = $dbeid;
Then you use $sessemployerid it will not be equal to $_SESSION['EID'] = $dbeid. It will be equal to the previous value of the session when it was assigned, which may or may not be correct. Probably on the first attempt it is wrong, then on subsequent attempts it is correct.
Just to lay it out a bit further:
//you assign $sessemployerid way up here
global $sessemployerid = $_SESSION['EID'];
...
//then you update the session
if(password_verify($employerpassword, $dbpwd)){
try{
$sql = "UPDATE userpwd SET LAST_LOGIN = NOW() WHERE EMPLOYER_EMAIL = :employeremail; ";
$query = $conn->prepare($sql);
$query->bindParam(":employeremail", $employeremail);
$query->execute();
}catch (PDOException $e){
echo "Error connecting to server: " . $e->getMessage();
die;
}
$_SESSION['EID'] = $dbeid; //<--- here you update the session but neglect $sessemployerid
$_SESSION['EMPLOYER_EMAIL'] = $dbemail;
$_SESSION['EMPLOYER_NAME'] = $dbcompanyname;
$_SESSION['LAST_LOGIN'] = $dblastlogin;
//echo "Logged in";
} else {
....
//then you use $sessemployerid, but it has a stale value (sometimes)
$select = "SELECT EID from e_profile WHERE EID=:eid";
$stmt = $conn->prepare($select);
$stmt->bindParam(":eid", $sessemployerid);
To fix this you could use a reference assignment
global $sessemployerid =& $_SESSION['EID'];
This can be demonstrated by this simple code:
$a = 1;
$b =& $a; //initial assignment, with reference
echo $b."\n";
$a = 2; //change the value of $a
echo $b; //$b is auto-magically updated
See it here
Ouputs
1
2
If you do it this way (the "normal" way)
$a = 1;
$b = $a; //initial assignment, normal
echo $b."\n";
$a = 2; //change the value of $a
echo $b; //$b is not updated
The output is
1
1
Alternatively you could simply update the global after changing the session's value:
if(password_verify($employerpassword, $dbpwd)){
...
$_SESSION['LAST_LOGIN'] = $dblastlogin;
global $sessemployerid = $_SESSION['EID'];
}else{
...
Because the value of $sessemployerid is out of sync with $_SESSION['EID'] you will get inconstant behavior depending on if you had updated the session or not on a previous page attempt.
Hope that makes sense.

How to avoid duplicating a lot of php prepare 12+ times

try {$db=mysqli_connect( etc )
catch {
retry on time out
handle errors
}
try { if (!($errors = $db->prepare("insert into errors (`insert`,`error`) values(?,?);
print "\n*********prepare Error:" . $db->error;
}
}
catch { repeat above}
try {$errors->bind_param("ss",$sqlLoad,$errormsg); }
catch {repeat above)
....
try {$error->execute()} catch {repeat above error handling}
Now repeat all of that 10-40 times for different SQL queries on different fields.
That is a lot of duplicated code. Make my code hard to read, and if someone wants to add more sql queries they are forced to reduplicate large blocks of code.
I was thinking something like this but ran into a stumbling block with bind.
$sql[0]=array("name","select ? from <tablename>","s");
$sql[1]=array("name","select ?,? from <tablename>","ss");
$sql[2]=array("name","select ?,?,? from <tablename>","sss");
$sql[3]=array("name","select ?,?,?,? from <tablename>","ssss");
for(i=0;i<=3,i++){
try (
$preQuery[$sql[i][0]=$db->prepare($sql[i][1]);}
catch {}
try {$preQuery[$sql[i][0]]->bind_param($sql[i][2],????);} //Here is the trouble how do I define unique variables
catch { }
}
Here is some real code
It is a work in progress
foreach ($fieldspath as $field)
{
$filepath=$_SERVER[$field];
$result=$queryfile->execute();
$getres = $queryfile->get_result();
$numRows = -1;
$numRows = $getres->num_rows;
if ($numRows <>0)
{
$qryField = $getres->fetch_assoc();
$_SERVER[$field]=$qryField["id"];
$fileCount=$qryField["count"];
$fileRating=$qryField["rating"];
mysqli_query($db, "update Files set count=count+1 where `id` ='" . $qryField["id"] . "';");
continue;
}
else
{
$output = $insertFile->execute();
$result = $queryip->execute();
$getres = $queryip->get_result();
$qryField = $getres->fetch_assoc();
$_SERVER[$field]=$qryField["id"];
}
}
Notice: How I can re-execute a query just by:
$result=$queryfile->execute();
The query doesn't have to be re-stated, nor do the parameters. Everything is automatic. The actual queries are all listed at the top of the program, and I never have to see them, or restate them ever again. Also I don't need to cram my parameters into array before I can use them.
<?php
$pipeName = '/var/run/mysql/mysql.sock';
$username = 'user';
$password = 'password';
$db = new PDO('mysql:unix_socket='.$pipeName.";dbname=dbase", $username, $password);
$sql["errors"]="insert into errors (`insert`,`error`) values(:insert,:error);";
$sql["events"]="insert into event (`message`) values(?);";
$sql["queryip"]="select id,count,rating FROM ip where address=? limit 1;";
$sql["queryUsrAgent"]="select id,count,rating FROM http_user_agent where agent=? limit 1;";
$sql["insUsrAgent"]="insert into http_user_agent (`agent`) values (?);";
$sql["insertIP"]="insert into ip (`address`) values (?);";
$sql["insertReqURI"]="insert into request (`REQUEST_URI`) values (?);";
$sql["queryReqURI"]="select * FROM request where REQUEST_URI=? LIMIT 1;";
$sql["queryfile"]="select id,count,rating FROM Files where path=? limit 1;";
$sql["insertFile"]="insert into Files (`path`) values (?);";
$sql["cntIp"]="update ip set count=count+1 where `address` = :ip";
$sql["cntFiles"]="update Files set count=count+1 where `id` = :id;";
$sql["cntAgent"]="update http_user_agent set count=count+1 where `agent` = :agent;";
$sql["reqRequest"]="select * FROM request where REQUEST_URI= :requesturi LIMIT 1;";
$sql["cntRequest"]="update request set count=count+1 where `REQUEST_URI` = :requesturi;";
$ready=doPrepare($db,$sql);
$ready["errors"]->execute(array("insert"=>"stuff","error" =>"stuff"));
pdoRun($ready,"errors",array("iniisert"=>"iiiii","error" =>"yyyyyggg"));
function doPrepare($db, $enmass) {
foreach ($enmass as $key => $sql) {
try {
$stmt[$key] = $db->prepare($sql);
} catch (PDOException $e) {
print "\nStuff";
trigger_error($e);
return false;
}
}
return $stmt;
}
function pdoRun($ready,$query,$vals) {
try {
$ready[$query]->execute($vals);
} catch (PDOException $e) {
print "\nExecution fail";
}
}
// $stmt->execute(array_values($column_values));
?>
Making prepared queries like you are doing doesn't work like you seem to think it does. The parameter placeholders can only substitute for literal values. You can't use them for column names or table names or anything else.
You also can't prepare a query like "select ? from" because it names no table. It's not a syntactically complete query.
The better practice is to code a "helper function" that does the prepare and execute for you. You can reduce repetitive code that way.
By the way, I find PDO is much easier than Mysqli when coding a helper function like this, because you don't have to use the bind_param() with variable arguments. In PDO, you just pass an array of arguments to execute().
function doInsert($db, $sql, $params) {
try {
$stmt = $db->prepare($sql);
$stmt->execute($params);
} catch (PDOException $e) {
trigger_error($e);
return false;
}
return true;
}
Now call it this way:
$sql = "insert into errors (`insert`, `error`) values(?, ?)";
$success = doInsert($db, $sql, [$sqlLoad, $errormsg]);
You might even like the function to format your INSERT statement for you:
function doInsert($db, $table, $column_values) {
$placeholders = array_fill(1, count($column_values), '?');
$columns = implode(',', array_keys($column_values));
$sql = "INSERT INTO `$table` ($columns) VALUES ($placeholders)";
try {
$stmt = $db->prepare($sql);
$stmt->execute(array_values($column_values));
} catch (PDOException $e) {
trigger_error($e);
return false;
}
return true;
}
Then call it like this:
$success = doInsert($db, "errors", ["insert"=>$sqlLoad, "error"=>$errormsg]);
You'll have to do something to apply back-ticks to the column names too.

Table row not updating

Problem is that if I update all users at one time the points row updates. But if I updating it by username row wont updating. I don't know why.
foreach($points as $p) {
$p = $p['points'] - $bet;
$username = $_SESSION['username'];
$q = $pdo -> prepare("UPDATE users SET points = '$p', username = '$username' ");
$q->execute();
}
without 'username = $username' all users updates perfectly.
Try:
try {
$q = $pdo->prepare("UPDATE users SET points = ? WHERE username = ?");
$q->execute(array($p, $username));
} catch(Exception $e) {
echo $e->getMessage();
die();
}
Or:
try {
$q = $pdo->prepare("UPDATE users SET points = :p WHERE username = :username");
$q->bindParam(':p', $p);
$q->bindParam(':username', $username);
$q->execute();
} catch(Exception $e) {
echo $e->getMessage();
die();
}
I haven't tested it, but I think that should work.
Check out the site.
WHERE username = 'username' or else with that lack of code, all rows are getting updated and that could be either planned or disaster.
As points is an integer, you should NOT use quotes around the variable, as it will be interpreted as a string, thus failing. So the correct syntax would be:
"UPDATE users SET points = {$p}, username = '{$username}'"

Categories