Exception Handling Introduced (PHP 5)
debt(d7/e3/b3/t5)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints list phpstan as the tool, but automated is explicitly 'no'. Common mistakes like swallowing exceptions (empty catch blocks) or catching generic Exception instead of specific types are not reliably caught by default linting — phpstan can detect some patterns but requires careful configuration and manual review to catch the full range of misuse. Silent swallowing in production is the worst case.
Closest to 'simple parameterised fix' (e3). The quick_fix describes replacing die()/return false with throw, catching specific types, and re-throwing with context. These are pattern replacements within a component — not single-line trivial fixes, but not cross-cutting architectural rework either. Fixing swallowed exceptions or overly broad catches is a repeated but localised refactor.
Closest to 'localised tax' (b3). Exception handling applies broadly (web, cli, queue-worker) but the common mistakes (swallowed exceptions, wrong catch granularity) impose a tax primarily on the components where they occur rather than shaping the entire codebase. It does not have strong gravitational pull across the architecture.
Closest to 'notable trap' (t5). The misconception field identifies that developers misunderstand finally — believing it only runs after catch, when in fact it runs whether or not an exception was thrown, and even after return in try/catch. This is a documented gotcha that most developers eventually learn, consistent with the t5 anchor. Additionally, swallowing exceptions and using exceptions for flow control are well-known but non-obvious pitfalls.
TL;DR
Explanation
PHP 5 (2004) added: try { } catch (ExceptionType $e) { } finally { }. The Exception base class with getMessage(), getCode(), getFile(), getLine(), getTrace(). Custom exceptions via class MyException extends Exception. PHP 4 had no try/catch — errors were handled with die(), trigger_error(), or return codes. The shift to exceptions enabled frameworks to build proper error handling. PHP 5.1 added set_exception_handler(). PHP 7 unified exceptions and errors under Throwable. Key principle: throw exceptions for exceptional conditions, not for flow control.
Common Misconception
Why It Matters
Common Mistakes
- Catching generic Exception when specific subclasses should be caught.
- Using exceptions for flow control (throwing to exit loops).
- Swallowing exceptions: catch(Exception $e) {} with empty body.
- Not using finally for cleanup (DB connections, file handles).
Code Examples
// PHP 4 style — checking return values:
$result = connectDb();
if ($result === false) { die('DB failed'); }
try {
$pdo = new PDO($dsn, $user, $pass);
} catch (\PDOException $e) {
throw new DatabaseConnectionException(
'Could not connect to database',
previous: $e
);
} finally {
// Cleanup always runs
}