0

I need to insert data into 3 tables and need to get the id of last inserted query into shopper table. I know this is doable by running

$conn -> insert_id;

in a single query but in my case I need to create a transaction with rollback in case of any failure. something like

$conn = new mysqli(DBHOST, DBUSER, DBPASS, DBNAME);

$stmt1 = $conn->prepare("INSERT INTO shopper (usersID, parentJob, phoneNumber,address) VALUES (?, ?, ?, ?)");
$stmt1->bind_param("ssss", $userId, $parentJob, $phoneB, $addressB);

$stmt2 = $conn->prepare("INSERT INTO shipment (shipmentID, usersID,..) VALUES (?, ?, ?, ?)");
$stmt2->bind_param("ssss", $userId, ...);

$stmt3 = $conn->prepare("INSERT INTO address (addressID, usersID, ...) VALUES (?, ?, ?, ?)");
$stmt3->bind_param("ss", $userId, ...);

$conn->begin_transaction();
if ($stmt1->execute() && $stmt2->execute() && $stmt3->execute()) {
    $conn->commit();
} else {
    $conn->rollback();
}

$conn->close();

As you can see I am trying to pass last inserted usersID as Foreign Key into shipment and address tables. so how can I do this when committing all of them together like

if ($stmt1->execute() && $stmt2->execute() && $stmt3->execute()) {
    $conn->commit();
} else {
    $conn->rollback();
}
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
Behseini
  • 6,066
  • 23
  • 78
  • 125
  • Just get and pass. It has nothing to do with transactions – Your Common Sense May 18 '20 at 09:05
  • 1
    I see. Well you can make it `if ($stmt1->execute() && $userId = $conn->insert_id && $stmt2->execute() && $stmt3->execute()) {` but better configure mysqli to throw exceptions and get rid of this if condition at all. – Your Common Sense May 18 '20 at 09:26

1 Answers1

2

Exceptions offer enormous help with transactions. Hence configure mysqli to throw exceptions. Not only for transactions but because it's the only proper way to report errors in general.

With exceptions your code will be plain and simple

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$conn = new mysqli(DBHOST, DBUSER, DBPASS, DBNAME);
$conn->set_charset('utf8mb4');

$conn->begin_transaction();

$stmt = $conn->prepare("INSERT INTO shopper (usersID, parentJob, phoneNumber,address) VALUES (null, ?, ?, ?)");
$stmt->bind_param("sss", $parentJob, $phoneB, $addressB);
$stmt->execute();
$userId = $conn->insert_id;

$stmt = $conn->prepare("INSERT INTO shipment (shipmentID, usersID,..) VALUES (?, ?, ?, ?)");
$stmt->bind_param("ssss", $userId, ...);
$stmt->execute();

$stmt = $conn->prepare("INSERT INTO address (addressID, usersID, ...) VALUES (?, ?, ?, ?)");
$stmt->bind_param("ss", $userId, ...);
$stmt->execute();

$conn->commit();

in case of error an exception will be thrown and a transaction will be rolled back automatically.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345