Где и как лучше прехватывать/обрабатывать исключения?
Хочу разобраться, как и где лучше/правильней обрабатывать исключения и что отдавать пользователю.
Есть код, он должен сохранить пользователя.
В этом примере мы можем получить Exception в 3 разных местах.
Как я сейчас представляю, обернуть вызов метода сервиса в контроллере в try catch. Поскольку в обязанность контроллера входит генерирование ответа пользователю в зависимости от результата. Но, меня смущают некоторые нюансы:
- В случаи большого количества возможных исключений методы контроллера превратятся в простыню из
catch. - Еще и ошибку нужно записать в лог.
Если обрабатывать ошибку по месту, возникает проблема в возврате обратно данных по цепочке. Это наплодит кучу if-ов и усложнит разные методы разными типами возврата.
Если поместить try catch в сервис и возвращать контроллеру к примеру User|false, как тогда контроллер будет генерировать ответ, если он не будет знать в чем проблема, в базе или в том, что это дубликат.
Может лучшим способом будет обрабатывать все ошибки через set_exception_handler?
class UserController
{
private UserSerivce $service;
public function store(array $data)
{
$user = $this->service->new($data);
return redirect()->to('/' . $user->id);
}
}
class UserSerivce
{
private UserRepository $repository;
public function new(array $data): User
{
$user = new User($data['name']); //InvalidArgumentException
$user = $this->repository->add($user);
return $user;
}
}
class UserRepository
{
public function __construct()
{
$this->builder = new PDO(''); //PDOException
}
public function add(User $user): User
{
$saved = $this->builder->query('INSERT INTO users (name) VALUES ("user")'); //PDOException
}
}
class User
{
private string $name;
public function __construct(string $name)
{
if (empty($name)) {
throw new InvalidArgumentException('Name is empty');
}
$this->name = $name;
}
}