Magic Strings
debt(d5/e3/b5/t5)
Closest to 'specialist tool catches it' (d5). The detection_hints list phpmd, phpcs, and phpstan — all specialist/linter-class tools rather than the compiler or a default linter. Repeated string literals across files can be flagged by these tools, but they require configuration and deliberate adoption. Not caught by the PHP compiler itself.
Closest to 'simple parameterised fix' (e3). The quick_fix describes replacing string literals with PHP 8.1 enums or class constants — a mechanical substitution pattern. For a single string it's trivial, but scattered usage across multiple call sites within a component typically requires a find-and-replace pass, landing it at e3 rather than e1.
Closest to 'persistent productivity tax' (b5). The applies_to covers web, cli, and queue-worker contexts — broad reach across the system. Common mistakes show magic strings scattered across the codebase affecting event names, config keys, status values, and error messages. Every future maintainer must search the codebase to find all usages, creating a persistent but not entirely system-defining tax.
Closest to 'notable trap — a documented gotcha most devs eventually learn' (t5). The misconception field explicitly states that developers believe magic strings are only a problem when repeated, missing that even a single unexplained string like 'pending' is a magic string. This is a well-known code-smell trap that most developers encounter and learn, but it's not catastrophic or contradicting another language's behavior.
Also Known As
TL;DR
Explanation
Magic strings are the string equivalent of magic numbers: inline string literals like 'admin', 'pending', or 'user_created' used as status values, event names, or configuration keys. They cause typo bugs that aren't caught until runtime, resist refactoring (no IDE rename support), and offer no context to readers. Replace them with constants, enums (PHP 8.1+), or class constants — these are findable, renameable, and document valid values in one place.
Common Misconception
Why It Matters
Common Mistakes
- Status values as strings scattered across the codebase: 'active', 'pending', 'inactive' — define as constants or enums.
- Event names as raw strings: event('user.created') — a typo in the listener silently misses the event.
- Config keys as inline strings repeated everywhere — one rename requires searching the whole codebase.
- Error message strings duplicated in multiple places — they diverge and give users inconsistent messages.
Code Examples
if ($user->role === 'admin') { /* typo risk */ }
if ($user->role === Role::ADMIN->value) { /* enum backed by string */ }