Using transactions for queries which have dependant results - php

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.

Related

Update reads successful in console, but the database is unaffected

Trying to update a record using PHP and PDO statements.
The query fires with no errors, and the console reads the update was successful, but there is no change in the table.
So confused as to why this is happening:
<?php
include("../include/sessions.php");
if(isset($_POST['editcriteria']))
{
$value = $_POST['editcriteria'];
$editUID = $value['editUID'];
$editAddDelete = $value['editAddDelete'];
$editeffectiveDate = $value['editeffectiveDate'];
try
{
$update = $conn->prepare("UPDATE primary_vehicle_data SET `add_delete` = :eadddelete,
`effective_date` = :eeffectivedate WHERE `uid` = :euid");
$update->execute([
'eadddelete' => $editAddDelete,
'eeffectivedate' => $editeffectiveDate,
'euid' => $editUID
]);
if($update)
{
echo "Success: Record Updated";
}
else
{
echo "Error: The Vehcile was not updated.";
}
}
catch(PDOException $e)
{
echo "Error: " . $e->getMessage();
}
}
?>
I simplified the above code as much as possible. There were several more parameters, but when I removed the parameters and left it with the 3 parameters above, I still get "Success: Record Updated". But the table is literally unaffected.
Why is this happening and how do I fix it?
* UPDATE *
I already confirmed the connection to the database is good. I'm lost.
$update is a PDOStatement object, so when you test
if ($update)
it will always succeed as a PDOStatement object is equivalent to true.
You should be:
checking the result of $update->execute e.g.
if ($update->execute([ /* params */])) {
checking the value in $update->rowCount, which will tell you if any rows were affected by the query.

Can anyone tell me if they see an error in the following PHP code?

For some reason, the while loop below never fires.
All of this is inside a class.
$code = $this->get_postal_state_no('Western Cape');
private function get_postal_state_no($psn)
{
$sql = "
SELECT
no
FROM
ct_state
WHERE
name LIKE('".$psn."');";
$stmt = sqlsrv_query($this->conn1, $sql);
// This statement is not false, so the error handling does not happen, this is expected.
if($stmt === FALSE)
{
if(($errors = sqlsrv_errors()) != NULL)
{
foreach($errors as $error)
{
$sqlstate = $error['SQLSTATE'];
$code = $error['code'];
$sqlmessage = $error['message'];
}
}
$msg = 'Error in $stmt in get_postal_state_no() method.';
$this->do_error_log($error_msg, $sqlstate, $code, $sqlmessage, $msg, __LINE__, __FILE__, __FUNCTION__, __CLASS__, __METHOD__);
sqlsrv_free_stmt($stmt);
}
//This loop is never entered. This is not expected.
while($obj = sqlsrv_fetch_object($stmt))
{
echo "I am here now";
break;
if(!empty($obj->no) && $obj->no != '')
{
echo "Hello, I exist";
break;
// This break never happens
return $obj->no;
}
else
{
echo "Hello, I don't exist";
break;
// This break never happens
$code = $this->sp_aa_iud_ct_state($psn);
return $code;
}
sqlsrv_free_stmt($stmt);
}
}
Does anyone have an idea why? I am using the php_sqlserv driver. The SQL server profiler shopws the query for the first part executing.
Thanks
J
Looking at the documentation page for sqlsrv_fetch_object it says this about the return value:
Returns an object on success, NULL if there are no more rows to return, and FALSE if an error occurs or if the specified class does not exist.
I suspect the function is either returning NULL or FALSE, though the reasons are a little unclear. Try adding this above the while loop and see what the output is:
$obj = sqlsrv_fetch_object($stmt)
var_dump($obj);
die;
while($obj = sqlsrv_fetch_object($stmt))
{ // ...
Another helpful debugging trick is to dump out the query and then copy/paste it into your DBMS system and run the query you are executing in code directly against your database to see if any results are actually being returned:
$sql = "
SELECT
no
FROM
ct_state
WHERE
name LIKE('".$psn."');";
var_dump($sql);

Adding input from textfield to database

I try to add datas which are taken from a textfile to my database with a php script, here is the script:
foreach($lines as $name){
$bolunmus=explode(" ", $name);
$add = false;
if(!exist_in_db($bolunmus[0], $bolunmus[1], $bolunmus[2])){
$add = mysql_query("
INSERT INTO people(name, surname, age)
VALUES('$bolunmus[0]', '$bolunmus[1]', '$bolunmus[2]');", $con);
}
else{
echo (" could not write it.<br>");
}
if($add)
echo $bolunmus[0]." ".$bolunmus[1]." ".$bolunmus[2]." Added to database.";
}
// this is my control function, which will return
// true if data already exist in database,
// else it will return false.
function exist_in_db($name, $surname, $age){
$result = mysql_query("
SELECT * FROM people ORDER BY id
");
while($row = mysql_fetch_array($result)){
if($row['name']==$name && $row['surname']==$surname || $row['age']==$age){
echo $row."could not write it.";
return true;
}else{
return false;
}
}
}
?>
in fact, the problem is when I try to execute this script, it reads from textfile, and if that user does not exist, it adds, until here there is not any problem. But when I try to execute it again, it adds users with same output like "bla bla 0 is added to database." If I don't make any changes in text-file, I want it to control again, and if that user exists, do not add it, thanks everybody.
if($row['name']==$name && $row['surname']==$surname || $row['age']==$age)
^ ^
There should be a bracket here.
if(($row['name']==$name && $row['surname']==$surname) || $row['age']==$age)
To debug further, try var_dump($bolunmus);

PHP script to check If user already exists in MySQL database

I'm creating simple game for Facebook. All users who used app are written to database. I need always check If user already exists Is in database, how to do that correctly?
So I have variable $name = $user_profile['name']; It successfully returns user's name
And this is my part of code to check If user already exists in database.
$user_profile = $facebook->api('/me');
$name = $user_profile['name'];
$mysqli = new mysqli("host","asd","pw","asdf");
echo "1";
$sql = "SELECT COUNT(*) AS num FROM myTable WHERE userName = ?";
echo "2";
if ($stmt = $mysqli->prepare($sql)) {
echo "3";
$stmt->bind_param('s', $name);
echo "4";
$stmt->execute();
echo "5";
$results = $stmt->get_result();
echo "6";
$data = mysqli_fetch_assoc($results);
echo "7";
}
if($data['num'] != 0)
{
echo "bad";
print "user already exists\n";
} else {
echo "good";
$apiResponse = $facebook->api('/me/feed', 'POST', $post_data);
print "No user in database\n";
}
}
This code not working, It should post data on user's wall If user not exists in database. I spent many time to find reason why, but unsuccessfully. After debugging It don't show any errors. To find which line is incorrect after every line I used echo "number" so now I know which line is incorrect. It prints 1 2 3 4 5 and stucks. (everything what are below the code not loading.) So that means this line $results = $stmt->get_result(); is incorrect. But I misunderstood what's wrong with this line?
If I comment this line all code loading (then print 1 2 3 4 5 6 7 No user in database! and It post data on user's wall.) but in this case program always do the same, not checking database.
Also I've tried to change COUNT(*) to COUNT(userName), but the same.
So could you help me, please?
I've read this: Best way to check for existing user in mySQL database? but It not helped me.
P.s. In this case i need to use FB username.
Can you try this, $stmt->fetch() instead of mysqli_fetch_assoc($results)
$mysqli = new mysqli("host","asd","pw","asdf");
echo "1";
/* Create the prepared statement */
$stmt = $mysqli->prepare("SELECT COUNT(*) AS num FROM myTable WHERE userName = ?") or die("Prepared Statement Error: %s\n". $mysqli->error);
/* Execute the prepared Statement */
$stmt->execute();
/* Bind results to variables */
$stmt->bind_result($name);
$data = $stmt->fetch();
if($data['num'] > 0)
{
echo "bad";
print "user already exists\n";
} else {
echo "good";
$apiResponse = $facebook->api('/me/feed', 'POST', $post_data);
print "No user in database\n";
}
/* Close the statement */
$stmt->close();
Ref: http://forum.codecall.net/topic/44392-php-5-mysqli-prepared-statements/

Issues using php's PDOStatement::execute/fetch/rowCount to test existence of values in database?

I'm having an issue with one of my classes (I believe). On a high level, I'm sending a form to a php file that initiates a class. By accessing several of it methods, it determines whether or not a value is in the database. If it is, it returns a boolean.
Here's the code that I believe is the issue:
public function territoryCheck($numberOut)
{
$this->numberOut = $numberOut;
//Execute test
$this->checkConnect();
$stmt = $this->dbh->prepare("SELECT t_id FROM Territory WHERE t_id = :param1");
$stmt->bindParam(':param1', $this->numberOut);
$stmt->execute();
$count = $stmt->rowCount();
//Determine value of test
if($count == 0)
{
return FALSE;
}
}
public function publisherCheck($lName, $fName)
{
$this->lName = $lName;
$this->fName = $fName;
//Execute test
$this->checkConnect();
$stmt = $this->dbh->prepare("SELECT p_id FROM People WHERE lastName = :param1 AND firstName = :param2");
$stmt->bindParam(':param1', $this->lName);
$stmt->bindParam(':param2', $this->fName);
$stmt->execute();
$count = $stmt->rowCount();
//Determine value of test
if($count == FALSE)
{
return FALSE;
}
else
{
$dummyvar = $stmt->fetch();
$this->p_id = implode($dummyvar);
}
}
public function isTerritoryOut($numberOut)
{
//Execute test
$this->checkConnect();
$this->numberOut = $numberOut;
$stmt = $this->dbh->prepare("SELECT t_id FROM checkIn WHERE t_id = :param1");
$stmt->bindParam(':param1', $this->numberOut);
$stmt->execute();
$count = $stmt->rowCount();
//Determine value of test
if($count != 0)
{
return TRUE;
}
}
There are three methods, each are a test that will return either true or false.
I was testing with execute(), fetch(), and finally rowCount() to try to emulate the values I want. Neither seem to work. Here's the code that calls these methods:
//Begin tests
$checkOut->territoryCheck($numberOut);
if($checkOut == FALSE)
{
$fail = "Territory number ".$numberOut." does not exist in our records. Please enter a valid territory. For more information, navigate to About.<\ br>";
}
$checkOut->publisherCheck($lName, $fName);
if($checkOut == FALSE)
{
if($fail !== "")
$fail .= "The publisher, ".$fName." ".$lName.", is not in our records. For more information, navigate to About.<\ br>";
else
$fail = "The publisher, ".$fName." ".$lName.", is not in our records. For more information, navigate to About.<\ br>";
}
$checkOut->isTerritoryOut($numberOut);
if($checkOut === TRUE)
{
if($fail !== "")
$fail .= "Territory number ".$numberOut." is currently checked out. Either the wrong number was entered or the territory hasn't been properly checked in.<\ br>";
else
$fail = "Territory number ".$numberOut." is currently checked out. Either the wrong number was entered or the territory hasn't been properly checked in.<\ br>";
}
For clarity, fail was set to "" earlier in the code. What happens is that it goes through all of these tests as if they had passed when I purposely create situations that should have failed. For instance, I only have territory numbers 1-130 in my database. If I put in 150, it essentially tells me that it exists.
I'm not sure what is going on, typecasting? == vs. ===?, etc.
Any help is appreciated.
I must admit, the cause is a rather obvious question that is so obvious I didn't even consider it. In each test, I simply call the method without assigning any variable to accept the return value(i.e $checkOut->publisherCheck(); instead of $test = $checkOut->publisherCheck();. Regardless, it works now.

Categories