As for architecture, which of the two is good practice when throwing exceptions from a model to a controller?
Structure A:
UserController.php
public function updateUserInfo(UserInfoRequest $request, UserModel $userModel) { $isError = false; $message = 'Success'; try { $message = $userModel->updateUserInfo($request->only(['username', 'password'])); } catch (SomeCustomException $e) { $isError = true; $message = $e->getMessage(); } return json_encode([ 'isError' => $isError, 'message' => $message ]); }
UserModel.php
public function updateUserInfo($request) { $isError = false; $message = 'Success'; $username = $request['username']; $password = $request['password']; try { $this->connect()->beginTransaction(); $this->connect()->table('users')->where('username', $username)->update(['password' => $password]); $this->connect()->commit(); } catch (\Exception $e) { $this->connect()->rollback(); $isError = true; $message = $e->getMessage(); } return [ 'isError' => $isError, 'message' => $message ]; }
Structure B:
UserController.php
public function updateUserInfo(UserInfoRequest $request, UserModel $userModel) { $isError = false; $message = 'Success'; try { $userModel->updateUserInfo($request->only(['username', 'password'])); } catch (SomeCustomException $e) { $isError = true; $message = $e->getMessage(); } catch (QueryException $e) { $isError = true; $message = $e->getMessage(); } return json_encode([ 'isError' => $isError, 'message' => $message ]); }
UserModel.php
public function updateUserInfo($request) { $username = $request['username']; $password = $request['password']; try { $this->connect()->beginTransaction(); $this->connect()->table('users')->where('username', $username)->update(['password' => $password]); $this->connect()->commit(); } catch (\Exception $e) { $this->connect()->rollback(); throw new QueryException(); } }
In Structure A, the model catches any exception, rolls back the transaction, and returns if it has an error or not for the controller. Then the controller returns only what is returned from the model.
In Structure B, the model catches any exception, rolls back the transaction, and throws a QueryException if an exception occurs. The controller then catches the received QueryException from the model, and then returns if it has an error or not.
The reason that Structure B still has a catch is because the model needs to be rolled back. If I were to remove the try-catch on the model here and the controller in order to immediately catch the exception, then the rollback would be handled on the controller, which, I think, clutters the functionality of the controller.
Let me know your thoughts. Thanks!