Here’s the problem: When a script starts modifying the database and something goes wrong, the database is usually corrupted. For example, lets say we have a User table and a Photos table.
A script creates a user dataset and in the next lines it attempts to create a photo dataset. The photo has a user_id column. Now lets assume something goes wrong and PDO’s lastInserId() doesn’t return the id of the user. So what happens in worst case: We get a user with no photo, and a photo with no valid user_id. Broken reference. 3 weeks to debug.
Are there any good strategies to follow, to prevent exactly this kind of problems? In my code below, you can see that I at least try to log that to a file and quit the script execution to prevent more damage and db curruption.
public function lastInsertId() {
$id = $this->dbh->lastInsertId();
if (!is_numeric($id)) {
$this->logError("DB::lastInsertId() did not return an id as expected!");
die();
}
return $id;
}
Maybe I have to use Transactions all over the place, at any time where an query B depends on a query A, and so forth? Is that the solution to go?
Should I do a “precaution rollback” before the die() call? I guess it would not hurt much at this point, would it? I’m not sure…
The solution would be to use transactions each time you have several queries for which it should be “all or none”, yes — that’s the A of ACID : Atomicity.
You can do a
rollbackbefore yourdie, if you want ; it won’t change much (a transaction that is not commited will automatically be rolled-back by the DB engine), but it will make your code more clear, and easier to understand.As a sidenote : using
diethis way is probably not the “right” way to deal with errors : it’ll prevent you from displaying any kind of “nice” error page, for instance.A solution that’s more often used is to have some kind of exception be thrown when there is such kind of problem — and in a higher layer of your application (in one single place) deal with those exceptions, to display an error page.