I'm trying to get my head around PDO transactions to commit a fairly complex set of MySQL queries at once. When I run the transaction however, it will commit one query and not the other - if there is a single error in either query I expect it to roll back both queries and not make changes to either table.
So far: My connect.php file:
class DbConnect {
private $conn;
function __construct() {
}
/**
* Establishing database connection
* @return database connection handler
*/
function connect() {
//Where HOST, USER, PASS etc are set
include_once "./dbconfig.php";
// Establish the connection
try {
$this->conn = new PDO("mysql:host=".HOST.";dbname=".DBNAME, USER, PASS);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
return $this->conn;
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
}
}
My file where I'm trying to pass the simultaneous SQL queries
public function transaction ($userId, $amount){
//Creates the PDO connection EDIT: added my DB connection
$db = new DbConnect();
$this->conn = $db->connect();
$con = $this->conn;
$con->beginTransaction();
try{
$sql = "INSERT INTO transactions (id_user, amount) VALUES (?, ?)";
$trans = $con->prepare($sql);
$trans->execute([$userId, $amount]);
//If I purposely create an error here the query above still runs in the database e.g. remove the $amount variable
$this->updateBalance($userId, $amount);
$con->commit();
return true;
}
catch (PDOException $e) {
$con->rollBack();
throw $e;
}
}
private function updateBalance ($userId, $amount){
$time = time();
$sql = "UPDATE balance SET balance=balance + ? WHERE user_id = ?";
$stmt = $this->conn->prepare($sql);
$stmt->execute([$amount, $userId]);
$row_count = $stmt->rowCount();
return $row_count > 0;
}
The above is just a small sample of a bigger more complex procedure otherwise I'd just put the balance query in the same place as the transaction, however I need to keep it in a separate function. Any ideas how I can get this into an "All or nothing" commit state?