d7DetectabilityOperational debt — how invisible misuse is to your safety net
Closest to 'only careful code review or runtime testing' (d7). Blackfire (listed) can detect performance cost in hot paths, but no linter flags reflection misuse by default; phpstan won't catch unchecked reflection use. Usually requires profiling or review.
e5EffortRemediation debt — work required to fix once spotted
Closest to 'touches multiple files / significant refactor in one component' (e5). Removing reflection from hot paths typically requires adding metadata caching layers or replacing with compiled containers — not a one-liner per quick_fix guidance.
b5BurdenStructural debt — long-term weight of choosing wrong
Closest to 'persistent productivity tax' (b5). applies_to spans web/cli/queue and reflection often becomes load-bearing infrastructure in DI/ORM layers; touches many work streams but doesn't fully define system shape.
t5TrapCognitive debt — how counter-intuitive correct behaviour is
Closest to 'notable trap, documented gotcha' (t5). The misconception (only for framework devs) plus the non-obvious performance cost and encapsulation-breaking behavior are well-known gotchas most PHP devs eventually learn.
PHP's built-in introspection system for examining classes, methods, properties, and parameters at runtime.
Explanation
The PHP Reflection API (ReflectionClass, ReflectionMethod, ReflectionProperty, ReflectionFunction, ReflectionParameter) enables runtime inspection of code structure — reading type declarations, attributes, docblocks, visibility, and default values without invoking the code. It underpins dependency injection containers (resolving constructor parameters), ORM hydration, serialisation libraries, and testing frameworks. Reflection is powerful but has a performance cost — production DI containers cache reflection results. PHP 8.0 Attributes provide a structured, performant alternative to docblock-parsed metadata.
Common Misconception
✗ The Reflection API is only useful for framework developers. Reflection enables runtime code generation, attribute processing, dependency injection containers, test mocking, and documentation generation — it is the backbone of most modern PHP frameworks.
Why It Matters
The Reflection API gives runtime access to class structure, docblocks, and attributes — it powers dependency injection containers, ORMs, and testing frameworks, but has non-trivial performance cost.
Common Mistakes
Using Reflection in hot code paths without caching results — ReflectionClass instantiation is expensive.
Not caching reflected class metadata in a DI container — reflecting the same class on every request adds measurable overhead.
Using Reflection to access private members of other classes in production code — breaks encapsulation.
Not using PHP 8 Attributes instead of docblock parsing when possible — native attributes are faster and type-safe.
Code Examples
✗ Vulnerable
// Uncached reflection in a hot path:
function resolve(string $class): object {
$ref = new ReflectionClass($class); // Expensive — not cached
$params = $ref->getConstructor()->getParameters();
// ... inject dependencies
}
✓ Fixed
// Inspect class structure at runtime
$ref = new ReflectionClass(OrderService::class);
echo $ref->getName(); // 'App\Domain\OrderService'
echo $ref->getShortName(); // 'OrderService'
$methods = $ref->getMethods(ReflectionMethod::IS_PUBLIC);
$constructor = $ref->getConstructor();
// Read PHP 8.0+ attributes:
foreach ($ref->getMethods() as $method) {
foreach ($method->getAttributes(Route::class) as $attr) {
$route = $attr->newInstance();
echo $route->path;
}
}
// Instantiate without constructor (DI containers, test fixtures):
$instance = $ref->newInstanceWithoutConstructor();
🧱FUNDAMENTALS— new to this? Start with the ground floor.
PHPphpA server-side scripting language that generates web pages and APIs — the code runs on the server, and only its output (usually HTML or JSON) reaches the browser.
PHP is often the first server-side language people meet, and understanding its execution model — script starts fresh on every request, no memory between requests — explains most of how the web backend works: sessions, databases, and caching all exist to bridge that per-request amnesia.
💡 Start with PHP 8.x, declare(strict_types=1), and PDO — skip any tutorial that mentions mysql_query().
Use PHP's Reflection API for framework-level metaprogramming (DI containers, ORMs, test mocking) — avoid using it in application code as it bypasses encapsulation and is significantly slower