d3DetectabilityOperational debt — how invisible misuse is to your safety net
Closest to 'default linter catches the common case' (d3). The term's detection_hints list Rector and phpcs, both widely used in PHP projects. The code_pattern `create_function\(` is a straightforward regex match that phpcs/Rector catch automatically, and PHP 7.2+ itself emits deprecation warnings at runtime. This places it at d3 — common tooling catches it without specialist configuration.
e3EffortRemediation debt — work required to fix once spotted
Closest to 'simple parameterised fix (replace pattern with safer alternative)' (e3). The quick_fix explicitly says to replace with `function(){}` closures or `fn()` arrow functions and to run Rector, which automates the migration. This is a small, mechanical refactor — Rector handles most cases automatically, but a human must verify variable capture semantics and ensure no user input was involved. Slightly above e1 because variable capture (use() clauses) may require manual review.
b3BurdenStructural debt — long-term weight of choosing wrong
Closest to 'localised tax' (b3). The applies_to scope covers web and cli contexts broadly, but create_function() is typically a call-site smell rather than a load-bearing architectural choice. Each occurrence is an isolated liability; there is no systemic pull on the rest of the codebase. The burden is per-use-site rather than cross-cutting, keeping it at b3.
t7TrapCognitive debt — how counter-intuitive correct behaviour is
Closest to 'serious trap (contradicts how a similar concept works elsewhere)' (t7). The misconception field states explicitly that developers typically think this is only a performance issue, when in fact it is an eval-based code injection vector (potential RCE) and a static analysis blocker. A competent developer migrating from older PHP or coming from another dynamic language would naturally assume a 'function factory' helper is merely a convenience or performance concern — the security implication is non-obvious and contradicts the benign naming.
About DEBT scoring →
scored by claude-sonnet-4-6 · 2026-05-11 · reviewed by human
TL;DR
create_function() created anonymous functions from strings — deprecated PHP 7.2, removed PHP 8. It used eval() internally, risked code injection, and was always replaceable with proper closures.
Explanation
create_function('$x', 'return $x * 2;') compiled a string as PHP code using eval() under the hood. Problems: (1) RCE risk if any argument came from user input, (2) not analysable by static analysis, (3) worse performance than closures, (4) no IDE support. Deprecated PHP 7.2, removed PHP 8. Direct replacement: function($x) { return $x * 2; } or fn($x) => $x * 2. Rector handles the migration. It was a PHP 4 workaround — closures (PHP 5.3) made it completely obsolete.
Common Misconception
✗ create_function() was only a performance issue — it was a security vulnerability (eval-based) and a static analysis blocker, not just slow.
Why It Matters
create_function() was removed in PHP 8 and generates deprecation warnings in PHP 7.2+. Beyond removal, it uses eval() internally — meaning the function body is a string that gets parsed at runtime, which is a code injection vector if any part of the string comes from user input. Every use case is better served by anonymous functions (closures), which are faster, statically analysable, and support proper variable capture via use().
Common Mistakes
Using create_function() with any user-controlled content — direct RCE.
Not using Rector to automate migration to closures.
Not knowing arrow functions (fn($x) => ...) are available as a cleaner alternative.
Code Examples
✗ Vulnerable
// Deprecated + RCE risk if $code from user:
$fn = create_function('$x', 'return $x * 2;');
// Removed in PHP 8 — fatal error
🧱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().