Let's suppose there is model that performs some logic on saving object. This logic consists of db-transactions, some external services calls.
class ExampleModel {
//some field
//constructor and getters with setters
public function save() {
$db->beginTransaction();
$db->somequery();
$db->anotherone();
$object->externalApiCall();
$object->saveToCache();
}
}
My question is what is the best way to catch errors and make rollbacks?
Solution#1 Catch everything in the model, rollback there, log some information and re-throw error to a controller. Will look something like this:
class ExampleModel {
//some field
//constructor and getters with setters
public function save() {
try {
$db->beginTransaction();
$db->somequery();
$db->anotherone();
$object->externalApiCall();
$object->saveToCache();
} catch (DbException $e) {
$db->rollback();
$logger->log($e->getMessage());
throw $e
}
catch (ApiExcetpion $e) {
somelogic();
throw $e;
}
}
}
My main concern with this approach is that there is a lot of redundancy in writing try/catch blocks. For every composite method there will be try catch block.
Solution #2 Throw errors in a Model, and handle rollbacks/logging etc in a controller. This one I don't like because it breaks MVC pattern, and a controller becomes fat.
Solution #3 Binding error-listeners to an app instance so that they will handle exceptions according to their logic. Example:
class ExampleModel {
//some field
//constructor and getters with setters
public function save() {
$db->beginTransaction();
$db->somequery();
$db->anotherone();
$object->externalApiCall();
$object->saveToCache();
}
}
$app->bind_error_handler("DbTransactionException", function () {
rollback();
log();
return View::render("some error");
});
I overall like this approach because there are no numerous try/catch blocks. Controller is skinny and error logic is de-coupled from everything else. My concern with last approach is whether or not it is considered best practice. Also is this approach flexible and will it give me flexibility of a first approach?
Overall question: What is considered best practice in handling errors (transactional and other) in MVC world? And which solution from what I have provided is the best one?
Aucun commentaire:
Enregistrer un commentaire