#Nguyên tắc cốt lõi
👉 Chỉ catch những exception bạn hiểu và có thể xử lý
👉 Không bao giờ catch \Exception hoặc \Throwable trừ khi ở boundary (top-level)
#Bad Example (Anti-pattern)
try {
$user = $repository->find($id);
$mailer->sendWelcome($user);
} catch (\Exception $e) {
return null; // Nuốt toàn bộ lỗi
}
#Vấn đề
- Không biết lỗi gì xảy ra
- Bug bị che giấu
- Debug cực khó
try {
$result = $service->process($data);
} catch (\Throwable $e) {
return 'Something went wrong';
}
#Nguy hiểm
- Catch luôn cả
Error(TypeError, OOM…) - Che mất lỗi nghiêm trọng của hệ thống
#Good Example (Best Practice)
#1. Catch cụ thể
try {
$user = $repository->find($id);
$mailer->sendWelcome($user);
} catch (UserNotFoundException $e) {
$logger->warning('User not found', ['id' => $id]);
return null;
} catch (MailerException $e) {
$logger->error('Email failed', ['error' => $e->getMessage()]);
}
#2. Multi-catch (PHP 8+)
try {
$data = $api->fetch($endpoint);
} catch (ConnectionException |TimeoutException $e) {
throw new ServiceUnavailableException('External down', previous: $e);
}
👉 Gộp các exception có cùng cách xử lý
#3. Top-level boundary
try {
$response = $kernel->handle($request);
} catch (\Throwable $e) {
$logger->critical('Unhandled exception', [
'message' => $e->getMessage(),
]);
return new Response('Internal Server Error', 500);
}
👉 Đây là nơi DUY NHẤT nên catch rộng
#Giải thích sâu (Senior mindset)
#1. Swallowing Exception = Bug
Nếu bạn catch mà không:
- log
- rethrow
👉 bạn đang che bug
#2. Exception Flow Design
Flow chuẩn:
- Domain throw exception
- Application decide xử lý
- Infrastructure log
- Boundary trả response
#3. Khi nào KHÔNG nên catch?
👉 Khi bạn không biết xử lý
→ để exception bubble up
#4. previous exception (rất quan trọng)
throw new ServiceException('API fail', previous: $e);
👉 Giữ full trace chain
#5. Error vs Exception
- Exception: business / logic
- Error: system (TypeError, Memory)
👉 Không nên catch Error trừ khi ở boundary
#Tips & Tricks
#1. Rule đơn giản
👉 “Can I handle it?”
- Yes → catch
- No → throw
#2. Always log khi catch
$logger->error(...);
#3. Không return silent
catch (...) {
return null;
}
#4. Laravel best practice
- Không catch trong service nếu không cần
- Dùng global handler
#5. Retry strategy
Chỉ retry với:
- Timeout
- Connection
Không retry với:
- Validation
#Interview Questions
1. Tại sao không nên catch Exception chung?
Summary:
- Che bug
Deep: Không biết lỗi gì xảy ra → khó debug, sai logic xử lý
2. Khi nào nên catch Throwable?
Summary:
- Ở top-level
Deep: Controller, middleware, worker → để tránh crash toàn hệ thống
3. Multi-catch là gì?
Summary:
- Bắt nhiều exception cùng lúc
Deep:
PHP 8 hỗ trợ catch (A | B $e) → giảm duplicate code
4. previous exception dùng để làm gì?
Summary:
- Giữ trace
Deep: Giúp debug chain exception đầy đủ
5. Khi nào nên để exception bubble up?
Summary:
- Khi không xử lý được
Deep: Để tầng trên handle đúng context
#Kết luận
- Catch sai = bug ẩn
- Catch đúng = hệ thống rõ ràng, dễ debug, production-ready