© 2026 Laravel

Catch Specific Exceptions (Bắt exception đúng loại)

3 phút đọc 31 lượt xem

#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