create_function() — The Dynamic Code Smell
debt(d3/e3/b3/t7)
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.
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.
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.
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.
TL;DR
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
Why It Matters
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
// Deprecated + RCE risk if $code from user:
$fn = create_function('$x', 'return $x * 2;');
// Removed in PHP 8 — fatal error
// Closure:
$fn = function($x) { return $x * 2; };
// Arrow function (PHP 7.4+):
$fn = fn($x) => $x * 2;