i have a php script with a sql query that is inside a foreach loop and if the query succeed to run it should echo "Success" but since its inside a loop it echo "success" multiple times but i wish to only echo "success" once. I have seen other similar threads here and i have looked at those and tried solve my problem from those threads but i have not been able to solve this problem from any other threads so please dont mark this as a duplicate.
Anyway, Here is my code
<?php
session_start();
include('../../config/dbconf.php');
foreach($_POST['entry'] as $entryid) {
$stmt = $authconn->prepare("UPDATE account SET dp = dp - ? WHERE username = ?");
$stmt->bind_param("is", $_POST['price'], $_SESSION['classicusr']);
if($stmt->execute()) {
echo "Success";
}else{
echo "Failed";
}
}
?>
You could try something like this?
Also, there is no need to prepare for each iteration of the loop.
<?php
session_start();
include('../../config/dbconf.php');
$bError = false;
$authconn->prepare("UPDATE account SET dp = dp - ? WHERE username = ?");
foreach($_POST['entry'] as $entryid) {
$stmt = $stmt->bind_param("is", $_POST['price'], $_SESSION['classicusr']);
try{
if(!$stmt->execute()) {
$bError = true;
// optional break and do not process further
// break;
$stmt = $stmt->errorInfo()
}
}catch (PDOException Exception){
$bError = true;
// additional erorr logging here. Could add to a delimetered string to report on later } }
echo ($bError ? 'Failure' : 'Success' );
?>
Seeing as you're not saying anything about the Failed statement, something like this might do the trick. All it requires is setting a simple flag.
<?php
session_start();
include('../../config/dbconf.php');
$feedbackGiven = FALSE;
foreach($_POST['entry'] as $entryid) {
$stmt = $authconn->prepare("UPDATE account SET dp = dp - ? WHERE username = ?");
$stmt->bind_param("is", $_POST['price'], $_SESSION['classicusr']);
if($stmt->execute()) {
if (!$feedbackGiven)
{
echo "Success";
$feedbackGiven = TRUE;
}
}else{
echo "Failed";
}
}
?>
Related
I'm trying to move the data from one column in my table, to another, and then setting the initial column back to zero. While the initial column is reset back to zero, it also adds that zero onto the end of target column (I'll provide some screenshots for context).
Here is my code:
function complete_da($da_id) {
include 'connect.php';
include 'globals.php';
retrieve_user_data($_SESSION['logged_in']);
nation_data_grab($_SESSION['logged_in']);
echo "u_n_i: ".$user_nation_information['active_da']." <br>";
$ret_da_info_sql = "SELECT `active_da`, `completed_da` FROM `nations` WHERE `nations`.`user_id` = ?;";
$ret_da_info_stmt = mysqli_stmt_init($connect);
if(!mysqli_stmt_prepare($ret_da_info_stmt, $ret_da_info_sql)) {
echo "Statement 1 Failed";
} else {
mysqli_stmt_bind_param($ret_da_info_stmt, "i", $user_data['id']);
mysqli_stmt_execute($ret_da_info_stmt);
// Use get_result for *, bind_result for specific columns
mysqli_stmt_bind_result($ret_da_info_stmt, $active_da, $completed_da);
mysqli_stmt_fetch($ret_da_info_stmt);
echo "u_n_i: ".$user_nation_information['active_da']." <br>";
$updated_cda_str = ($completed_da .= ",".$active_da);
}
mysqli_stmt_close($ret_da_info_stmt);
$update_compl_with_active_sql = "UPDATE `nations` SET `completed_da` = ? WHERE `nations`.`user_id` = ?;";
$update_compl_with_active_stmt = mysqli_stmt_init($connect);
if(!mysqli_stmt_prepare($update_compl_with_active_stmt, $update_compl_with_active_sql)) {
echo "Statement 2 Failed";
} else {
mysqli_stmt_bind_param($update_compl_with_active_stmt, "si", $updated_cda_str, $user_data['id']);
mysqli_stmt_execute($update_compl_with_active_stmt);
$set_active_zero_sql = "UPDATE `nations` SET `active_da` = ? WHERE `nations`.`user_id` = ?;";
$set_active_zero_stmt = mysqli_stmt_init($connect);
$zero = 0;
if(!mysqli_stmt_prepare($set_active_zero_stmt, $set_active_zero_sql)) {
echo "Statement 2 Failed";
} else {
mysqli_stmt_bind_param($set_active_zero_stmt, "ii", $zero, $user_data['id']);
mysqli_stmt_execute($set_active_zero_stmt);
}
mysqli_stmt_close($set_active_zero_stmt);
}
mysqli_stmt_close($update_compl_with_active_stmt);
mysqli_close($connect);
}
Here is my table before the function is run:
Before
Table after function has run:
After
When run, the debugging echos I used to check to see if the 'active_da' is set correctly produces this result (the 4 is the button ID, they are just triggers for the function for now):
Results from echo
My question is, how can I just simply transfer the 'active_da' column onto the end of the 'completed_da' column without adding that extra zero?
EDIT: I believe this is the query that's throwing it off
$set_active_zero_sql = "UPDATE `nations` SET `active_da` = ? WHERE `nations`.`user_id` = ?;";
$set_active_zero_stmt = mysqli_stmt_init($connect);
$zero = 0;
if(!mysqli_stmt_prepare($set_active_zero_stmt, $set_active_zero_sql)) {
echo "Statement 2 Failed";
} else {
mysqli_stmt_bind_param($set_active_zero_stmt, "ii", $zero, $user_data['id']);
mysqli_stmt_execute($set_active_zero_stmt);
}
I have this code on "insert.php":
if ($stmt = $GLOBALS['mysqli']->prepare("INSERT INTO table1(iduser, title, msg, anonim, ip, iduniversity) VALUES (?,?,?,?,?,?)")) {
$stmt->bind_param("issisi", $_SESSION['iduser'], $_POST['title'], $_POST['msg'], $anonim, getIP(), $_SESSION['iduniversity']);
if ($stmt->execute()) {
$idmsg = $GLOBALS['mysqli']->insert_id;
$i = 0;
$stmt2 = $GLOBALS['mysqli']->prepare("INSERT INTO tag(idmsg, tag) VALUES(?,?)");
foreach ($tags as $tag) {
if ($tag != '') {
$stmt2->bind_param("is", $idmsg, $tag);
if ($stmt2->execute()) {
$i++;
}
}
}
$stmt2->close();
$stmt->close();
mysqli_close($GLOBALS['mysqli']);
sendFile($idmsg);
header("Location: /public/watch_msg.php?idmsg=" . $idmsg);
exit();
} else {
exit("Ops! Ocorreu algum erro. COD1370");
}
} else {
exit("Ops! Ocorreu algum erro. COD1371");
}
So, everything is working fine, except that sometimes when it redirects to "watch_msg.php" the message seems not to be on the database yet. When this happens, as soon as I refresh the page, everything is there!
First thing I thought is that there could be a race-condition somewhere, but I read in another question that PHP is sequential, and as I close both statements and connection before the redirect (so that used tables should be unlocked), why i'm getting this result somethimes? What i'm doing wrong?
Also, no functions outputs anything, but "sendFile" saves an image if the user sends one, so headers should be fine (it also gives me the error when I comment the function).
Code on watch_msg:
$msg = NULL;
$tags = NULL;
$coments = NULL;
$data_high = date("Y-m-d H:i:s");
$iduser;
if ($loggedin) { //If logged in
$idmsg = filter_input(INPUT_GET, 'idmsg', FILTER_SANITIZE_STRING);
$iduser = $_SESSION['iduser'];
$query = "SELECT * FROM table1 WHERE iduser = ? AND idmsg = ? AND datemsg < ?";
$stmt = $GLOBALS['mysqli']->prepare($query);
$stmt->bind_param("iis", $iduser, $idmsg, $data_high);
if ($stmt->execute()) {
$msg = mysqli_fetch_assoc($stmt->get_result());
if ($msg === NULL) {
exit('This message doesn\'t exists');
}
...
} else {
echo "Error.";
}
}
Here is my script structure:
try {
$dbh_conn->beginTransaction();
$stmt1 = $dbh_conn->prepare("SELECT user_id FROM activate_account WHERE token = ?");
$stmt1->execute(array($validate_activate_token));
$num_rows = $stmt1->fetch(PDO::FETCH_ASSOC);
if($num_rows) {
$user_id = $num_rows['user_id'];
$stmt2 = $dbh_conn->prepare("UPDATE users SET active = 1 WHERE id = ?");
$stmt2->execute(array($user_id));
$updated = $stmt2->rowCount();
if ( $updated > 0 ){
$stmt3 = $dbh_conn->prepare("DELETE FROM activate_account WHERE token = ?");
$stmt3->execute(array($validate_activate_token));
$status = "all fine";
} else {
$status = "first problem";
}
} else {
$status = "second problem";
}
$dbh_conn->commit();
echo $status;
die;
} catch(PDOException $e) {
$dbh_conn->rollBack();
$status = "third problem";
echo $status;
die;
}
The result of my code always is second problem. Why? And how can I rewrite my code to fix it?
Note that I've tested this condition if($num_rows) { separately (in another script singly) and it is true, but when I write it into script above, it is always false.
The purpose of transactions is to make sure that queries that must happen together are never broken up. In your use case, the first query can be executed in isolation with no downside.
Put the last two in a transaction, but leave the first alone. If the first fails, just don't run the other two.
If the first succeeds but one of the other two (in the transaction) fails so that neither of the two is committed, you're no worse off for having executed the first.
Happy New Year to all. I need to point out I am trying to use PDO exclusively and I'm a relative noob to using PDO, so please excuse the question if it appears plainly obvious.
I'm having a bit of a stupid moment because I cannot seem to understand a few things as to why a relatively simple email validation system I have (tried) to write is not quite working correctly. Everything is ok until the php at the end of the validation link is setting the email address as being validated. Here is my code, followed by questions:
Firstly I have an include file that holds the DB login. It looks like this:
<?php
// DATABASE SETTINGS
$hostname = "127.0.0.1";
$username = "devProduction";
$password = "ienx3rybcisuc";
$database = "devProduction";
try {
$conn = new PDO("mysql:host=$hostname; dbname=$database", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->exec("SET CHARACTER SET utf8"); // Sets encoding UTF-8
// close the database connection (removed as I do this at the end of each call)
//$conn = null;
} catch(PDOException $e) {
echo $e->getMessage();
}
?>
And then in the page that actually received the user after they click on the link sent out to their email:
<?php
// Grab our includes
include '../conf/Funcs.php';
include '../conf/DBconfig.php'; // (This is the file displayed above)
require_once '../conf/Mobile_Detect.php';
// Check out what device is looking at us
$detect = new Mobile_Detect;
$deviceType = ($detect->isMobile() ? ($detect->isTablet() ? 'tablet' : 'phone') : 'computer');
$scriptVersion = $detect->getScriptVersion();
// Check to see if we are already logged in under an already validated account
if(isset($_COOKIE['AGMARDTuid']) || isset($_COOKIE['AGMARDTtoken'])) {
logout();
header("Location: ../");
exit;
} else {
$val = base64url_decode($_GET['val']);
$val = explode(":-:", $val);
$uid = $val[0];
$add = $val[1];
$key = $val[2];
// These are the three items that are pulled out of the URL $val value. This works fine
// It's only here to check it's working ok for the moment
echo "uid: ".$uid."<br>add: ".$add."<br>key: ".$key."<br><br>";
// Kill the process if either of the three values - $uid, $add, $key - are empty
if(($uid == "") || ($uid == NULL) || ($add == "") || ($add == NULL) || ($key == "") || ($key == NULL)) {
logout();
header("Location: ../");
exit;
} else {
// Seems everything is in order for email validation, so lets validate
$yes = "yes";
$NULL = NULL;
try {
$stmt = $conn->prepare("UPDATE $database.users SET `emailValidated` = :validate, `emailValidationKey` = :newkey WHERE `uid` = :uid AND `email` = :add AND `emailValidationKey` = :key");
$stmt->bindParam(':uid', $uid);
$stmt->bindparam(':add', $add);
$stmt->bindParam(':key', $key);
$stmt->bindParam(':validate', $yes);
$stmt->bindParam(':newkey', $NULL);
$stmt->execute();
$result = "success";
} catch(PDOException $e) { catchMySQLerror($e->getMessage()); $result = "fail"; }
$conn = null;
echo "result: ".$result." (post sql)<br><br>";
if($result == "fail") {
echo "Email did not successfully validate, there was a problem<br><br>";
echo $conn . "<br>" . $e->getMessage();
} else if($result == "success"){
echo "Email successfully validated<br><br>";
echo $conn . "<br>" . $e->getMessage();
}
echo "<br><br>We got to the end!";
}
}
?>
The code works, kinda. The problem is, if there is NOT an account within the database that matches all three values passed to the script from the URL, it still displays as having updated (validated) an account, even though it has not. Why is this?
Also, for the section that I am binding some parameters, specifically these two:
$stmt->bindParam(':validate', $yes);
$stmt->bindParam(':newkey', $NULL);
Why do I seem to have to assign $yes = "yes"; and "$NULL = NULL; as variables beforehand? I did try:
$stmt->bindParam(':validate', 'yes');
$stmt->bindParam(':newkey', NULL);
and
$stmt->bindParam(':validate', yes);
$stmt->bindParam(':newkey', NULL);
and
$stmt->bindParam(':validate', 'yes');
$stmt->bindParam(':newkey', 'NULL');
all without success.
Answers and info and suggestions always welcome and appreciated. Thank you!
C
You should use bindValue instead bindParam when you want to pass a value (or the result of a function) in the prepared statement.
$id = 100;
$datas = array('a', 'b', 'c');
$stmt = $db->prepare("SELECT * FROM user WHERE id = :id AND status > :status AND justForExample = :other");
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->bindValue(':status', 1, PDO::PARAM_INT);
$stmt->bindValue(':other', implode("", $datas), PDO::PARAM_STR);
$stmt->execute();
The documentation to BindValue
The documentation to BindParam
More informations about the difference
I am creating an part of a website that deals with confirmation of a user subscribing to a newsletter.
I am having trouble with the usage on prepared statements when selecting data.
This is basically a check against information that was sent to the user in an email and retrieved by getting the info from the entered url.
So there is a string or 'key' in the database that is sent to the user in an email as a link to a page on my site with the users details appended to the url. The script checks to see if these keys match
The problem is that when I run the script it will trigger an error. This says "wrong key".
The key in the database ($dbkey) is the same as the key provided in the email link. which is the same key that is made into $key. The problem though, is that in the while loop an error is being triggered and $dbkeyis not being passed the data from the database :
Notice: Trying to get property of non-object in C:\wamp\www\site\script.php on line 35
The sql statement when run in phpmyadmin does return the correct result set.
Here is the code:
$confirm= sanitize($_GET['confirm']);
$stmt = $link->prepare("SELECT id, dbkey FROM specials WHERE id = ?");
if (!$stmt)
{
$error = "{$link->errno} : {$link->error}";
include "$docRoot/html/main/error.html.php";
exit();
}
if (!$stmt->bind_param("i", $confirm))
{
$error = "{$stmt->errno} : {$stmt->error}";
include "$docRoot/html/main/error.html.php";
exit();
}
if (!$stmt->execute())
{
$error = "{$stmt->errno} : {$stmt->error}";
include "$docRoot/html/main/error.html.php";
exit();
}
$stmt->store_result();
if ($stmt->num_rows)
{
while ($row = $stmt->fetch())
{
$dbKey = $row->dbkey;
}
$key= sanitize($_GET['key']);
if ($dbKey !== $key)
{
echo 'wrong key';
}
}
else
{
echo 'not in database';
}
I would like to say that all other scripts connecting to the database in this manner do work, but this was the first time I have used prepared statements to select data. I wonder if this problem is caused by an error in my coding, hence the reason why I have posted this question.
If anyone could spot where I have gone wrong here, or possibly possibly provide some advice on how I would debug the code to see what exactly the error is that would be greatly appreciated!
Thanks!!
EDIT: The problem simply is the $key returns a string but $dbkey returns empty
EDIT2:
if ($stmt = $link->prepare("SELECT id, verified, dbkey FROM specials WHERE id=?")) {
$stmt->bind_param("i", $confirm);
$stmt->execute();
$stmt->bind_result($dbId, $dbVerified, $dbKey);
$stmt->fetch();
$stmt->close();
if ($dbKey !== $key)
{
echo 'wrong key';
}
else if ($dbVerified == 1)
{
echo 'already activated';
}
else if ($dbKey == $key && dbVerified == 0)
{
echo 'success';
}
}
else
}
echo 'user not in db';
}
$stmt->fetch() just returns a boolean indicating whether it was successful, not an object whose properties are the current row's fields. You need to call $stmt->bind_result() to specify into which variables you want the fields to be placed.
The approach taken in your second edit looks good, except that the test for whether the user is in the database should be onfetch(), not prepare() (or else use num_rows as you had previously). Thus:
if ($stmt = $link->prepare("SELECT id, verified, dbkey FROM specials WHERE id=?"))
{
$stmt->bind_param("i", $confirm);
$stmt->execute();
$stmt->bind_result($dbId, $dbVerified, $dbKey);
if ($stmt->fetch())
{
if ($dbVerified == 1)
{
echo 'already activated';
}
else if ($dbKey !== $key)
{
echo 'wrong key';
}
else if ($dbKey == $key && dbVerified == 0)
{
echo 'success';
}
}
else
}
echo 'user not in db';
}
$stmt->close();
}